Qt音视频开发44-本地摄像头推流(支持分辨率/帧率等设置/实时性极高)

news2024/11/20 15:50:42

一、前言

本地摄像头推流和本地桌面推流类似,无非就是采集的设备源头换成了本地摄像头设备而不是桌面,其他代码完全一样。采集本地摄像头实时视频要注意的是如果设置分辨率和帧率,一定要是设备本身就支持的,如果不支持那就歇菜,比如设备本身最大分辨率到1280x720,你主动设置要采集1080x720分辨率的图像,那是采集不到的,会失败的,如果默认不设置,一般会采用640x480分辨率以及25帧率去采集。采集本地摄像头设备命令行是 ffmpeg -f dshow -i video=“USB Video Device”:audio=“麦克风 (USB Audio Device)” -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtsp rtsp://192.168.0.110:6907/stream ,可以指定带上麦克风,这样音视频都有。

采集大致步骤:

  • 查找格式 av_find_input_format,参数 dshow/v4l2/avfoundation
  • 打开桌面 avformat_open_input,参数 video=USB Video Device
  • 查找视频流 av_find_best_stream
  • 查找解码器 avcodec_find_decoder
  • 打开解码器 avcodec_open2
  • 循环读取 av_read_frame
  • 解码视频 avcodec_send_packet/avcodec_receive_frame
  • 关闭释放 avcodec_free_context/avformat_close_input

推流大致步骤:

  • 创建输出 avformat_alloc_output_context2
  • 创建视频流 avformat_new_stream
  • 打开输出 avio_open,参数填推流完整地址
  • 写入开始符 avformat_write_header
  • 写入帧数据 av_interleaved_write_frame
  • 关闭释放 avio_close/avformat_free_context

二、效果图

在这里插入图片描述

三、体验地址

  1. 国内站点:https://gitee.com/feiyangqingyun
  2. 国际站点:https://github.com/feiyangqingyun
  3. 个人作品:https://blog.csdn.net/feiyangqingyun/article/details/97565652
  4. 体验地址:https://pan.baidu.com/s/1d7TH_GEYl5nOecuNlWJJ7g 提取码:01jf 文件名:bin_video_push。

四、相关代码

void FFmpegThread::initInputFormat()
{
    //本地摄像头/桌面录屏
    if (videoType == VideoType_Camera) {
#if defined(Q_OS_WIN)
        //ifmt = av_find_input_format("vfwcap");
        ifmt = av_find_input_format("dshow");
#elif defined(Q_OS_LINUX)
        //可以打开cheese程序查看本地摄像头(如果是在虚拟机中需要设置usb选项3.1)
        //ifmt = av_find_input_format("v4l2");
        ifmt = av_find_input_format("video4linux2");
#elif defined(Q_OS_MAC)
        ifmt = av_find_input_format("avfoundation");
#endif
    } else if (videoType == VideoType_Desktop) {
#if defined(Q_OS_WIN)
        ifmt = av_find_input_format("gdigrab");
#elif defined(Q_OS_LINUX)
        ifmt = av_find_input_format("x11grab");
#elif defined(Q_OS_MAC)
        ifmt = av_find_input_format("avfoundation");
#endif
    }
}

