rtp,对于它的实现ffmpeg和gstreamer。对于这种复杂协议,实现肯定会有不同和妥协。
下面都是用命令窗口操作。命令换行(\
on Linux, ^
on Windows),环境变量访问 ($NAME
or ${NAME}
on Linux, %NAME%
on Windows).
先理解概念 转码:
由于发送端和接收端需要的文件格式不一致,需要:
1)解码媒体,成raw格式和信息部分;2)编码raw格式用不同的编码器codec。
上图有个mkv文件,音频OPUS,视频是vp8.转码成视频h264,音频MP3,然后用mp4 container封装。
我们用rtp是不用封装到container的。
FFmpeg
ffmpeg \ [global_options] \ { [input_options] -i input_url } \ { [output_options] output_url }
命令是有序的,一般是上面这个结构。
RTP流命令概览
ffmpeg \ -re \ -i video.mp4 \ -an \ -c:v copy \ -f rtp \ -sdp_file video.sdp \ "rtp://192.168.1.109:5004"
参数意义:
-re
: 模拟直播流,慢速推;否则ffmpeg会尽快发送完成.-i video.mp4
: Input file.-an
: 输出不要音频.-c:v copy
: 视频不转码,直接拷贝输出.-f rtp
: 输出格式,rtp。如果想保存成文件,直接写文件名,会根据后缀猜测转成的类型.-sdp_file video.sdp
: 生成sdp文件,这个文件能拷贝给另外一个去播放.rtp://192.168.1.109:5004
: 输出的url.
添加音频 -c:a copy
("copy audio"), 有下面报错:
[rtp @ 0x6fec300] Only one stream supported in the RTP muxer
BUG:
事实上,生成的sdp文件多了行
SDP:
需要去掉:sed -i '/^SDP:/d' video.sdp
FFmpeg ≥ 4.3没有这个问题。
附加特性:
RTCP端口设定:
ffmpeg -re -i video.mp4 -an -c:v copy -f rtp -sdp_file video.sdp \ "rtp://192.168.1.109:5004?rtcpport=54321"
但是ffmpeg有个bug,生成的sdp里面不包含这个
rtcpport=54321
端口的生成,需要手动加上。
Symmetric RTP
ffmpeg -re -i video.mp4 -an -c:v copy -f rtp -sdp_file video.sdp \ "rtp://192.168.1.109:5004?rtcpport=5005&localrtpport=5004&localrtcpport=5005"
可以inspect这个口的rtp和rtcp包。
RTP and RTCP multiplexing
不支持
Timestamps 纠正
ffmpeg \ -re \ -fflags +genpts \ -i video.mp4 \ -an \ -c:v copy \ -f rtp \ -sdp_file video.sdp \ "rtp://192.168.1.109:5004"
输入时转码
-c:v vp8 替换 copy
注意用htop去看cpu从0.7%到转码飙升到10-55%
播放 RTP流
由于 dynamic Payload Types的使用,必须用sdp文件播放,没有工具用rtp播放的。
FFmpeg playback
ffplay \ -protocol_whitelist file,rtp,udp \ -i video.sdp
GStreamer playback
安装:
sudo apt-get update && sudo apt-get install --yes \ gstreamer1.0-plugins-{good,bad,ugly} \ gstreamer1.0-{libav,tools}
播放:
gst-launch-1.0 playbin uri="sdp://$PWD/video.sdp"
等价于命令
gst-launch-1.0 \ filesrc location=video.sdp \ ! sdpdemux timeout=0 ! queue \ ! rtph264depay ! h264parse ! avdec_h264 \ ! videoconvert ! autovideosink