天天看點

基于libvlc aar的android播放器執行個體

之前我在伺服器裡面已經編譯出aar包(VLC for Android編譯出AAR檔案)因為有了aar包做一些事情就簡單多了,不像以前的so庫,接口很多都要自己寫,現在基于aar包去制作自己的android播放器

參考文章:

VLC for Android編譯出AAR檔案(https://blog.csdn.net/u010735007/article/details/108141213)

基于libvlc aar的android播放器執行個體(https://blog.csdn.net/u010735007/article/details/108168267)

基于libvlc aar的android播放器(點播與本地播放)(https://blog.csdn.net/u010735007/article/details/108424493)

基于libvlc aar的android截屏和錄制視訊功能(https://blog.csdn.net/u010735007/article/details/108517985)

android,ios,linux多平台libvlc api文檔說明筆記(不斷更新)(https://blog.csdn.net/u010735007/article/details/108198711)

VLC-3.0全部詳細參數(https://blog.csdn.net/avsuper/article/details/80145439)

VLC也有自己的的例子,包括了java和native方式,下載下傳方法:git clone https://code.videolan.org/videolan/libvlc-android-samples.git

不過VLC例子的build.gradle問裡面,org.videolan.android:libvlc-all:3.1.12會編譯開始會下載下傳這個aar包,不用牆過去的話,會下載下傳很慢

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.0.2'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'org.videolan.android:libvlc-all:3.1.12'
}
           

接下來開始基于aar包去制作自己的android播放器,名稱暫定vlc-player,播放直播和點播

一.效果示範:

1.直播

基于libvlc aar的android播放器執行個體
基于libvlc aar的android播放器執行個體

2.點播

基于libvlc aar的android播放器執行個體

點播是多了進度條功能

二.apk配置注意地方:

在build.gradle裡面,配置libs的路徑,使app/libs成為項目的一部分

android {
	...
    repositories{
        flatDir{
            dirs 'libs'
        }
    }
}
           

然後去掉了自動下載下傳的aar配置,使用本地的arr

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    ...
 	//implementation 'org.videolan.android:libvlc-all:3.1.12'
    implementation(name: 'libvlc-all-3.2.6', ext: 'aar')//使用本地aar
}
           

由于包有70多M,build.gradle裡面,隻配置armeabi-v7a,x86這2個cpu類型,生成的apk隻有30多M,也相容64位的cpu。唯一比較大的問題64位的cpu的最好效果沒有發揮出來,等抽時間再裁剪一下vlc内部。

defaultConfig {
		...
        ndk {
            //選擇要添加的對應cpu類型的.so庫。
            abiFilters 'armeabi-v7a','x86'
        }
    }
           

三.apk主要代碼分析:

下面代碼段主要初始化vlc,args是vlc的參數配置,後期用的比較多。"–rtsp-tcp"是加快rtsp加載視訊速度,因為apk會應用安防的比較多,對速度和實時性要求比較高

final ArrayList<String> args = new ArrayList<>();//VLC參數
        args.add("--rtsp-tcp");//強制rtsp-tcp,加快加載視訊速度
        args.add("--live-caching=0");
        args.add("--file-caching=0");
        args.add("--network-caching=0");//增加實時性,延時大概2-3秒
        mLibVLC = new LibVLC(this, args);
        mMediaPlayer = new MediaPlayer(mLibVLC);
        mVideoLayout = findViewById(R.id.video_layout);
           

下面代碼設定播放位址和開始播放

mMediaPlayer.attachViews(mVideoLayout, null, ENABLE_SUBTITLES, USE_TEXTURE_VIEW);
		mMediaPlayer.setVideoScale(MediaPlayer.ScaleType.SURFACE_BEST_FIT);
        Uri uri = Uri.parse("http://nclive.grtn.cn/gdws/sd/live.m3u8?_upt=0704702d1598088562");//rtsp流位址或其他流位址
        final Media media = new Media(mLibVLC, uri);
        mMediaPlayer.setMedia(media);
        media.release();
        mMediaPlayer.play();
           

下面代碼段主要監聽播放器狀态,用于擴充各種應用

//監聽播放狀态
        mMediaPlayer.setEventListener(new MediaPlayer.EventListener() {
            @Override
            public void onEvent(MediaPlayer.Event event) {
                if (event.type == MediaPlayer.Event.Opening) {
                    Log.d(TAG, "VLC Opening");
                    progressBar.setVisibility(View.VISIBLE);
                }
                else if (event.type == MediaPlayer.Event.Buffering){
                    Log.d(TAG, "VLC Buffering:" + event.getBuffering());
                    if (event.getBuffering() >= 100){
                        progressBar.setVisibility(View.GONE);
                    }
                    else
                        progressBar.setVisibility(View.VISIBLE);
                }
                else if (event.type == MediaPlayer.Event.Playing){
                    Log.d(TAG, "VLC Playing");
                }
                else if (event.type == MediaPlayer.Event.Stopped){
                    Log.d(TAG, "VLC Stopped");
                    progressBar.setVisibility(View.GONE);
                }
                else if (event.type == MediaPlayer.Event.EncounteredError){
                    Log.d(TAG, "VLC EncounteredError");
                    progressBar.setVisibility(View.GONE);
                    error_text.setVisibility(View.VISIBLE);
                    error_text.setText("播放錯誤");
                }
                else if (event.type == MediaPlayer.Event.Vout){
                    Log.d(TAG, "VLC Vout"+ event.getVoutCount());
					mHandler.sendEmptyMessageDelayed(UPDATE_SCREEN, 1000);
                }
            }
        });
    }
           

重點介紹一下setAspectRatio(寬高比)的方法,vlc問題最多出現在跟據螢幕和view寬高拉伸和縮放。不配置寬高比的話,會使用MediaPlayer.ScaleType.SURFACE_BEST_FIT,具體它是怎麼best fit,不是很清楚,但是比例效果是有問題的。setAspectRatio其實很簡單就是擷取螢幕和view寬高,然後轉成字元串(寬:高)傳到這個方法就可以了,如下代碼

case UPDATE_SCREEN:
 		//frame的螢幕大小
		screen_width = frame_layout.getWidth();
		screen_height = frame_layout.getHeight();
		Log.d(TAG, "screen_width:" + screen_width + " screen_height:" + screen_height);
		mMediaPlayer.getVLCVout().setWindowSize(screen_width, screen_height);
		mMediaPlayer.setAspectRatio(screen_width + ":" + screen_height);//設定螢幕比例
		mMediaPlayer.setScale(0);
		break;
 case UPDATE_FULL_SCREEN:
		mMediaPlayer.getVLCVout().setWindowSize(full_screen_height, full_screen_width);
		mMediaPlayer.setAspectRatio(full_screen_height + ":" + full_screen_width);//設定螢幕比例
		mMediaPlayer.setScale(0);
		break;
           

還有MediaPlayer.Event.Vout應該是Video渲染view時出現監聽的狀态,設定螢幕寬高比最為合适,早了不起作用,晚了出現視訊拉伸的動畫

四.以model方式調用libvlc,提高效率:

這段時間在開發過程中發現aar有點龐大而且放到香港伺服器,編譯通過後下載下傳到本地調試很麻煩,還有vlc源代碼有些bug和一些功能沒有打開,效率特别低。是以把libvlc的代碼作為model加入播放器程式,進行調試

具體移植的過程就忽略,我的代碼裡面已經完成了,可以參考。唯一的主要是下面部分

修改app的build.gradle檔案,編譯通過即可

//implementation(name: 'libvlc-all-3.3.0-eap17', ext: 'aar')
implementation project(path: ':libvlc')
           

linux端使用compile-libvlc.sh編譯對應架構,得出so檔案進行調試即可,釋出的時候再編譯出aar

具體的代碼,大家可以下載下傳,git位址:https://gitee.com/newpoyang/vlc-player,本人喜歡用碼雲,國内伺服器比較快

如有用到此功能的朋友,可以留言交流和點贊