播放器功能 | MediaPlayer | ExoPlayer | IjkPlayer | RTC | TXPlayer |
---|---|---|---|---|---|
UI/Player/业务解耦 | 支持 | 支持 | 支持 | ||
切换视频播放模式 | 支持 | 支持 | 支持 | ||
视频无缝切换 | 支持 | 支持 | 支持 | ||
调节播放进度 | 支持 | 支持 | 支持 | ||
网络环境监听 | 支持 | 支持 | 支持 | ||
滑动改变亮度/声音 | 支持 | 支持 | 支持 | ||
设置视频播放比例 | 支持 | 支持 | 支持 | ||
自由切换视频内核 | 支持 | 支持 | 支持 | ||
记录播放位置 | 支持 | 支持 | 支持 | ||
清晰度模式切换 | 支持 | 支持 | 支持 | ||
重力感应自动进入 | 支持 | 支持 | 支持 | ||
锁定屏幕功能 | 支持 | 支持 | 支持 | ||
倍速播放 | 不支持 | 支持 | 支持 | ||
视频小窗口播放 | 支持 | 支持 | 支持 | ||
列表小窗口播放 | 支持 | 支持 | 支持 | ||
边播边缓存 | 支持 | 支持 | 支持 | ||
同时播放多个视频 | 支持 | 支持 | 支持 | ||
仿快手预加载 | 支持 | 支持 | 支持 | ||
基于内核无UI | 支持 | 支持 | 支持 | ||
添加弹幕 | 支持 | 支持 | 支持 | ||
全屏显示电量 | 支持 | 支持 | 支持 |
类型 | 功能说明 |
---|---|
项目结构 | VideoCache缓存lib,VideoKernel视频内核lib,VideoPlayer视频UIlib |
内核 | MediaPlayer、ExoPlayer、IjkPlayer,后期接入Rtc和TXPlayer |
协议/格式 | http/https、concat、rtsp、hls、rtmp、file、m3u八、mkv、webm、mp三、mp4等 |
画面 | 调整显示比例:默认、16:九、4:三、填充;播放时旋转画面角度(0,90,180,270);镜像旋转 |
布局 | 内核和UI分离,和市面GitHub上大多数播放器不同,方便定制,经过addView添加 |
播放 | 正常播放,小窗播放,列表播放,仿抖音播放 |
自定义 | 能够自定义添加视频UI层,能够说UI和Player高度分离,支持自定义渲染层SurfaceView |
A基础功能java
B高级功能android
C拓展功能【这块根据实际状况选择是否须要使用,通常视频付费App会有这个工鞥】git
视频常见的布局视图github
后期可能涉及的布局视图web
视频播放器的痛点算法
播放器内核难以切换api
播放器内核和UI层耦合缓存
UI难以自定义或者修改麻烦性能优化
视频播放器结构不清晰服务器
须要达到的目的和效果
通用视频框架特色
必定要解耦合
适合多种业务场景
视频分层
播放器内核
VideoPlayer播放器
UI控制器视图
以下所示
//视频UI层,必需要有 implementation 'cn.yc:VideoPlayer:3.0.1' //视频缓存,若是不须要则能够不依赖 implementation 'cn.yc:VideoCache:3.0.0' //视频内核层,必须有 implementation 'cn.yc:VideoKernel:3.0.1'
若是宽高比变形,则会有黑边
<org.yczbj.ycvideoplayerlib.player.VideoPlayer android:id="@+id/video_player" android:layout_width="match_parent" android:layout_height="240dp"/>
以下所示
//建立基础视频播放器,通常播放器的功能 BasisVideoController controller = new BasisVideoController(this); //设置控制器 mVideoPlayer.setVideoController(controller); //设置视频播放连接地址 mVideoPlayer.setUrl(url); //开始播放 mVideoPlayer.start();
若是是全屏播放,则须要在清单文件中设置当前activity的属性值
这两个变量控制全屏后和退出全屏的屏幕方向
<activity android:name=".VideoActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait"/>
如何一进入页面就开始播放视频,稍微延时一下便可
代码以下所示,注意避免直接start(),由于有可能视频尚未初始化完成……
mVideoPlayer.postDelayed(new Runnable() { @Override public void run() { mVideoPlayer.start(); } },300);
首先建立一个自定义view,须要实现InterControlView接口,重写该接口中全部抽象方法,这里省略了不少代码,具体看demo。
public class AdControlView extends FrameLayout implements InterControlView, View.OnClickListener { private ControlWrapper mControlWrapper; public AdControlView(@NonNull Context context) { super(context); init(context); } private void init(Context context){ LayoutInflater.from(getContext()).inflate(R.layout.layout_ad_control_view, this, true); } /** * 播放状态 * -1 播放错误 * 0 播放未开始 * 1 播放准备中 * 2 播放准备就绪 * 3 正在播放 * 4 暂停播放 * 5 正在缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,缓冲区数据足够后恢复播放) * 6 暂停缓冲(播放器正在播放时,缓冲区数据不足,进行缓冲,此时暂停播放器,继续缓冲,缓冲区数据足够后恢复暂停 * 7 播放完成 * 8 开始播放停止
*/ @Override public void onPlayStateChanged(int playState) { switch (playState) { case ConstantKeys.CurrentState.STATE_PLAYING: mControlWrapper.startProgress(); mPlayButton.setSelected(true); break; case ConstantKeys.CurrentState.STATE_PAUSED: mPlayButton.setSelected(false); break; } } /** * 播放模式 * 普通模式,小窗口模式,正常模式三种其中一种 * MODE_NORMAL 普通模式 * MODE_FULL_SCREEN 全屏模式 * MODE_TINY_WINDOW 小屏模式 * @param playerState 播放模式 */ @Override public void onPlayerStateChanged(int playerState) { switch (playerState) { case ConstantKeys.PlayMode.MODE_NORMAL: mBack.setVisibility(GONE); mFullScreen.setSelected(false); break; case ConstantKeys.PlayMode.MODE_FULL_SCREEN: mBack.setVisibility(VISIBLE); mFullScreen.setSelected(true); break; } //暂未实现全面屏适配逻辑,须要你本身补全 } } ```
而后该怎么使用这个自定义view呢?很简单,在以前基础上,经过控制器对象add进来便可,代码以下所示
controller = new BasisVideoController(this); AdControlView adControlView = new AdControlView(this); adControlView.setListener(new AdControlView.AdControlListener() { @Override public void onAdClick() { BaseToast.showRoundRectToast( "广告点击跳转"); } @Override public void onSkipAd() { playVideo(); } }); controller.addControlComponent(adControlView); //设置控制器 mVideoPlayer.setController(controller); mVideoPlayer.setUrl(proxyUrl); mVideoPlayer.start();
提问:针对不一样内核播放器,好比谷歌的ExoPlayer,B站的IjkPlayer,还有原生的MediaPlayer,有些api不同,那使用的时候如何统一api呢?
定义一个接口,这个接口有什么呢?这个接口定义通用视频播放器方法,好比常见的有:视频初始化,设置url,加载,以及播放状态,简单来讲能够分为三个部分。
首先定义一个工厂抽象类,而后不一样的内核播放器分别建立其具体的工厂实现具体类
如何使用,分为三步,具体操做以下所示
这种建立对象最大优势
发展中遇到的问题
UI难以自定义或者修改麻烦
视频播放器结构须要清晰
适合多种业务场景
方便播放业务发生变化
关于视频播放器
关于视频视图View
播放器player和controller交互
播放器player和view交互
如何添加自定义播放器视图
若是是在Activity中的话,建议设置下面这段代码
@Override protected void onResume() { super.onResume(); if (mVideoPlayer != null) { //从后台切换到前台,当视频暂停时或者缓冲暂停时,调用该方法从新开启视频播放 mVideoPlayer.resume(); } }
@Override protected void onPause() { super.onPause(); if (mVideoPlayer != null) { //从前台切到后台,当视频正在播放或者正在缓冲时,调用该方法暂停视频 mVideoPlayer.pause(); } } @Override protected void onDestroy() { super.onDestroy(); if (mVideoPlayer != null) { //销毁页面,释放,内部的播放器被释放掉,同时若是在全屏、小窗口模式下都会退出 mVideoPlayer.release(); } } @Override public void onBackPressed() { //处理返回键逻辑;若是是全屏,则退出全屏;若是是小窗口,则退出小窗口 if (mVideoPlayer == null || !mVideoPlayer.onBackPressed()) { super.onBackPressed(); } } ```
网络上比较好的项目:https://github.com/danikula/A...
可是存在一些问题,好比以下所示
而后看一下怎么使用,超级简单。传入视频url连接,返回一个代理连接,而后就能够呢
HttpProxyCacheServer cacheServer = ProxyVideoCacheManager.getProxy(this); String proxyUrl = cacheServer.getProxyUrl(URL_AD); mVideoPlayer.setUrl(proxyUrl); public static HttpProxyCacheServer getProxy(Context context) { return sharedProxy == null ? (sharedProxy = newProxy(context)) : sharedProxy; } private static HttpProxyCacheServer newProxy(Context context) { return new HttpProxyCacheServer.Builder(context) .maxCacheSize(512 * 1024 * 1024) // 512MB for cache //缓存路径,不设置默认在sd_card/Android/data/[app_package_name]/cache中 //.cacheDirectory() .build(); }
大概的原理
原理详细一点来讲
如何实现预加载
统一管理视频播放器封装库日志,方便后期排查问题
针对视频封装库,统一处理抛出的异常,为了方便开发者快速知道异常的来由,则能够查询约定的code码。