ijkplayer中遇到的問題彙總

在做音頻播放的時候,很多公司使用的是開源的ijkplayer播放器,ijkplayer底層是基於ffmpeg,在某機型上面可能常常遇到各種問題。今天整理了大家在使用ijkplayer中遇到的問題,以及根據ijkplayer社區issue和solution方案。如下:

1、直播技術總結(三)ijkplayer的一些問題優化記錄https://blog.csdn.net/hejjunlin/article/details/57075026

2、視頻直播技術(四):使用Ijkplayer播放直播視頻https://www.cnblogs.com/renhui/p/6420140.html

3、IJKPlayer問題集錦之不定時更新- https://www.jianshu.com/p/220b00d00deb

4、直播技術總結(三)ijkplayer的一些問題優化記錄- http://blog.csdn.net/hejjunlin/article/details/57075026

5、ijkplayer rtmp秒開ijkplayer設置rtmp秒開,可以讓rtmp加載時間從5~10秒縮短到1s以內,以達到秒開且低延遲的目的:

<code>IjkMediaPlayer ijkMediaPlayer = null;  
ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.setOption(1, "analyzemaxduration", 100L);
ijkMediaPlayer.setOption(1, "probesize", 10240L);
ijkMediaPlayer.setOption(1, "flush_packets", 1L);
ijkMediaPlayer.setOption(4, "packet-buffering", 0L);
ijkMediaPlayer.setOption(4, "framedrop", 1L);
/<code>

6、ijkplayer實時播放rtmp等實時性要求很高的流媒體時候,會出現10S左右的延遲,原因是因為加了緩衝區處理,可以把其緩存設置變小,達到實時的效果:

<code>ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 0);  
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 8);
ijkMediaPlayer.setOption(1, "analyzemaxduration", 100L);
ijkMediaPlayer.setOption(1, "probesize", 10240L);
ijkMediaPlayer.setOption(1, "flush_packets", 1L);
ijkMediaPlayer.setOption(4, "packet-buffering", 0L);
ijkMediaPlayer.setOption(4, "framedrop", 1L);
/<code>

7、快速起直播流:直播技術總結(五)如何快速起播直播流- http://blog.csdn.net/hejjunlin/article/details/72860470這裡優化後者,主要修改兩個參數,一個是probesize,一個是analyzeduration,分別用來控制其讀取的數據量大小和時長。減少 probesize 和 analyzeduration 可以降低avformat_find_stream_info的函數耗時,達到起播快

<code>ijkMediaPlayer.setOption(1,"analyzemaxduration",xxx);
ijkMediaPlayer.setOption(1,"probesize",xxx);
/<code>

8、卡頓優化和秒開,弱網優化

  • ijkplayer 解決rtmp 延遲長的問題,達到秒開的結果- https://blog.csdn.net/yyhjifeng/article/details/71191950
  • ijkplayer直播播放器使用經驗之談-卡頓優化和秒開實現- https://blog.csdn.net/cmshao/article/details/80149176

9、ijkplayer丟幀的處理方案https://www.jianshu.com/p/ecf51ee32589直播的延遲,如果延遲過大,可以採取兩種策略,一種是丟幀,一種是追幀。我們可以考慮丟音頻包來實現,音頻包不不在關鍵幀的問題,丟起來比較好操作,然後因為視頻同步到音頻,所以視頻會追幀,也會跟上來。

10、使用Ijkplayer倍速變調問題解決方案- https://www.cnblogs.com/renhui/p/6510872.html

<code>public void setSpeed(float speed) {
_setPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, speed);
}
public float getSpeed(float speed) {
return _getPropertyFloat(FFP_PROP_FLOAT_PLAYBACK_RATE, .0f);
}
/<code>

11、ijkPlayer中的錯誤碼:

<code>IJKMEDIA: SDL_JNI_DetachThreadEnv
ijkplayer如何斷掉握手 Android ? ijkplayer如何釋放連接 Android ?
/*
* Do not change these values without updating their counterparts in native
*/