bool FFmpegThread::initInput()
{
    //实例化格式处理上下文
    formatCtx = avformat_alloc_context();
    //设置超时回调(有些不存在的地址或者网络不好的情况下要卡很久)
    formatCtx->interrupt_callback.callback = FFmpegHelper::avinterruptCallBackFun;
    formatCtx->interrupt_callback.opaque = this;

    //打开输入(通过标志位控制回调那边做超时判断)
    //其他地方调用 formatCtx->url formatCtx->filename 可以拿到设置的地址(两个变量值一样)
    tryOpen = true;
    QByteArray urlData = VideoHelper::getRightUrl(videoType, videoUrl).toUtf8();
    int result = avformat_open_input(&formatCtx, urlData.data(), ifmt, &options);
    tryOpen = false;
    if (result < 0) {
        debug("打开出错", "错误: " + FFmpegHelper::getError(result));
        return false;
    }

    //根据自己项目需要开启下面部分代码加快视频流打开速度
    //开启后由于值太小可能会出现部分视频流获取不到分辨率
    if (decodeType == DecodeType_Fastest && videoType == VideoType_Rtsp) {
        //接口内部读取的最大数据量(从源文件中读取的最大字节数)
        //默认值5000000导致这里卡很久最耗时(可以调小来加快打开速度)
        formatCtx->probesize = 50000;
        //从文件中读取的最大时长(单位为 AV_TIME_BASE units)
        formatCtx->max_analyze_duration = 5 * AV_TIME_BASE;
        //内部读取的数据包不放入缓冲区
        //formatCtx->flags |= AVFMT_FLAG_NOBUFFER;
        //设置解码错误验证过滤花屏
        //formatCtx->error_recognition |= AV_EF_EXPLODE;
    }

    //获取流信息
    result = avformat_find_stream_info(formatCtx, NULL);
    if (result < 0) {
        debug("找流失败", "错误: " + FFmpegHelper::getError(result));
        return false;
    }

    //解码格式
    formatName = formatCtx->iformat->name;
    //某些格式比如视频流不做音视频同步(响应速度快)
    if (formatName == "rtsp" || videoUrl.endsWith(".sdp")) {
        useSync = false;
    }

    //设置了最快速度则不启用音视频同步
    if (decodeType == DecodeType_Fastest) {
        useSync = false;
    }

    //有些格式不支持硬解码
    if (formatName.contains("rm") || formatName.contains("avi") || formatName.contains("webm")) {
        hardware = "none";
    }

    //本地摄像头设备解码出来的直接就是yuv显示不需要硬解码
    if (videoType == VideoType_Camera || videoType == VideoType_Desktop) {
        useSync = false;
        hardware = "none";
    }

    //过低版本不支持硬解码
#if (FFMPEG_VERSION_MAJOR < 3)
    hardware = "none";
#endif

    //获取文件时长(这里获取到的是秒)
    double length = (double)formatCtx->duration / AV_TIME_BASE;
    duration = length * 1000;
    this->checkVideoType();

    //有时候网络地址也可能是纯音频
    if (videoType == VideoType_FileHttp) {
        onlyAudio = VideoHelper::getOnlyAudio(videoUrl, formatName);
    }

    if (getIsFile()) {
        //文件必须要音视频同步
        useSync = true;
        //发送文件时长信号
        emit receiveDuration(duration > 0 ? duration : 0);
    }

    QString msg = QString("格式: %1 时长: %2 秒 加速: %3").arg(formatName).arg(duration / 1000).arg(hardware);
    debug("媒体信息", msg);
    return true;
}

五、功能特点

5.1 文件推流

  1. 指定网卡和监听端口,接收网络请求推送音视频等各种文件。
  2. 实时统计显示每个文件对应的访问数量、总访问数量、不同IP地址访问数量。
  3. 可指定多种模式,0-直接播放、1-下载播放。
  4. 实时打印显示各种收发请求和应答数据。
  5. 每个文件对应MD5加密的唯一标识符,用于请求地址后缀区分访问哪个文件。
  6. 支持各种浏览器(谷歌chromium/微软edge/火狐firefox等)、各种播放器(vlc/mpv/ffplay/potplayer/mpchc等)打开请求。
  7. 播放过程中可以任意切换播放进度,支持倍速播放。
  8. 需要推流的文件名称历史记录自动存储和打开加载应用。
  9. 切换文件获取访问地址,自动拷贝地址到剪切板方便直接粘贴测试使用。
  10. 极低CPU占用,128路1080P同时推流不到1%CPU占用,异步发送数据机制。
  11. 纯QTcpSocket通信,不依赖流媒体服务程序,核心源码不到500行,注释详细,功能完整。
  12. 支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。

