FFmpeg開發筆記(三十八)APP如何訪問SRS推流的RTMP直播地址

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

SRS是一款開源流媒體伺服器,最開始是做RTMP直播的,那時全稱為“Simple RTMP Server”,意思是簡單的RTMP伺服器。後來SRS增加支援了其他流媒體協議,包括HLS、SRT、WebRTC等等,它的全稱又改為“Simple Realtime Server”,意思是簡單的實時伺服器。
有關SRS的編譯、安裝與啟動過程參見之前的文章《Linux環境安裝SRS實現影片推流》。注意,使用ffmpeg命令把影片檔案推流給SRS時,要注意區分FFmpeg的版本,因為FFmpeg從6.1開始才給RTMP協議支援HEVC、VP9、AV1這三種影片編碼器,所以FFmpeg 6.0和更早的版本只能以H.264格式向SRS推流,如下所示:

ffmpeg -re -stream_loop -1 -i "/usr/local/src/test/2018s.mp4" -vcodec h264 -f flv rtmp://127.0.0.1/live/test

而下面這種以HEVC格式(即H.265)向SRS推流的命令對於FFmpeg 6.0和更早的版本來說是錯誤的:

ffmpeg -re -stream_loop -1 -i "/usr/local/src/test/2018s.mp4" -vcodec hevc -f flv rtmp://127.0.0.1/live/test

只有把FFmpeg升級到6.1或更高版本,才能以HEVC格式把影片檔案推流給SRS。
在手機上可透過APP或者小程式播放RTMP直播流,其中小程式使用video標籤播放RTMP連結,APP除了藉助FFmpeg庫處理之外,還能使用ExoPlayer播放RTMP連結。引入ExoPlayer播放RTMP直播流的整合步驟說明如下。

一、修改build.gradle

開啟APP模組的build.gradle,在dependencies節點內部補充以下的導包配置:

implementation 'com.google.android.exoplayer:exoplayer:2.17.1'
implementation 'com.google.android.exoplayer:extension-rtmp:2.17.1'

可見以上配置不但匯入了exoplayer的主包,還匯入了rtmp的擴充套件包。

二、修改播放程式碼支援RTMP流

ExoPlayer的詳細用法參見《Android Studio開發實戰:從零基礎到App上線(第3版)》一書第14章的“14.3.3 新型播放器ExoPlayer”,其中與RTMP有關的播放程式碼方法修改如下:

// 播放影片
private void playVideo(String url) {
    DataSource.Factory factory = new DefaultDataSource.Factory(this);
    // 建立指定地址的媒體物件
    MediaItem videoItem = new MediaItem.Builder().setUri(Uri.parse(url)).build();
    // 基於工廠物件和媒體物件建立媒體來源
    MediaSource videoSource;
    if (url.endsWith("m3u8")) {  // HLS地址
        videoSource = new HlsMediaSource.Factory(factory)
                .createMediaSource(videoItem);
    } else if (url.startsWith("rtmp")) {  // RTMP地址
        videoSource = new ProgressiveMediaSource.Factory(new RtmpDataSource.Factory())
                .createMediaSource(videoItem);
    } else {
        videoSource = new ProgressiveMediaSource.Factory(factory)
                .createMediaSource(videoItem);
    }
    mPlayer.setMediaSource(videoSource); // 設定播放器的媒體來源
    mPlayer.prepare(); // 播放器準備就緒
    mPlayer.play(); // 播放器開始播放
}

可見主要改動是增加判斷RTMP地址,如果是RTMP連結就引入RtmpDataSource作為資料工廠來源。

三、調整SRS的配置檔案

透過小程式或者ExoPlayer播放RTMP直播流時,可能出現播放介面黑屏,但有聲音傳出的情況。這是因為SRS預設沒有快取關鍵幀,使得拉流一開始沒找到關鍵幀就黑屏了。
解決辦法是修改SRS配置,指定開啟快取GOP,這樣客戶端在拉流時總能找到已快取的關鍵幀。開啟srs安裝目錄下的conf/srs.conf,在“vhost __defaultVhost__”節點內部新增下面一行:

gop_cache   on;

該行配置的作用是開啟快取關鍵幀,實際應用記得設定為on,否則客戶端拉流找不到關鍵幀就無法渲染畫面。

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


相關文章