视频和视频帧:ffmpeg的RTMP推流

这篇具有很好参考价值的文章主要介绍了视频和视频帧:ffmpeg的RTMP推流。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

本文将介绍以下内容:

  • 什么是推流?将介绍推流常见的协议RTMPHLS等。
  • 怎么用ffmpeg做推流,包括cmdcode两种方式。
  • 笔者在开发推流时遇到的一些坑点。

I. 推流简介

笔者最初听到“推流”时,内心想:“这是什么高端玩意儿?”,迫于项目压力,不得不顶着压力调研和开发。经过一段时间的学习、开发和总结,笔者终于明白了推流,到底是个什么高端玩意儿?

什么是推流?

在 科普 | 直播中常说的推流拉流究竟是什么东东?中说:

推流,指的是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号传到网络的过程。

用大白话讲,推流就是把本地音视频数据通过网络上传到云端/后台服务器,所谓“采集阶段封包好”,笔者认为是未解码的H264的NALU。

推流的整个阶段如下图,本图同样摘自 科普 | 直播中常说的推流拉流究竟是什么东东?(读者请先忽略“拉流”这个名词,姑且替换为客户端用户在视频门户网站,如腾讯视频、B站等看网络在线的视频,自然也包括看直播。):

ffmpeg 推流,ffmpeg,音视频,网络

上图从“推流端”到“源站”(同上文所说到的“服务器”),再到CDN分发节点,最后到“播放端”,整个过程的视音频数据,都是压缩的数据流。也就是说,对视频数据来说,就是H264码流。解码工作是在播放端进行的。

推流的工作可想而知,最多的应用就是直播;而在大多数视频门户网站,笔者目前也很疑惑,是否存在步骤1,从效率上来说,视频数据直接存放在“源站”,通过CDN根据客户端请求下发,应该就可以了。至于具体做法,有待考证,笔者在这里姑且记一笔吧。

了解了什么是推流之后,下一个问题自然就出来了:应该怎么推流呢?这其实是一个复杂的过程,而且还需要了解”源站“,也就是推流服务器。本文仅涉及本地音视频数据通过网络上传到云端/后台服务器的本地音视频上传阶段,所以,先来了解本地的数据是怎么上传的,第一步就是了解推流的协议!

笔者了解到的几个目前常用的推流协议有:RTMP,HLS,webRTC,HTTP-FLV。本文仅介绍RTMP,原因是:笔者目前只接触了RTMP协议的推流工作。

RTMP

RTMP是Real Time Messaging Protocol(实时消息传输协议)的首字母缩写。是Adobe公司开发的一个基于TCP的应用层协议,也就是说,RTMP是和HTTP/HTTPS一样,是应用层的一个协议族。RTMP在TCP通道上一般传输的是flv 格式流。请注意,RTMP是网络传输协议,而flv则是视频的封装格式。flv封装格式设计出来的目的是为了用于网络传输使用的,因此RTMP+FLV可以说是”黄金搭档“。

RTMP协议包括:基本协议及RTMPT/RTMPS/RTMPE等多种变种。从视频协议学习:推流拉流都擅长的 RTMP了解到,RTMP协议家族有以下几个点挺有趣,读者们不妨看看:

  1. RTMP工作在TCP之上,默认使用端口1935,这个是基本形态;
  2. RTMPE在RTMP的基础上增加了加密功能;
  3. RTMPT封装在HTTP请求之上,可穿透防火墙;
  4. RTMPS类似RTMPT,增加了TLS/SSL的安全功能;
  5. RTMFP使用UDP进行传输的RTMP;

RTMP就是专门针对多媒体数据流的实时通信设计出来的一种网络数据传输协议,主要用来在Flash/AIR平台和支持RTMP协议的流媒体/交互服务器之间进行音视频和数据通信。现在Adobe公司已经不支持了,不过目前,该协议还在广泛使用。