5.2 网络推流

  1. 支持各种本地视频文件和网络视频文件。
  2. 支持各种网络视频流,网络摄像头,协议包括rtsp、rtmp、http。
  3. 支持将本地摄像头设备推流,可指定分辨率和帧率等。
  4. 支持将本地桌面推流,可指定屏幕区域和帧率等。
  5. 自动启动流媒体服务程序,默认mediamtx(原rtsp-simple-server),可选用srs、EasyDarwin、LiveQing、ZLMediaKit等。
  6. 可实时切换预览视频文件。
  7. 推流的清晰度和质量可调。
  8. 可动态添加文件、目录、地址。
  9. 视频文件自动循环推流,如果视频源是视频流,在掉线后会自动重连。
  10. 网络视频流自动重连,重连成功自动继续推流。
  11. 网络视频流实时性极高,延迟极低,延迟时间大概在100ms左右。
  12. 推流后除了用rtmp地址访问以外,还支持直接hls/webrtc访问,可以直接浏览器打开看实时画面。
  13. 支持Qt4/Qt5/Qt6任意版本,支持任意系统(windows/linux/macos/android/嵌入式linux等)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/491624.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常规项目风险识别的规范流程和方法

一、识别风险输入 识别项目风险&#xff0c;首先需要对项目管理计划、项目文件、协议、采购文档、事业环境因素、组织过程资产等进行风险识别。 项目管理计划是指&#xff1a;需求、进度、成本、质量、资源、风险等管理计划以及范围基准、进度基准、成本基准。而项目文件指&…

普通2本,去过字节外包,到现在年薪25W+的测试开发,我的2年转行心酸经历...

个人简介 我是一个普通二本大学机械专业毕业&#xff0c;17年毕业&#xff0c;19年转行&#xff0c;目前做IT行业的软件测试已经有3年多&#xff0c;职位是高级测试工程师&#xff0c;坐标上海… 我想现在我也有一点资格谈论关于转行这个话题&#xff1b;希望你在决定转行之前…

Python爬虫-xpath方法爬虫技术分享,更高效,代码简洁!

这里写目录标题 一、获取文档树对象二、文本转化文档树对象文件转化文档树对象节点、元素、属性、内容路径表达式通配符谓语多个路径函数实战信息 ↓ ↓ ↓ 加下方名片找我&#xff0c;直接拿源码还有案例 ↓ ↓ ↓ 一、获取文档树对象 通过Xpath 获取文档的对象&#xff0c;获…

matlab定义函数

1新建文件 首先建立M文件或直接点击&#xff08;File/New/Function)建立函数文件&#xff0c;其中函数文件的格式是&#xff1a; function [输出变量] 函数名称(输入变量&#xff09; % 注释 % 函数体 2函数语法 2.1基本语法 function yf(x) %函数的声明 yx^2 就是建立了一个y…

边框虚线滚动动画特效

