上一篇文章介紹了如何通過ZLMediaKit實現視頻推拉流,并使用VLC播放器驗證視頻直播地址。即使不用VLC播放器,直接在Qt工程的C++代碼中調用FFmpeg的API,也能訪問ZLMediaKit的直播地址,并正常渲染視頻畫面。關于如何在Qt工程中引入FFmpeg,可參考《FFmpeg開發實戰:從零基礎到短視頻上線》一書的“第11章 ?FFmpeg的桌面開發”。
《FFmpeg開發實戰:從零基礎到短視頻上線》一書的“第12章 ?FFmpeg的移動開發”介紹了如何在手機APP上集成FFmpeg。根據該書的操作步驟,在APP工程的JNI代碼中調用FFmpeg的API,也能正常播放ZLMediaKit的直播畫面。
但是如果手機APP不走FFmpeg,通過其他途徑訪問直播地址之時,卻發現無法播放ZLMediaKit的HLS直播地址http://124.***.***.***:8080/live/test/hls.m3u8。無論采用谷歌官方的ExoPlayer,還是采用微信小程序的video標簽,都播放不了ZLMediaKit的HLS視頻。查看APP的報錯日志,發現ExoPlayer扔出以下的錯誤信息:
E/ExoPlayerImplInternal: Playback errorcom.google.android.exoplayer2.ExoPlaybackException: Source errorat com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:641)at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:613)at android.os.Handler.dispatchMessage(Handler.java:105)at android.os.Looper.loopOnce(Looper.java:206)at android.os.Looper.loop(Looper.java:296)at android.os.HandlerThread.run(HandlerThread.java:67)Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 401at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:396)at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:258)at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)at com.google.android.exoplayer2.source.hls.HlsMediaChunk.prepareExtraction(HlsMediaChunk.java:495)at com.google.android.exoplayer2.source.hls.HlsMediaChunk.feedDataToExtractor(HlsMediaChunk.java:468)at com.google.android.exoplayer2.source.hls.HlsMediaChunk.loadMedia(HlsMediaChunk.java:437)at com.google.android.exoplayer2.source.hls.HlsMediaChunk.load(HlsMediaChunk.java:394)at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)at java.lang.Thread.run(Thread.java:930)
原來是流媒體服務端丟出了401錯誤,意思是沒有權限拒絕訪問。這個問題著實難搞,尋尋覓覓、反反復復,總也找不到為啥會沒有權限,分明使用VLC播放器是可以正常播放的呀。
于是檢查ZLMediaKit的源代碼,發現ZLMediaKit內部對于HTTP地址增加了Cookie校驗,原來這套校驗規則適配了FFmpeg,卻尚未適配ExoPlayer,也未適配小程序。那么修改ZLMediaKit源代碼的src/Http/HttpFileManager.cpp,把accessFile函數中的401鑒權代碼注釋掉,并將修改后的代碼文件上傳到Linux服務器。
然后回到build目錄運行make和make install命令重新編譯安裝ZLMediaKit,也就是依次執行下面命令。
kill -s 9 `ps -aux | grep MediaServer | awk '{print $2}'`
cd /usr/local/src/ZLMediaKit/build
make
make install
編譯安裝完畢,執行下面命令,重新啟動MediaServer服務。
cd /usr/local/src/ZLMediaKit/release/linux/Debug
./MediaServer -d &
執行以下命令,將本地視頻推流給ZLMediaKit。
ffmpeg -re -stream_loop -1 -i "/usr/local/src/test/2018s.mp4" -vcodec h264 -f rtsp rtsp://127.0.0.1/live/test
然后在APP代碼中使用ExoPlayer播放HLS地址http://124.***.***.***:8080/live/test/hls.m3u8,發現可以正常播放HLS視頻了。接著使用真機調試微信小程序,發現通過video標簽也能正常播放HLS視頻了。更多詳細的FFmpeg開發知識參見《FFmpeg開發實戰:從零基礎到短視頻上線》一書。