RTMP具体如何进行握手连接、传输数据,以及其封装的数据包格式,读者都可以通过各种资料了解到,本文不再赘述。(主要原因是:笔者还没有深入了解这块知识。捂脸)

II. ffmpeg的rtmp推流

下面将介绍2种ffmpeg推流的方式:命令行(cmd)和代码(code)。

命令行(CMD)推流

ffmpeg cmd的参数实在太多,因此这里只介绍基础的、以及笔者了解的跟读者们做一个分享。

首先,来看一个将本地视频文件推流到服务器的最基础的命令:

ffmpeg -i ${input_video} -f flv rtmp://${server}/live/${streamName}
  • -i:表示输入视频文件,后跟视频文件路径/URL。
  • -f:强制ffmpeg采用某种格式,后跟对应的格式。

上文有提到,RTMP一般用flv流数据,因此多设置-f flv

接着,另一个基本需求,就是在推流的时候希望不要加上音频,这个也好实现:

ffmpeg -i ${input_video} -vcodec copy -an -f flv rtmp://${server}/live/${streamName}
  • -vcodec:指定视频解码器,v是视频videocodec就是解码器,后跟解码器名称,copy表示不作解码;
  • -acodec:指定音频解码器,同理,aaudio,后跟解码器名称。an代表acodec none就是去掉音频的意思。

关于a/v的写法很多,除了上面介绍的,还有-c:v copy -c:a copy等。

再有其他的需求,读者可自行Google。

代码(code)推流

ffmpeg的c++代码推流,网上也是一搜一大堆。笔者推荐雷神的最简单的基于FFmpeg的推流器(以推送RTMP为例),能够满足基础的推流需求。但是笔者在实际应用场景时遇到过几个case,最后总结得到一份相对鲁棒可用的code segment:

