FFmpeg開發筆記(四十二)使用ZLMediaKit開啟SRT影片直播服務

aqi00發表於2024-07-28
《FFmpeg開發實戰:從零基礎到短影片上線》一書在第10章介紹了輕量級流媒體伺服器MediaMTX,透過該工具可以測試RTSP/RTMP等流媒體協議的推拉流。不過MediaMTX的功能實在是太簡單了,無法應用於真實直播的生產環境,真正能用於生產環境的流媒體伺服器還要看SRS或者ZLMediaKit。

ZLMediaKit是一款國產的開源流媒體伺服器,支援RTSP、RTMP、SRT等主流直播協議,它的安裝說明參見之前的文章《Linux環境安裝ZLMediaKit實現影片推流》。結合ZLMediaKit與ffmpeg實現RTSP/RTMP協議的推流功能,已在《Linux環境安裝ZLMediaKit實現影片推流》一文中詳細介紹,這裡單獨講解如何透過ZLMediaKit與ffmpeg實現SRT協議的推流功能。
ZLMediaKit在編譯和啟動的時候已經預設支援SRT,檢視ZLMediaKit的配置檔案config.ini,找到srt部分的配置資訊如下,可見ZLMediaKit預設把9000埠分配給SRT協議。

[srt]
latencyMul=4
pktBufSize=8192
port=9000
timeoutSec=5

除此以外,ZLMediaKit無需另外調整什麼配置,只要在啟動之後執行下面的ffmpeg命令即可將影片檔案向SRT地址推流。注意,務必確保Linux伺服器上的FFmpeg已經整合了libsrt庫,否則ffmpeg無法向srt地址推流,詳細的整合步驟參見之前的文章《Linux環境給FFmpeg整合libsrt和librist》。

ffmpeg -re -stream_loop -1 -i "/usr/local/src/test/cctv5.ts" -c copy -f mpegts 'srt://127.0.0.1:9000?streamid=#!::r=live/test,m=publish'

注意,上面命令中的srt地址後半段為“r=live/test,m=publish”,其中“r=live/test”表示SRT的服務名稱叫做“live/test”,而“m=publish”表示該地址屬於釋出功能也就是給推流方使用。
ZLMediaKit對影片原始檔的封裝格式也有要求,不僅要求原始檔為ts格式,還要求推流格式也為ts格式,所以ffmpeg命令中新增了“-f mpegts”表示轉換成mpeg的ts流格式。如果原始檔不是ts格式,或者沒轉成mpegts格式,後續透過ffplay播放srt連結都會報下面的錯誤。

non-existing PPS 0 referenced

此外,ZLMediaKit支援的音影片編碼標準羅列在src/Extension/Frame.h中,詳細的音影片支援標準如下所示。

#define CODEC_MAP(XX) \
    XX(CodecH264,  TrackVideo, 0, "H264", PSI_STREAM_H264, MOV_OBJECT_H264)          \
    XX(CodecH265,  TrackVideo, 1, "H265", PSI_STREAM_H265, MOV_OBJECT_HEVC)          \
    XX(CodecAAC,   TrackAudio, 2, "mpeg4-generic", PSI_STREAM_AAC, MOV_OBJECT_AAC)   \
    XX(CodecG711A, TrackAudio, 3, "PCMA", PSI_STREAM_AUDIO_G711A, MOV_OBJECT_G711a)  \
    XX(CodecG711U, TrackAudio, 4, "PCMU", PSI_STREAM_AUDIO_G711U, MOV_OBJECT_G711u)  \
    XX(CodecOpus,  TrackAudio, 5, "opus", PSI_STREAM_AUDIO_OPUS, MOV_OBJECT_OPUS)    \
    XX(CodecL16,   TrackAudio, 6, "L16", PSI_STREAM_RESERVED, MOV_OBJECT_NONE)       \
    XX(CodecVP8,   TrackVideo, 7, "VP8", PSI_STREAM_VP8, MOV_OBJECT_VP8)             \
    XX(CodecVP9,   TrackVideo, 8, "VP9", PSI_STREAM_VP9, MOV_OBJECT_VP9)             \
    XX(CodecAV1,   TrackVideo, 9, "AV1", PSI_STREAM_AV1, MOV_OBJECT_AV1)             \
    XX(CodecJPEG,  TrackVideo, 10, "JPEG", PSI_STREAM_JPEG_2000, MOV_OBJECT_JPEG)

