本文介紹Android播放器SDK在使用過程中的常見問題及解決方案。
License相關問題
如果需要同時使用短視頻SDK和播放器SDK,AndroidManifest.xml
中的License key應該如何配置?
如果既申請了短視頻SDK的License,又申請了播放器SDK的License,則只需要在AndroidManifest.xml
中配置最后一個申請的License即可。
報錯License is invalid!!!
問題現(xiàn)象:使用5.4.7.1及之后版本的播放器時,出現(xiàn)如下報錯。
解決方法:
請先確認您是否已申請License授權并在已配置License,5.4.7.1及之后版本播放器SDK需要配置License之后才能正常使用,具體操作,請參見License說明。
請確認您配置的License是否正確,判斷方法請參見如何判斷License是否正確。
如何判斷License是否正確?
如何獲取當前播放進度
播放器SDK默認每500 ms回調一次播放進度。您可以修改回調間隔時間,通過將間隔時間縮短,以更高頻率地獲取當前播放進度,示例代碼如下:
//修改回調間隔
PlayerConfig config = mAliyunLivePlayer.getConfig();
config.mPositionTimerIntervalMs = 100;//回調間隔時間,單位:ms。
mAliyunLivePlayer.setConfig(config);
mAliPlayer.setOnInfoListener(new IPlayer.OnInfoListener() {
@Override
public void onInfo(InfoBean infoBean) {
if(infoBean.getCode() == InfoCode.CurrentPosition){
//當前播放進度
long currentPosition = infoBean.getExtraValue();
}
}
});
創(chuàng)建播放器時發(fā)生crash
可通過以下步驟排查問題產生原因:
檢查CPU架構是否為x86架構。
播放器SDK目前僅支持arm64-v8a架構和armeabi-v7a架構,不支持x86架構。
檢查項目中是否混合集成了播放器SDK相關的.so和Maven依賴。
例如:在build.gradle中通過Maven依賴集成了播放器SDK,又在項目的Module中l(wèi)ibs相關目錄下也集成了播放器相關的動態(tài)庫。
解決方案推薦:如果存在混用的情況,建議刪除動態(tài)庫,使用Maven方式依賴。如果必須要集成動態(tài)庫,則請排查播放器SDK相關的.so文件是否統(tǒng)一(需要保證是同一個版本下的.so文件)。播放器SDK的集成操作及動態(tài)庫獲取,請參見快速集成。播放器相關的動態(tài)庫如下圖所示:
如果集成的是part包,請確認AlivcFFmpeg的版本依賴是否正確。
AlivcFFmpeg的版本依賴信息請參見AlivcFFmpeg版本依賴。
播放器運行過程中發(fā)生crash
可通過以下步驟排查問題產生原因:
確認crash是否產生在播放器SDK。
查看是否有帶
AliyunPlayer
前綴的崩潰堆棧,如果有,則說明問題產生在播放器SDK。升級至最新版播放器SDK并驗證,確認問題是否已經修復。
如果問題依然存在,請準備相關的崩潰文件(包含全部線程)、崩潰日志、崩潰場景等信息,如何獲取問題日志。
播放視頻時畫面有黑邊
可通過以下步驟排查問題產生原因:
檢查視頻源本身是否存在黑邊問題。
可通過如下接口調節(jié)播放器的縮放模式。
/* SCALE_ASPECT_FILL:按比例填充,畫面會有裁剪。 SCALE_ASPECT_FIT:按比例縮放,會有黑邊。 SCALE_TO_FILL:不按比例填充,畫面會變形。 */ mAliPlayer.setScaleMode();
若縮放模式依然無法滿足需求,則可以在應用層調節(jié)SurfaceView/TextureView的大小。
播放視頻時有聲音無畫面
可通過以下步驟排查問題產生原因:
使用其他播放器播放,檢查視頻是否是純音頻。
確認渲染視頻的View設置是否有異常,例如沒有給播放器設置顯示View,或者顯示View被移出播放界面。設置顯示View的方法請參見創(chuàng)建播放器的步驟4。
播放已獲取讀取權限的本地視頻時報錯Invalid argument
當播放已獲取讀取權限的本地視頻時報錯Invalid argument,建議檢查一下文件名稱和文件絕對路徑,避免路徑中出現(xiàn)中文和空格混雜的情況。
播放已獲取讀取權限的本地視頻時報錯Permission denied
因Android系統(tǒng)從Android 10(Android Q)版本開始引入了分區(qū)儲存特性,需要在AndroidManifest.xml
的application標簽下新增android:requestLegacyExternalStorage="true"
后,才能正常使用Android設備的存儲權限。
全屏播放時劉海屏閃現(xiàn)一個黑色通知欄
可以通過設置為沉浸式的狀態(tài)欄解決。
播放MOV視頻失敗
Android播放器SDK支持MOV格式的視頻。如果播放MOV視頻失敗,可考慮是否由源視頻的moov(音視頻數(shù)據(jù)索引)在mdat(音視頻數(shù)據(jù))之后造成,可通過轉碼源視頻將moov移到mdat之后解決。更多信息,請參見步驟二:排查流。
初始化或播放視頻時報錯找不到播放器SDK的.so動態(tài)庫
可通過以下步驟排查問題產生原因:
檢查CPU架構是否滿足要求。
播放器SDK目前僅支持arm64-v8a架構和armeabi-v7a架構的動態(tài)庫。
檢查播放器SDK的版本是否過低。
如果播放器SDK版本是5.4.6.0-full或者更低的版本,建議升級到5.4.6.0-full-15467853或者更高的版本。播放器SDK的最新及歷史版本請參見Android播放器SDK。
使用列表播放器AliListPlayer播放HLS(m3u8)視頻報錯
V5.4.5.0及之前版本的播放器SDK不支持使用列表播放器AliListPlayer
播放HLS(m3u8)格式的視頻。從V5.4.5.0之后版本開始支持播放HLS(m3u8)格式的視頻,但是需要開啟本地緩存,開啟本地緩存的方法請參見本地緩存。
使用Android播放器SDK是否支持播放Android工程中assets和raw文件夾下的視頻?
不支持。需要您將視頻拷貝到手機存儲中,然后使用絕對路徑來播放視頻。
播放HLS視頻流并配置本地緩存后,播放失敗報錯403
問題現(xiàn)象:當以VidAuth播放方式,播放HLS(M3U8)協(xié)議的視頻流時,開啟本地緩存后,出現(xiàn)播放失敗并報錯403。
問題原因:由于開啟本地緩存后,如果在沒有充分緩存的狀態(tài)下退出播放,當下一次起播時,未緩存的部分因仍然使用上一次過期的Vid鑒權信息請求,從而導致鑒權失敗報錯403。
處理方法:針對5.5.4.0及以后版本的播放器SDK,如果視頻播放URL帶有鑒權參數(shù)且播放協(xié)議為HLS,可以通過設置PlayerConfig.mEnableStrictAuthMode
字段,進行不同鑒權模式的選擇(默認值為false)。
非嚴格鑒權(false):鑒權也緩存,若上一次只緩存了部分媒體,下次播放至非緩存部分時,播放器會用緩存的鑒權發(fā)起請求,如果URL鑒權設置的有效期很短,會導致播放異常。
嚴格鑒權(true):鑒權不緩存,每次起播都進行鑒權,無網絡下會導致起播失敗。
Android播放器SDK是否支持邊下載邊播放?
不支持。Android播放器SDK支持在播放的過程中通過開啟本地緩存功能緩存下載視頻文件,下次再播放時,直接播放緩存好的視頻文件;目前不支持將放在文件目錄下的本地緩存視頻文件單獨拿出來進行播放。
Android播放器SDK是否支持獲取播放視頻的緩沖速度?
支持。Android播放器SDK支持獲取緩沖速度、實時渲染幀率、音視頻碼率、網絡下行碼率等,詳細說明請參見獲取播放信息。
HDR視頻播放異常
Android播放器SDK暫不支持帶旋轉角度的HDR視頻,因此播放此類視頻時會有異常。
seek相關問題
seek后,進度條異常回跳
問題原因:播放器默認使用不精準seek。seek后播放器會從seek點附近的關鍵幀開始播放。
解決方法:切換為精準seek模式。
如何切換精準seek和非精準seek模式
切換seek模式的示例代碼如下:
//非精準seek。
mAliPlayer.seekTo(1000);
mAliPlayer.seekTo(1000, IPlayer.SeekMode.Inaccurate);
//精準seek。
mAliPlayer.seekTo(1000,IPlayer.SeekMode.Accurate);
使用精準seek模式后,進度條也會異常回跳
問題原因:由于精準seek耗時比非精準seek耗時更長,當seek點距離關鍵幀間隔過大,超過精準seek的最大間隔時,播放器SDK會自動切換成非精準seek,導致進度條回跳。
解決方法:可以通過接口設置精準seek的最大間隔,將精準seek的最大間隔調大,降低精準seek被切換成非精準seek的頻率,以提高seek精準度,但當seek的點距離關鍵幀間隔太長時,耗時也將更長,請根據(jù)業(yè)務特點合理設置精準seek的最大間隔。示例代碼如下:
//單位:ms。
mAliPlayer.setMaxAccurateSeekDelta(1000);
緩存相關問題
使用邊播邊緩存(CacheConfig)時緩存失敗
可以在onInfo回調中,獲取緩存失敗的原因。onInfo回調的示例代碼如下:
mAliPlayer.setOnInfoListener(new IPlayer.OnInfoListener() {
@Override
public void onInfo(InfoBean infoBean) {
if(infoBean.getCode() == InfoCode.CacheSuccess){
//邊播邊緩存成功
}else if(infoBean.getCode() == InfoCode.CacheError){
//邊播邊緩存失敗
String error = infoBean.getExtraMsg();
}
}
});
常見的失敗原因如下:
CacheConfig中設置的大小和時長與視頻不匹配導致緩存失敗。
在播放過程中,stop或者seek到buffer外導致緩存失敗。
播放器SDK V5.4.4.0版本,新增支持的預加載和本地緩存能力,可以完全替代邊播邊緩存的使用場景。建議使用新增加的本地緩存能力,更多內容請參見進階功能。
本地緩存,緩存目錄是否可以指定到內部存儲目錄
可以指定。您可以將Android設備的外部存儲目錄換成內部存儲目錄,請確保內部存儲目錄有訪問權限即可正常緩存。
視頻緩存時報錯encrypt check fail
緩存即下載,如果設置了安全下載,請確認加密校驗文件與App信息是否匹配(即需要將離線下載中生成的加密校驗文件下載并保存到播放器SDK中,詳細內容請參見視頻下載),否則會導致緩存或下載失敗。
獲取音視頻源數(shù)據(jù)
解碼方式需要切換為軟解碼,并且播放不加密的視頻,才會返回音視頻的原始數(shù)據(jù)。示例代碼如下:
//切換到軟解碼。
mAliPlayer.enableHardwareDecoder(false);
IPlayer.RenderFrameCallbackConfig renderFrameCallbackConfig = new IPlayer.RenderFrameCallbackConfig();
//是否只返回底層視頻數(shù)據(jù)地址,默認為true。
renderFrameCallbackConfig.mVideoDataAddr = false;
//是否只返回底層音頻數(shù)據(jù)地址,默認為false。
renderFrameCallbackConfig.mAudioDataAddr = false;
mAliPlayer.setRenderFrameCallbackConfig(renderFrameCallbackConfig);
mAliPlayer.setOnRenderFrameCallback(new IPlayer.OnRenderFrameCallback() {
@Override
public boolean onRenderFrame(FrameInfo frameInfo) {
return false;
}
});
獲取視頻寬高
您可以通過以下三種方式獲取視頻寬高:
阿里云播放器AliPlayer實例執(zhí)行完prepare方法后,至少確保處于準備完成狀態(tài)后,通過如下方法獲取:
mAliyunPlayer.setOnPreparedListener(new IPlayer.OnPreparedListener() { @Override public void onPrepared() { mAliyunPlayer.getVideoWidth(); mAliyunPlayer.getVideoHeight(); } });
監(jiān)聽視頻大小變化回調方法:
mAliyunPlayer.setOnVideoSizeChangedListener(new IPlayer.OnVideoSizeChangedListener() { @Override public void onVideoSizeChanged(int width, int height) { } });
通過track方式獲取:
mAliyunPlayer.setOnTrackReadyListener(new IPlayer.OnTrackReadyListener() { @Override public void onTrackReady(MediaInfo mediaInfo) { List<TrackInfo> trackInfos = mediaInfo.getTrackInfos(); for (TrackInfo trackInfo : trackInfos) { if(trackInfo.getType() == TrackInfo.Type.TYPE_VIDEO){ trackInfo.getVideoWidth(); trackInfo.getVideoHeight(); } } } });
自動碼率切換邏輯
當開啟自動碼率切換,即調用了mAliPlayer.selectTrack(TrackInfo.AUTO_SELECT_INDEX)
接口后,播放器SDK內部會統(tǒng)計當前網速,當10秒內網速達到下一個碼率時,就會切換到下一個碼率。若10秒內網速未達到下一個碼率,則不切換。
從高碼率切換到低碼率的場景,當10秒內網速達到下一個碼率時,會將已緩存的高碼率內容播放完成后才切換。
從低碼率切換到高碼率的場景,當10秒內網速達到下一個碼率時,會直接切換。
自動碼率切換,首先需要在控制臺轉碼為自適應流,然后指定播放器獲取自適應流。以VidAuth播放方式為例,示例如下:
VidAuth vidAuth = new VidAuth();
List<Definition> list = new ArrayList<>();
list.add(Definition.DEFINITION_AUTO);
vidAuth.setDefinition(list);
自定義重試邏輯
在網絡重試場景下,播放器SDK默認重試次數(shù)為2次,網絡超時時間為15秒,當重試失敗后會觸發(fā)Error回調。
可以自定義重試邏輯,當觸發(fā)重試時,將重試事件通知到外部,由外部決定具體的重試邏輯。示例代碼如下:
PlayerConfig config = mAliPlayer.getConfig();
//1.設置重試次數(shù),此處以設置為0為例。
config.mNetworkRetryCount = 0;
mAliPlayer.setConfig(config);
mAliPlayer.setOnInfoListener(new IPlayer.OnInfoListener() {
@Override
public void onInfo(InfoBean infoBean) {
//2.監(jiān)聽retry事件。
if(infoBean.getCode() == InfoCode.NetworkRetry){
//TODO做相應的邏輯處理。
}
}
});
播放RTS流時,報錯協(xié)議不支持
可通過以下步驟排查報錯原因:
檢查3個SDK(AliyunPlayer、AlivcArtc、Rts)是否全部都已集成。
使用阿里云播放器播放RTS流,需要集成3個SDK:AliyunPlayer、AlivcArtc、Rts。集成操作可參見阿里云播放器SDK集成Native RTS SDK實現(xiàn)說明。
檢查Native RTS SDK(Rts)和阿里云播放器SDK(AliyunPlayer)的版本是否配套。
Native RTS SDK和阿里云播放器SDK有版本配套關系,需要集成對應的版本,版本配套關系請參見SDK下載。
檢查AliyunPlayer和AlivcArtc的版本是否一致,需保持一致。
集成Native RTS SDK后,需要手動加載。
load RtsSDK:System.loadLibrary("RtsSDK");
可選:經上述步驟排查驗證后,若仍然報錯。請在AndroidManifest.xml文件中或在app/build.gradle文件的
android{}
閉包中,配置android:extractNativeLibs="true"
,示例代碼如下:packagingOptions { jniLibs { useLegacyPackaging true } }
縮略圖使用
在播放器SDK中使用縮略圖前,請確保已為視頻配置縮略圖,即視頻已生成雪碧截圖(在視頻點播控制臺創(chuàng)建類型為雪碧圖的截圖模板,通過工作流將視頻用該雪碧圖的截圖模板處理后,生成雪碧圖數(shù)據(jù)),詳細內容請參見視頻截圖。播放器SDK中使用縮略圖的示例代碼如下:
mAliPlayer.setOnPreparedListener(new IPlayer.OnPreparedListener() {
@Override
public void onPrepared() {
//1.獲取縮略圖URL。
List<Thumbnail> thumbnailList = mAliPlayer.getMediaInfo().getThumbnailList();
//2.創(chuàng)建縮略圖幫助類。
ThumbnailHelper mThumbnailHelper = new ThumbnailHelper(thumbnailList.get(0).mURL);
//3.設置監(jiān)聽。
mThumbnailHelper.setOnPrepareListener(new ThumbnailHelper.OnPrepareListener() {
@Override
public void onPrepareSuccess() {
//5.縮略圖加載成功后,可以請求獲取指定位置的縮略圖。
mThumbnailHelper.requestBitmapAtPosition(1000);
}
@Override
public void onPrepareFail() {}
});
mThumbnailHelper.setOnThumbnailGetListener(new ThumbnailHelper.OnThumbnailGetListener() {
@Override
public void onThumbnailGetSuccess(long positionMs, ThumbnailBitmapInfo thumbnailBitmapInfo) {
//6.獲取指定位置縮略圖的Bitmap。
Bitmap thumbnailBitmap = thumbnailBitmapInfo.getThumbnailBitmap();
}
@Override
public void onThumbnailGetFail(long positionMs, String errorMsg) {}
});
//4.加載縮略圖。
mThumbnailHelper.prepare();
}
});
請注意:如果播放方式為URL的時候,AliPlayer 可能并不能獲取到ThumbnailList,建議用戶直接指定縮略圖的URL。
mAliPlayer.setOnPreparedListener(new IPlayer.OnPreparedListener() {
@Override
public void onPrepared() {
//1.創(chuàng)建縮略圖幫助類。
ThumbnailHelper mThumbnailHelper = new ThumbnailHelper(URL);
//2.設置監(jiān)聽。
mThumbnailHelper.setOnPrepareListener(new ThumbnailHelper.OnPrepareListener() {
@Override
public void onPrepareSuccess() {
//4.縮略圖加載成功后,可以請求獲取指定位置的縮略圖。
mThumbnailHelper.requestBitmapAtPosition(1000);
}
@Override
public void onPrepareFail() {}
});
mThumbnailHelper.setOnThumbnailGetListener(new ThumbnailHelper.OnThumbnailGetListener() {
@Override
public void onThumbnailGetSuccess(long positionMs, ThumbnailBitmapInfo thumbnailBitmapInfo) {
//5.獲取指定位置縮略圖的Bitmap。
Bitmap thumbnailBitmap = thumbnailBitmapInfo.getThumbnailBitmap();
}
@Override
public void onThumbnailGetFail(long positionMs, String errorMsg) {}
});
//3.加載縮略圖。
mThumbnailHelper.prepare();
}
});
清晰度相關問題
視頻轉碼了多個清晰度,播放器SDK默認會播放視頻的哪個清晰度?
默認清晰度播放順序:FD、LD、SD、HD、2K、4K、OD,清晰度的定義請參見清晰度:Definition。播放器SDK會從左到右依次查找,找到哪個清晰度就播放哪個清晰度。
如何指定視頻播放默認清晰度?
示例代碼如下:
//以VidSts播放方式為例
VidSts vidSts = new VidSts();
//設置vid、AccessKeyId、AccessKeySecret、token等參數(shù)的代碼此處省略,可參見基礎功能文檔中的創(chuàng)建播放器設置。
/*
參數(shù)1:期望播放的清晰度,取值為FD、LD、SD、HD、2K、4K、OD。
參數(shù)2:是否強制使用期望播放的清晰度播放。false:不強制使用期望的清晰度播放,按播放器SDK的默認清晰度播放順序查找播放;true:強制使用設置的期望清晰度播放,如果找不到期望播放的清晰度就不播放。
*/
vidSts.setQuality("",false);
如果同一個清晰度有多個碼流,播放器SDK會播放哪個碼流?
當同一個清晰度有多個碼流時,播放器SDK會播放最新的碼流。
如何設置同一個視頻,在播放時無水印,下載后帶水印?
將視頻轉碼多個清晰度,播放時播放無水印的清晰度,下載時下載有水印的清晰度。
如何獲取問題日志
當您向阿里云獲取技術支持時,請將您的問題日志一并提交,以便更高效地為您解決問題。問題日志的獲取方法如下:
獲取問題日志。
建議將日志級別設置為
AF_LOG_LEVEL_TRACE
后再獲取問題日志。具體方法請參見獲取SDK日志。將生成的日志提供給阿里云技術支持。