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