边框线条效果如上 /*边框虚线滚动动画特效*/.border-animate {background: linear-gradient(90deg, gray 60%, transparent 60%) repeat-x left top/10px 1px,linear-gradient(0deg, gray 60%, transparent 60%) repeat-y right top/1px 10px,linear-gradient(90deg, gray 60%,…

今天面了一个来字节要求月薪23K,明显感觉他背了很多面试题...

最近有朋友去字节面试&#xff0c;面试前后进行了20天左右&#xff0c;包含4轮电话面试、1轮笔试、1轮主管视频面试、1轮hr视频面试。 据他所说&#xff0c;80%的人都会栽在第一轮面试&#xff0c;要不是他面试前做足准备&#xff0c;估计都坚持不完后面几轮面试。 其实&…

用于2.4GHz ISM频段FHSS解决方案的射频IC

比较了 WLAN 和相关系统。IEEE802.11b FHSS 支持 1.6Mbps 数据传输。MAX2644 SiGe LNA用作2.5GHz频段的PA驱动器和接收器低噪声放大器&#xff08;LNA&#xff09;。MAX2240和MAX2242功率放大器&#xff08;PA&#xff09;产生~20dBm输出&#xff0c;具有所需的线性度。MAX2754…

EasyRecovery15Mac中文电脑版安装详细操作教程

EasyRecovery是一款操作安全、恢复性比较高的数据恢复工具&#xff0c;小伙伴们可以使用EasyRecovery恢复各种各样被删除的文件、视频、图片等。EasyRecovery还可以支持恢复被格式化的媒体文件&#xff0c;只是使用EasyRecovery恢复时时间较久。如果小伙伴们有误删除的文件需要…

第三十三章 Unity Mecanim动画系统(下)

本章节&#xff0c;我们继续讲解Unity的 Mecannim 动画系统。在上一章节中&#xff0c;我们设置了动画过渡&#xff0c;但是还没有为这些动画过渡设置过渡条件。这个过渡条件需要在“Animator”窗口中设置。这个窗口的左边是用来编辑“动画层”和“动画参数”的。这里的“动画参…

Redis的20种使用场景

本文介绍Redis除了缓存以外的使用场景。 测试源码&#xff1a;https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-011-redis 1缓存 本文假定你已经了解过Redis&#xff0c;并知晓Redis最基础的一些使用&#xff0c;如果你对Redis的基础API还不了解&#xff…

Kubernetes服务搭建[配置-部署](Kubeadm)

文章目录 **[1 — 7] ** [ 配置K8S主从集群前置准备操作 ]一&#xff1a;主节点操作 查看主机域名->编辑域名1.1 编辑HOST 从节点也做相应操作1.2 从节点操作 查看从节点102域名->编辑域名1.3 从节点操作 查看从节点103域名->编辑域名 二&#xff1a;安装自动填充&…

Android - 动画

一、概念 补间动画 ViewAnimation&#xff08;Tween&#xff09;&#xff1a;不改变view的位置和属性。属性动画PeopertyAnimation&#xff1a;view的属性根据执行的动画发生真实的改变。帧动画 DrawableAnimation&#xff08;Frame&#xff09;&#xff1a; 二、补间动画 Vi…

SPSS如何进行使用时间序列模型之案例实训?

文章目录 0.引言1.时间序列数据平稳处理2.指数平滑法建模3.ARIMA建模4.季节性分解 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对SPSS进行了学习&#xff0c;本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结&#xff0c;本文对…

MYSQL用户组管理

1&#xff1a;使用明文密码创建用户 使用密文密码创建用户 1.2 查看用户信息 1.3 重命名用户 rename 1.4 删除用户信息 drop 1.5 修改当前登录用户的密码 set password password(123456); 1.6 修改其他用户的密码 set password for nancylocalhost password(abc123); 1.7…

2023年常见的20道JavaScript面试题及其答案解析,你知道多少

JavaScript中typeof操作符有哪些返回值&#xff1f; 答案&#xff1a;typeof操作符返回字符串数据类型。可能的返回值有&#xff1a;“undefined”、“boolean”、“number”、“string”、“object"和"function”。如何检查一个变量是否为数组&#xff1f; 答案&…

【JavaEE】Thread类

目录 前言 1、创建一个线程 1.1、 体会多线程的执行 1.2、体会单线程的执行 1.3、sleep方法&#xff08;休眠&#xff09; 1.4、通过第三方程序来观察线程详情 1.5、创建线程的方式 1.5.1、继承Thread类&#xff0c;重写run方法来创建线程 1.5.2、实现Runnable接口&am…

linux 查看系统版本

文章目录 一、查看Linux内核版本的命令二、查看Linux系统发行版本的命令三、 延伸&#xff1a; 一、查看Linux内核版本的命令 cat /proc/version 此命令可以查看正在运行的内核版本信息。/proc 目录存储的是当前内核运行状态的一系列特殊文件&#xff0c;包括&#xff1a;内存…

electron源码保护

electron 程序发布后&#xff0c;如果未对程序做保护&#xff0c;则极容易受到破坏&#xff0c;比如被轻松破解密码&#xff0c;或者被修改程序&#xff0c;所以必须对程序做一些安全防护。虽然没有100%的安全防护&#xff0c;但是提升破解难度&#xff0c;直至破解代价超出了范…

UML图中的domain model,object model,system sequence diagram以及interaction diagram

UML图&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;是一种用于描述、可视化、构建和记录软件系统的标准化建模语言。在UML中&#xff0c;有很多类型的图&#xff0c;其中包括领域模型&#xff08;Domain Model&#xff09;、对象模型&#xff08…

拥抱智能时代:初探RFID系统

在数字化时代&#xff0c;人们越来越追求高效率和高质量的体验&#xff0c;以获得更快乐、更好的生活。RFID系统作为一项智能化管理技术&#xff0c;正越来越广泛地应用于各个领域&#xff0c;以提高效率和质量。本文将介绍RFID系统的基本概念、工作原理和实际应用案例&#xf…