AVFormatContext *mp_ifmt_ctx = nullptr;
AVFormatContext *mp_ofmt_ctx = nullptr;
uint64_t start_timestamp; // 获取得到第一帧的时间
// ...
​
int pushStreaming(AVPacket *pkt, int frm_cnt) {
    // 做筛选:因为实际源视频文件可能包括多个音视频码流,这里只选取一路视频流m_vs_index和一路音频流m_as_index。
    if (pkt->stream_index == m_vs_index || pkt->stream_index == m_as_index) {
        // 没有pts的视频数据,如未解码的H.264裸流,需要重新计算其pts。
        if (pkt->pts == AV_NOPTS_VALUE) {
            AVRational time_base = mp_ifmt_ctx->streams[m_vs_index]->time_base;
            // Duration between 2 frames (us)
            int64_t calc_duration = (double)AV_TIME_BASE / 
                    av_q2d(mp_ifmt_ctx->streams[m_vs_index]->r_frame_rate);
            // Reset Parameters
            pkt->pts = (double)(frm_cnt * calc_duration) / 
                    (double)(av_q2d(time_base) * AV_TIME_BASE);
            pkt->dts = pkt->pts;
            pkt->duration = (double)calc_duration /
                            (double)(av_q2d(time_base) * AV_TIME_BASE);
        }
        
        // 笔者在这里省去了delay操作,读者可根据需求增加。该操作通过控制推流的速率来减轻推流服务器的压力。
        // if (pkt->stream_index == m_vs_index) {
        //     AVRational time_base = mp_ifmt_ctx->streams[m_vs_index]->time_base; 
        //     AVRational time_base_q = {1, AV_TIME_BASE}; 
        //     int64_t pts_time =  av_rescale_q(pkt->dts, time_base, time_base_q); 
        //     int64_t now_time = av_gettime() - start_timestamp;
        //     if (pts_time > now_time) {
        //         av_usleep((unsigned int)(pts_time - now_time));
        //     }
        // }
​
        //计算延时后,重新指定时间戳
        AVRational istream_base = mp_ifmt_ctx->streams[pkt->stream_index]->time_base;
        AVRational ostream_base = mp_ofmt_ctx->streams[pkt->stream_index]->time_base;
        pkt->pts = av_rescale_q_rnd(pkt->pts, istream_base, ostream_base,
                (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->dts = av_rescale_q_rnd(pkt->dts, istream_base, ostream_base,
                (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt->pts = pkt->pts < 0 ? 0 : pkt->pts;
        pkt->dts = pkt->dts < 0 ? 0 : pkt->dts;
        pkt->duration = (int)av_rescale_q(pkt->duration, istream_base, ostream_base);
        pkt->pos = -1;
        if (pkt->pts < pkt->dts) {
            return 1;
        }
        // 向推流服务器推送流数据
        int ret = av_interleaved_write_frame(mp_ofmt_ctx, pkt);
        if (ret < 0) {
            return ret;
        }
    }
    return 0;
}

III. 推流遇到的坑

笔者遇到过2个推流失败的case:

  1. 推一个RTSP摄像头的流数据时,一旦打开该摄像头的音频轨道就会在av_interleaved_write_frame()函数处出错。(返回码不记得了)
  2. 使用英飞拓某几款摄像头推流时,总是失败,返回码显示-33。

以上2个问题都成功定位问题所在:

  1. 操作人员在打开音频轨道时总是同时打开2个音频轨道,只要选择关闭其中1个音频,马上就可以推流了;
  2. 这几款摄像头同时包括多个视频码流,似乎他们会通过RTSP同时把多个码流同时传过来;最后在代码中强行过滤视音频码流,只保留一路视频+一路音频就可以了。

原因归结为一个:flv格式至多只能包括一个视频流和一个音频流

至此,笔者原以为视频封装格式就只是记录了几个无关紧要的参数的认知,完全崩塌。据笔者了解,MP4是可以同时包括多路码流的。看来多媒体/流媒体技术的水还很深呢,还有很多很多地方需要笔者去学习、踩坑、总结呢!自勉自勉。

写在后面

文章中有不严谨的地方,欢迎指摘。

 文章来源地址https://www.toymoban.com/news/detail-742972.html

原文  视频和视频帧:ffmpeg的RTMP推流 - 知乎 

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

 

到了这里,关于视频和视频帧:ffmpeg的RTMP推流的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Android-音视频学习系列-(九)Android-端实现-rtmp-推流

    Android-音视频学习系列-(九)Android-端实现-rtmp-推流

    视频画面的采集主要是使用各个平台提供的摄像头 API 来实现的,在为摄像头设置了合适的参数之后,将摄像头实时采集的视频帧渲染到屏幕上提供给用户预览,然后将该视频帧传递给编码通道,进行编码。 1. 权限配置 2. 打开摄像头 2.1 检查摄像头 public static void checkCameraSe

    2024年04月12日
    浏览(14)
  • JavaCV音视频开发宝典:使用javacv读取GB28181、海康大华平台和网络摄像头sdk回调视频码流并转码推流rtmp流媒体服务

    JavaCV音视频开发宝典:使用javacv读取GB28181、海康大华平台和网络摄像头sdk回调视频码流并转码推流rtmp流媒体服务

    《JavaCV音视频开发宝典》专栏目录导航 《JavaCV音视频开发宝典》专栏介绍和目录 本篇文章用于解决javacv接入h264/hevc裸流或者接入ps/ts流等字节流的非流媒体协议视频源接入并推流到rtmp流媒体服务。 本篇文章适用于gb28181/海康大华网络摄像机设备sdk对接以及海康大华等视频平

    2023年04月09日
    浏览(20)
  • Android-音视频学习系列-(九)Android-端实现-rtmp-推流(2)

    Android-音视频学习系列-(九)Android-端实现-rtmp-推流(2)

    配置好之后,检查一下 AudioRecord 当前的状态是否可以进行录制,可以通过 AudioRecord##getState 来获取当前的状态: STATE_UNINITIALIZED 还没有初始化,或者初始化失败了 STATE_INITIALIZED 已经初始化成功了。 2. 开启采集 创建好 AudioRecord 之后,就可以开启音频数据的采集了,可以通过调

    2024年04月12日
    浏览(11)
  • 【音视频】基于ffmpeg对视频的切割/合成/推流

    【音视频】基于ffmpeg对视频的切割/合成/推流

    基于FFmpeg对视频进行切割、合成和推流的价值和意义在于它提供了一种高效、灵活且免费的方式来实现视频内容的定制、管理和分发。通过FFmpeg,用户可以轻松地剪辑视频片段,根据需要去除不必要的部分或提取特定时间段的内容,从而优化观看体验和提高内容的价值。视频

    2024年01月18日
    浏览(29)
  • 音视频 ffmpeg命令直播拉流推流

    对于不是rtmp的协议 -c copy要谨慎使用 参数:-re,表示按时间戳读取文件 参考:Nginx搭建rtmp流媒体服务器(Ubuntu 16.04)https://www.jianshu.com/p/16741e363a77 推荐一个零声学院项目课,个人觉得老师讲得不错,分享给大家: 零声白金学习卡(含基础架构/高性能存储/golang云原生/音视频/

    2024年02月10日
    浏览(16)
  • 使用FFmpeg将本地文件通过UDP推流的音视频

    推流是指将音视频数据通过网络传输到指定的目标端,而FFmpeg是一个功能强大的跨平台多媒体处理工具,可以用于音视频编解码、转码、处理等操作。本文将介绍如何使用FFmpeg将本地文件通过UDP协议进行推流,实现音视频数据的传输。 首先,需要确保已经安装了FFmpeg工具。如

    2024年03月19日
    浏览(20)
  • Qt音视频开发42-网络推流(视频推流/本地摄像头推流/桌面推流/网络摄像头转发推流等)

    Qt音视频开发42-网络推流(视频推流/本地摄像头推流/桌面推流/网络摄像头转发推流等)

    上次实现的文件推流,尽管优点很多,但是只能对现在存在的生成好的音视频文件推流,而现在更多的场景是需要将实时的视频流重新推流分发,用户在很多设备比如手机/平板/网页/电脑/服务器上观看,这样就可以很方便的将分散的视频流统一集中的流媒体服务器上,然后统

    2024年02月03日
    浏览(11)
  • 视频和视频帧:ffmpeg的RTMP推流

    视频和视频帧:ffmpeg的RTMP推流

    本文将介绍以下内容: 什么是推流?将介绍推流常见的协议 RTMP , HLS 等。 怎么用ffmpeg做推流,包括 cmd 和 code 两种方式。 笔者在开发推流时遇到的一些坑点。 I. 推流简介 笔者最初听到“推流”时,内心想:“这是什么高端玩意儿?”,迫于项目压力,不得不顶着压力调研

    2024年02月05日
    浏览(8)
  • 【音视频】基于NGINX如何播放rtmp视频流

    【音视频】基于NGINX如何播放rtmp视频流

    现阶段直播越来越流行,直播技术发展也越来越快。Webrtc、rtmp、rtsp是比较火热的技术,而且应用也比较广泛。本文通过实践来展开介绍关于rtmp如何播放。 本文重点介绍基于NGINX如何播放rtmp视频流 可以参考上一篇博文:【音视频】基于webrtc协议浏览器播放rtsp https://blog.csdn.n

    2024年01月19日
    浏览(18)
  • 音视频开发 RTMP协议发送H.264编码及AAC编码的音视频(C++实现)

    音视频开发 RTMP协议发送H.264编码及AAC编码的音视频(C++实现)

    RTMP(Real Time Messaging Protocol)是专门用来传输音视频数据的流媒体协议,最初由Macromedia 公司创建,后来归Adobe公司所有,是一种私有协议,主要用来联系Flash Player和RtmpServer,如 FMS , Red5 , crtmpserver 等。RTMP协议可用于实现直播、点播应用,通过 FMLE(Flash Media Live Encoder) 推送音

    2023年04月08日
    浏览(16)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包