由此可見,如果待推流的影片檔案不屬於上面的音影片編碼標準,將無法透過SRT服務地址正常推流。
執行ffmpeg的SRT推流命令之後,ZLMediaKit輸出以下的日誌資訊,可見其SRT推流功能正常執行。

[MediaServer] [576478-event poller 0] SrtSession.cpp:103 onRecv | 1-11(127.0.0.1:33630) 
[MediaServer] [576478-event poller 0] SrtTransportImp.cpp:166 operator() | test(127.0.0.1:33630) 允許 srt 推流
[MediaServer] [576478-event poller 0] Decoder.cpp:143 onTrack | Got track: H264
[MediaServer] [576478-event poller 0] Decoder.cpp:143 onTrack | Got track: mpeg4-generic
[MediaServer] [576478-event poller 0] Decoder.cpp:97 onStream | Add track finished
[MediaServer] [576478-event poller 0] MediaSink.cpp:161 emitAllTrackReady | All track ready use 172ms
[MediaServer] [576478-event poller 0] MediaSource.cpp:517 emitEvent | 媒體註冊:fmp4://__defaultVhost__/live/test
[MediaServer] [576478-event poller 0] MultiMediaSourceMuxer.cpp:551 onAllTrackReady | stream: schema://__defaultVhost__/app/stream , codec info: mpeg4-generic[48000/2/16] H264[1280/720/25] 
[MediaServer] [576478-event poller 0] MediaSource.cpp:517 emitEvent | 媒體註冊:rtmp://__defaultVhost__/live/test
[MediaServer] [576478-event poller 0] MediaSource.cpp:517 emitEvent | 媒體註冊:rtsp://__defaultVhost__/live/test
[MediaServer] [576478-event poller 0] MediaSource.cpp:517 emitEvent | 媒體註冊:ts://__defaultVhost__/live/test
[MediaServer] [576478-event poller 0] MediaSource.cpp:517 emitEvent | 媒體註冊:hls://__defaultVhost__/live/test

接著按照《FFmpeg開發實戰:從零基礎到短影片上線》一書“1.3 Windows系統安裝FFmpeg”的介紹,在個人電腦上安裝FFmpeg並開啟MSYS的命令列,執行下面的ffplay命令,期望從SRT地址拉流播放。注意,務必確保電腦上的FFmpeg已經整合了libsrt庫,否則ffplay無法播放srt連結,詳細的整合步驟參見之前的文章《Windows環境給FFmpeg整合libsrt》。

ffplay -i 'srt://124.xxx.xxx.xxx:9000?streamid=#!::r=live/test,m=request'

上面的SRT拉流地址與之前的推流地址大同小異,除了把內網IP換成外網IP之外,就是把連結末尾的“m=publish”改成了“m=request”,其中request表示請求也就是用於拉流方。
ffplay執行後彈出播放器視窗,正常播放影片畫面和聲音。同時觀察ZLMediaKit的服務日誌如下所示:

[MediaServer] [576478-event poller 0] SrtSession.cpp:103 onRecv | 2-16(112.5.138.145:57022) 
[MediaServer] [576478-event poller 0] SrtTransport.cpp:731 onShutdown | peer close connection
[MediaServer] [576478-event poller 0] SrtSession.cpp:118 onError | 2-16(112.5.138.145:57022) 6(peer close connection)
[MediaServer] [576478-event poller 0] SrtTransportImp.cpp:14 ~SrtTransportImp | test(112.5.138.145:57022) srt 播放器(__defaultVhost__/live/test)斷開,耗時(s):16

從以上日誌可見,ZLMediaKit透過SRT協議成功實現了影片直播的SRT推拉流功能。

更多詳細的FFmpeg開發知識參見《FFmpeg開發實戰:從零基礎到短影片上線》一書。

相關文章