1、视频原理
浏览器或是音视频播放器(如ffplay、VLC、射手影音等)播放互联网上视频文件,需要对接收数据经过以下几个步骤:
解析协议-> 解封装 -> 解码音视频 -> 音视频同步。
简单起见,可将视频数据分为以下四层如下表1-1所示,可结合图1-1了解其数据流在各阶段的处理流程
层级 | 作用 |
协议层 | 处理符合特定流媒体协议规范的数据,如http、rtsp、rtmp等 |
封装格式层 | 处理符合特定格式规范的数据,如mkv、mp4、flv等 |
编解码层 | 符合特定编码标准规范的数据,如h264、h265、vp8、aac等 |
像素层 | 符合特定像素格式规范的数据,如yuv420p、yuv422p、rgb24、pem等 |
表1-1 音视频各层级协议封装格式表
图1-1 音视频数据流处理层级图
音视频流各协议层处理作用分别如下所述:
解协议
将流媒体协议的数据解析为标准的相应的封装格式数据。视音频在网络上传播的时候,常常采用各种流媒体协议,例如HTTP,RTMP,WebRTC或是MMS等等。这些协议在传输视音频数据的同时,也会传输一些信令数据。这些信令数据包括对播放的控制(播放,暂停,停止),或者对网络状态的描述等。解协议的过程中会去除掉信令数据而只保留视音频数据。例如,采用RTMP协议传输的数据,经过解协议操作后,输出FLV格式的数据。
解封装
将输入的封装格式的数据,分离成为音频流压缩编码数据和视频流压缩编码数据。封装格式种类很多,例如MP4,MKV,RMVB,TS,FLV,AVI等等,它的作用就是将已经压缩编码的视频数据和音频数据按照一定的格式放到一起。例如,FLV格式的数据,经过解封装操作后,输出H.264编码的视频码流和AAC编码的音频码流。
解码
将视频/音频压缩编码数据,解码成为非压缩的视频/音频原始数据。音频的压缩编码标准包含AAC,MP3,AC-3等等,视频的压缩编码标准则包含H.264,MPEG2,VC-1等等。解码是整个系统中最重要也是最复杂的一个环节。通过解码,压缩编码的视频数据输出成为非压缩的颜色数据,例如YUV420P,RGB等等;压缩编码的音频数据输出成为非压缩的音频抽样数据,例如PCM数据。
视音频同步
根据解封装模块处理过程中获取到的参数信息,同步解码出来的视频和音频数据,并将视频音频数据送至系统的显卡和声卡播放出来
2、系统架构
实现视频端到端播放,整个数据流经过四个组件: 推流端(ffmpeg)、播放端(浏览器)、流媒体服务器和协议转换器。具体系统架构图如下2-1所示。
图2-1 视频端到端系统架构图
3、代码实践
3.1 流媒体服务器
注意
- 构建二进制文件,需要golang环境,版本需要1.18.x以上;
- 可以关闭mediamtx原生的webrtc播放功能(webrtcDisable: yes),只提供以RTSP协议方式读取流。
$make binaries
$./mediatx
3.2 协议转换器
将以RTSP协议读取视频流并转换为WebRTC协议视频流传给浏览器。
3.3 推送端
利用ffmpeg循环读取视频流并加上时间戳,具体命令如下
$ffmpeg -re -stream_loop -1 -i oceans.mp4 -vf "settb=AVTB,\n setpts='trunc(PTS/1K)*1K+st(1,trunc(RTCTIME/1K))-1K*trunc(ld(1)/1K)',\n drawtext=fontsize=60:text='%{localtime}.%{eif\:1M*t-1K*trunc(t*1K)\:d}'" -x264-params "keyint=10:min-keyint=1" -crf 26 -c:v libx264 -an -b:v 500k -bufsize 500k -preset ultrafast -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/mystream
3.4 浏览器端
前端代码借鉴mediamtx项目内关于原生支持webrtc的前端浏览代码。
注意
- 改造websocket连接请求参数格式,通过传递topic请求参数来表征播放流的path路径
4、总结
本文重点在于阐述工程实践部分,从整体勾勒视频流端到端数据流以及简要概述相关组件的功能,而理论描述方面则简略提及视频相关协议,如RTP/RCTP、SDP、RTSP、WebRTC等,还有相关技术概念,如NAT、P2P和ICE candidate等。在实现RTSP协议转换WebRTC协议模块方面则借鉴模仿开源组件mediamtx中WebRTC服务模块处理代码,并结合开源的gortsplib库糅合而成(有待改进)。