int MEDIA_INFO_UNKNOWN = 1;//未知信息
int MEDIA_INFO_STARTED_AS_NEXT = 2;//播放下一條
int MEDIA_INFO_VIDEO_RENDERING_START = 3;//視頻開始整備中,準備渲染
int MEDIA_INFO_VIDEO_TRACK_LAGGING = 700;//視頻日誌跟蹤
int MEDIA_INFO_BUFFERING_START = 701;//開始緩衝中 開始緩衝
int MEDIA_INFO_BUFFERING_END = 702;//緩衝結束
int MEDIA_INFO_NETWORK_BANDWIDTH = 703;//網絡帶寬,網速方面
int MEDIA_INFO_BAD_INTERLEAVING = 800;//
int MEDIA_INFO_NOT_SEEKABLE = 801;//不可設置播放位置,直播方面
int MEDIA_INFO_METADATA_UPDATE = 802;//
int MEDIA_INFO_TIMED_TEXT_ERROR = 900;
int MEDIA_INFO_UNSUPPORTED_SUBTITLE = 901;//不支持字幕
int MEDIA_INFO_SUBTITLE_TIMED_OUT = 902;//字幕超時
int MEDIA_INFO_VIDEO_INTERRUPT= -10000;//數據連接中斷,一般是視頻源有問題或者數據格式不支持,比如音頻不是AAC之類的
int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//視頻方向改變,視頻選擇信息
int MEDIA_INFO_AUDIO_RENDERING_START = 10002;//音頻開始整備中
int MEDIA_ERROR_SERVER_DIED = 100;//服務掛掉,視頻中斷,一般是視頻源異常或者不支持的視頻類型。
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//數據錯誤沒有有效的回收
int MEDIA_ERROR_IO = -1004;//IO 錯誤
int MEDIA_ERROR_MALFORMED = -1007;
int MEDIA_ERROR_UNSUPPORTED = -1010;//數據不支持
int MEDIA_ERROR_TIMED_OUT = -110;//數據超時
Error (-10000,0)
/<code>

12、ijkplayer 使用經驗:

a、IJKPlayer 不像系統播放器會給你旋轉視頻角度,所以你需要通過onInfo的what == IMediaPlayer.MEDIA_INFO_VIDEO_ROTATION_CHANGED去獲取角度,自己旋轉畫面;或者開啟硬解硬解碼,不過硬解碼容易造成黑屏無聲,諸位慎重啊O__O "…。

<code>mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
mediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1);
/<code>

b、IJKPlayer 出現黑色有聲音沒圖像,看看你的視頻編碼是不是H264,pixel format是否存在,音頻編碼是不是AAC?默認IJKPlayer是不支持3pg(支持它幹啥(?-?*)?),不支持mepg(比如這個庫RecordVideoDemo ),不支持AMR。所以如果你真的想要支持,那麼參考這個#1961,打開mpeg支持,重新編ffmpeg,然後通過硬解碼播放mpeg;或者通過系統的錄製VideoRecord;或者選另外的JAVACV錄製封裝FFmpegRecorder。

<code>ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec_mpeg4", 1);
/<code>

c、快進和慢放接口,只支持API23以上,23以下的支持,是需要自己配置ffmpeg支持avfilter,不過可能會出現聲音顫抖等問題,官方說不穩定,參考#1690。Tryavfilter but the audio sounds shaking = = For avfilter, only support software decoder.

d、暫停的時候,退到後臺再回到前臺,畫面黑了?這時候個人處理方式是,可以在暫停的時候,通過TextureView.getBitmap(point.x, point.y);獲取到暫停的畫面,用ImageView顯示它,在onSurfaceTextureUpdated的時候隱藏ImageView,來實現畫面的銜接。

e、一些視頻返回碼

<code>int MEDIA_INFO_VIDEO_RENDERING_START = 3;//視頻準備渲染
int MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK = 200;//數據錯誤沒有有效的回收
int MEDIA_INFO_BUFFERING_START = 701;//開始緩衝
int MEDIA_INFO_BUFFERING_END = 702;//緩衝結束

int MEDIA_INFO_VIDEO_ROTATION_CHANGED = 10001;//視頻選擇信息
int MEDIA_ERROR_SERVER_DIED = 100;//視頻中斷,一般是視頻源異常或者不支持的視頻類型。
int MEDIA_ERROR_IJK_PLAYER = -10000,//一般是視頻源有問題或者數據格式不支持,比如音頻不是AAC之類的
MediaPlayer Error (-10000,0), 視頻播放過程中出錯了,可能是視頻的原因,播放器內部錯誤
/<code>

f、某些視頻在SeekTo的時候,會跳回到拖動前的位置,這是因為視頻的關鍵幀的問題,通俗一點就是FFMPEG不兼容,視頻壓縮過於厲害,seek只支持關鍵幀,出現這個情況就是原始的視頻文件中i 幀比較少,播放器會在拖動的位置找最近的關鍵幀,目前麼,IJKPlayer無解。

g、下載速度可以通過IjkMediaPlayer的getTcpSpeed獲取。

h、高分辨率開啟硬解碼,不支持的話會自動切換到軟解,就算開啟mediacodec,如果設備不支持,顯示的解碼器也是avcodec軟解。

i、ijkMediaPlayer.setOption可配置的對應頭文件參考:ff_ffplay_options。

j、緩衝進度條不到100,官方表示我就不保證都100,所以一般我都是://95這個數值可能不準確,有些時候可能還需要低一些if (secProgress > 95) secProgress = 100;

k、上面a、b、f的問題,在IJK封裝的EXOPlayer和MediaPlayer都不會有問題,兼容上確實強過IJKPlayer,但是它們在細節上,卻沒有IJK處理的好,如EXOPlayer:退到後再回到前臺、切換渲染控件的黑屏一段時間問題,除了用seekto之外目前沒發現其他辦法,這樣的體驗讓我最後還是選擇IJKPlayer。

l、設置cookie 可以通過ijkPlayer的public void setDataSource(String path, Mapheaders) 的header實現設置,參考ijkPlayer的issues-1150,headers也是在內部被轉化為何issuses一樣的setOption方法。

13、ijkplayer常見問題以及解決方案

a、ijkplayer播放rtmp直播流,延遲明顯- https://github.com/Bilibili/ijkplayer/issues/210b、全屏播放c、有時候會開始直播時出現黑屏d、有時候會出現花屏e、解碼方式設置f、如何區分點播直播g、是否需要開啟硬件加速h、How to set up only listen to the sound does not show video?- https://github.com/Bilibili/ijkplayer/issues/1074i、如何設置後臺播放j、視頻加載速度慢The traffic speed is mostly depending on the quality of video CDN, not player itself.k、怎麼靜音 和非靜音mute/unmute system volume.There is no mute/unmute API in ijkplayer.l、視頻黑屏,但是有聲音確定下視頻源的編碼方式,ijk默認只帶了h264解碼codem、適配問題,對於不同的cpu架構,需要編譯不同的so庫n、播放視頻有的設備聲畫不同步o、如何查看m3u8時長

<code> cat game05.m3u8 | grep EXTINF | wc -l 32
p、how to change the video quality?
Video quality is determined when being encoded.I don’t think it can be changed by player.
/<code>

q、為什麼往前拖動進度條後,還會往後退幾秒seek只支持關鍵幀,出現這個情況就是原始的視頻文件中i 幀比較少,播放器會在拖動的位置找最近的關鍵幀。r、how to change URL when ijkplayer is playing RTMP videoCreate new player.s、怎樣添加字幕呢?如果希望字幕時間精確,可以在native層做解析和時間同步,到了時間後回調給java層,一般字幕文件加載都是在java層做的,解析文件格式,然後按照時間區間來顯示。t、如何設置硬解?

<code>ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, “mediacodec”, 1); 

ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "http-detect-range-support", 0);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "overlay-format", IjkMediaPlayer.SDL_FCC_RV32);
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "analyzeduration", "2000000");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "probsize", "4096");
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 0);
/<code>

u、http重定向到rtmp/Https,ijkplayer無法播放視頻

<code>ijkMediaPlayer.setOption( IjkMediaPlayer.OPT_CATEGORY_FORMAT, "dns_cache_clear", 1);
/<code>

v、android mediaPlayer error (-38,0) prepare()調用報錯解決辦法:出現這個錯誤發現在mediaPlayer.reset()後調用了mediaPlayer.getDuration()在沒有給mediaPlayer對象設置數據源之前,是不能使用getDuration等這些方法的.需要檢查一下在設置MediaPlayer的數據源時,使用的是那種方式:

  • 1、在初始化MediaPlayer時,通過create方法設置數據源。則不能寫MediaPlayer.prepare()方法,這時,會報錯。
  • 2、如果是使用MediaPlayer構造函數初始化MediaPlayer,然後通過setDataSource方法設置數據源時,就需要在start()之前,使用MediaPlayer.prepare()方法,對數據源進行一次編譯。能夠避免出現(-38,0)這種錯誤。

https://blog.csdn.net/shareus/article/details/78585260

https://github.com/Bilibili/ijkplayer/issues

ijkplayer中遇到的問題彙總

歡迎關注我的微信公眾號「碼農突圍」,分享Python、Java、大數據、機器學習、人工智能等技術,關注碼農技術提升•職場突圍•思維躍遷,20萬+碼農成長充電第一站,陪有夢想的你一起成長。


分享到:


相關文章: