# YCVideoPlayer
**Repository Path**: CoderZone/YCVideoPlayer
## Basic Information
- **Project Name**: YCVideoPlayer
- **Description**: 视频播放器封装库案例,仿照优酷,爱奇艺视频播放器,可以添家视频观看权限,试看模式,类似优酷试看功能。基于ijkplayer,支持网络视频或者本地视频播放,滑动调节亮度或者音量,快进快退,记录播放位置。可以设置边观看变缓存,支持全屏播放,小窗口,正常播放等模式;还支持列表播放,切换分辨率,还可以自定义视频播放器,拓展性强
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 87
- **Created**: 2020-04-15
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
#### **目录介绍**
- **1.关于此视频封装库介绍**
- 1.1 能够满足那些业务需求
- 1.2 对比同类型的库有哪些优势
- **2.关于使用方法说明**
- 2.1 关于gradle引用说明
- 2.2 添加布局
- 2.3 最简单的视频播放器参数设定
- 2.4 注意的问题
- 2.5 关于开源库中的类说明
- 2.6 暴露接口让用户实现返回键和登录和购买会员点击事件逻辑
- **3.关于播放类型说明**
- 3.1 普通视频播放
- 3.2 list页面视频播放
- 3.3 小窗口视频播放
- 3.4 类似爱奇艺,优酷会员试看视频播放
- 3.5 关于封装库中日志打印
- **4.关于相关方法说明**
- 4.1 关于VideoPlayer类[播放器]中方法说明
- 4.2 关于VideoPlayerController类[控制器]中方法说明
- 4.3 关于对象的销毁
- **5.关于封装的思路**
- 5.1 参考的案例思路
- 5.2 封装的基本思路
- 5.3 关于窗口切换分析
- 5.4 关于VideoPlayerManager视频播放器管理器分析
- 5.5 关于VideoPlayerController视频控制器分析
- 5.6 关于InterVideoPlayer接口分析
- **6.关于如何自定义你想要的视频播放模式**
- 6.1 自定义视频播放器
- **7.关于效果图的展示**
- 7.1 效果图如下所示
- **8.关于遇到的问题说明**
- 8.1 视频难点
- 8.2 遇到的bug
- 8.3 后期需要实现的功能
- **9.关于版本更新说明**
- 9.1 V1.0.0 更新于2017年9月4日
- 9.2 V1.0.1 更新于2017年11月18日
- 9.3 v1.1.0 更新于2018年1月15日
- 9.4 v1.1.1 更新于2018年1月18日
- **10.关于参考文档说明**
- 10.1 参考的项目
- 10.2 参考的博客
- **11.关其他说明**
- 11.1 目前市场流行的视频框架
- 11.2 如何选择合适的框架
- 11.3 关于我的个人博客和站点
### 0.备注
- 仿照爱奇艺,优酷播放器写的,十分感谢GitHub上大神前辈们的开源案例和思路。
- 支持插入广告,设置视频观看权限,观看完后登录或者购买会员。我看到在star较多的项目issues中,有些人正好需要这个案例,库集成后直接通过代码调用即可,灵活且拓展性强。
- 由于调到做视频的部门,因此此部分代码会持续更新,也欢迎同行提bug或者问题
- 如果你觉得还可以,给个star吧!我也在持续学习中!!!
- 项目地址:https://github.com/yangchong211/YCVideoPlayer
### 1.关于此视频封装库介绍
#### 1.1 能够满足那些业务需求
> **A基础功能**
>
- 1.1.1 能够自定义视频加载loading类型,设置视频标题,设置视频底部图片,设置播放时长等基础功能
- 1.1.2 可以切换播放器的视频播放状态,播放错误,播放未开始,播放开始,播放准备中,正在播放,暂停播放,正在缓冲等等状态
- 1.1.3 可以自由设置播放器的播放模式,比如,正常播放,全屏播放,和小屏幕播放。其中全屏播放支持旋转屏幕。
- 1.1.4 可以支持多种视频播放类型,比如,原生封装视频播放器,还有基于ijkplayer封装的播放器。
- 1.1.5 可以设置是否隐藏播放音量,播放进度,播放亮度等,可以通过拖动seekBar改变视频进度。还支持设置n秒后不操作则隐藏头部和顶部布局功能
-
> **B高级功能**
>
- 1.1.6 支持一遍播放一遍缓冲的功能,其中缓冲包括两部分,第一种是播放过程中缓冲,第二种是暂停过程中缓冲
- 1.1.7 基于ijkplayer的封装播放器,支持多种格式视频播放
- 1.1.8 可以设置是否记录播放位置,设置播放速度,设置屏幕比例
- 1.1.9 支持滑动改变音量【屏幕右边】,改变屏幕亮度【屏幕左边】,支持切换视频清晰度模式
- 1.1.0 支持list页面中视频播放,滚动后暂停播放,播放可以自由设置是否记录状态。并且还支持删除视频播放位置状态。
-
> **C拓展功能**
>
- **C1产品需求:类似优酷,爱奇艺视频播放器部分逻辑。比如如果用户没有登录也没有看视频权限,则提示试看视频[自定义布局];如果用户没有登录但是有看视频权限,则正常观看;如果用户登录,但是没有充值会员,部分需要权限视频则进入试看模式,试看结束后弹出充值会员界面;如果用户余额不足,比如余额只有99元,但是视频观看要199元,则又有其他提示。**
- C2自身需求:比如封装好了视频播放库,那么点击视频上登录按钮则跳到登录页面;点击充值会员页面也跳到充值页面。这个通过定义接口,可以让使用者通过方法调用,灵活处理点击事件。
- C.1.1 实现了上面两个需求,灵活可拓展性强。
- C.1.2 对于设置视频的宽高,建议设置成4:3或者16:9或者常用比例,如果不是常用比例,则可能会有黑边。其中黑边的背景可以设置
- C.1.3 可以设置播放有权限的视频时的各种文字描述,而没有把它写在封装库中,使用者自己设定
- C.1.4 锁定屏幕功能
-
> **D待添加功能**
>
- D.1.1 可以支持屏幕截图功能,视频添加水印效果
- D.1.2 支持弹幕功能
- D.1.3 后期待定
#### 1.2 对比同类型的库有哪些优势
> **1.2.1目前仅仅查了下GitHub上项目**
>
- 目前GitHub上比较流行的库
- 至于官方库就不说了,jiecao的库是基于ijkplayer视频框架,目前封装库有许多,下面几个只是star比较多,其中jiecao库比较类似。
```
ijkplayer官方库
https://github.com/Bilibili/ijkplayer
Vitamio官方库
https://github.com/yixia/VitamioBundle
以jiecao为例的封装库
https://github.com/JasonChow1989/JieCaoVideoPlayer-develop 2年前
https://github.com/open-android/JieCaoVideoPlayer 1年前
https://github.com/lipangit/JiaoZiVideoPlayer 4个月前
https://github.com/CarGuo/GSYVideoPlayer
其他库
https://github.com/danylovolokh/VideoPlayerManager
```
-
> **1.2.2 具有的优势**
>
- **A.代码布局更加简洁,而且无多余代码**
- **B.几乎没有多少淡黄色警告,关于注释,通过使用阿里编码插件检测后更加规范,我对代码有洁癖**
- **C.视频播放器[负责播放],视频控制器[负责视频播放各种点击或者属性设置操作],控制器抽象类[定义属性抽象类,供子类实现],其他可以看代码。结构分层上比较清晰**
- **D.几乎所有的方法或者重要的成员或者局部变量都有相关的注释,注释的内容非常详细**
- **E.关于视频属性设置或者按钮点击事件,都可以通过设置相关方法灵活实现。**
- 首先这些库封装的思路和代码都不错,我也是借鉴他们的思路,在他们的思路上改进而封装的。
- **相比来说代码结构更加清晰,举几个例子**
- 针对视频播放页面布局,由于视频播放状态众多,我封装这库不同状态布局有十几种,许多库的视图布局没注释,显示比较臃肿,如果修改或者定位,不熟悉或者好久不操作,都要花时间找。展示我的布局代码
```
```
### 2.关于使用方法说明
#### 2.1 关于gradle引用说明
- **2.1.1直接引用这段代码就可以**
```
compile 'cn.yc:YCVideoPlayerLib:2.2'
```
#### 2.2 添加布局
- 注意,在实际开发中,由于Android手机碎片化比较严重,分辨率太多了,建议灵活设置布局的宽高比为4:3或者16:9或者你认为合适的,可以用代码设置。
- 如果宽高比变形,则会有黑边
```
```
#### 2.3 最简单的视频播放器参数设定
- **2.3.1 这个是最简单视频播放器的设置参数代码**
```
//设置播放类型
// IjkPlayer or MediaPlayer
videoPlayer1.setPlayerType(VideoPlayer.TYPE_NATIVE);
//网络视频地址
String videoUrl = DataUtil.getVideoListData().get(0).getVideoUrl();
//设置视频地址和请求头部
videoPlayer1.setUp(videoUrl, null);
//是否从上一次的位置继续播放
videoPlayer1.continueFromLastPosition(true);
//设置播放速度
videoPlayer1.setSpeed(1.0f);
//创建视频控制器
VideoPlayerController controller = new VideoPlayerController(this);
controller.setTitle("办快来围观拉,自定义视频播放器可以播放视频拉");
//设置视频时长
controller.setLength(98000);
//设置5秒不操作后则隐藏头部和底部布局视图
controller.setHideTime(5000);
//controller.setImage(R.drawable.image_default);
ImageUtil.loadImgByPicasso(this, R.drawable.image_default, R.drawable.image_default, controller.imageView());
//设置视频控制器
videoPlayer1.setController(controller);
```
- **2.3.2 关于模仿爱奇艺登录会员权限功能代码**
```
//设置视频加载缓冲时加载窗的类型,多种类型
controller.setLoadingType(2);
ArrayList content = new ArrayList<>();
content.add("试看结束,yc观看全部内容请开通会员1111。");
content.add("试看结束,yc观看全部内容请开通会员2222。");
content.add("试看结束,yc观看全部内容请开通会员3333。");
content.add("试看结束,yc观看全部内容请开通会员4444。");
controller.setMemberContent(content);
controller.setHideTime(5000);
//设置设置会员权限类型,第一个参数是否登录,第二个参数是否有权限看,第三个参数试看完后展示的文字内容,第四个参数是否保存进度位置
controller.setMemberType(false,false,3,true);
controller.imageView().setBackgroundResource(R.color.blackText);
//ImageUtil.loadImgByPicasso(this, R.color.blackText, R.drawable.image_default, controller.imageView());
//设置试看结束后,登录或者充值会员按钮的点击事件
controller.setOnMemberClickListener(new OnMemberClickListener() {
@Override
public void onClick(int type) {
switch (type){
case ConstantKeys.Gender.LOGIN:
//调到用户登录也米娜
startActivity(MeLoginActivity.class);
break;
case ConstantKeys.Gender.MEMBER:
//调到用户充值会员页面
startActivity(MeMemberActivity.class);
break;
default:
break;
}
}
});
```
- **2.3.3其他设置,让体验更好**
- **如果是在Activity中的话,建议设置下面这段代码**
```
@Override
protected void onStop() {
super.onStop();
VideoPlayerManager.instance().releaseVideoPlayer();
}
@Override
public void onBackPressed() {
if (VideoPlayerManager.instance().onBackPressed()) return;
super.onBackPressed();
}
```
- **如果是在Fragment中的话,建议设置下面这段代码**
```
//在宿主Activity中设置代码如下
@Override
protected void onStop() {
super.onStop();
VideoPlayerManager.instance().releaseVideoPlayer();
}
@Override
public void onBackPressed() {
if (VideoPlayerManager.instance().onBackPressed()) return;
super.onBackPressed();
}
//--------------------------------------------------
//在此Fragment中设置代码如下
@Override
public void onStop() {
super.onStop();
VideoPlayerManager.instance().releaseVideoPlayer();
}
```
#### 2.4 注意的问题
- **2.4.1如果是全屏播放,则需要在清单文件中设置当前activity的属性值**
- android:configChanges 保证了在全屏的时候横竖屏切换不会执行Activity的相关生命周期,打断视频的播放
- android:screenOrientation 固定了屏幕的初始方向
- 这两个变量控制全屏后和退出全屏的屏幕方向
```
```
#### 2.5 关于开源库中的类说明
- 
#### 2.6 暴露接口让用户实现返回键和登录和购买会员点击事件逻辑
```
controller.setOnMemberClickListener(new OnMemberClickListener() {
@Override
public void onClick(int type) {
switch (type){
case ConstantKeys.Gender.LOGIN:
//调到用户登录也米娜
startActivity(MeLoginActivity.class);
break;
case ConstantKeys.Gender.MEMBER:
//调到用户充值会员页面
startActivity(MeMemberActivity.class);
break;
default:
break;
}
}
});
controller.setOnVideoBackListener(new OnVideoBackListener() {
@Override
public void onBackClick() {
onBackPressed();
}
});
```
### 3.关于播放类型说明
#### 3.1 普通视频播放
- 3.1.1 这一步操作可以直接看第二部分内容——关于使用方法说明
#### 3.2 list页面视频播放
- **3.2.1如何在list页面设置视频**
- 第一步:在activity或者fragment中
```
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
VideoAdapter adapter = new VideoAdapter(this, DataUtil.getVideoListData());
recyclerView.setAdapter(adapter);
//注意:下面这个方法不能漏掉
recyclerView.setRecyclerListener(new RecyclerView.RecyclerListener() {
@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
VideoPlayer videoPlayer = ((VideoAdapter.VideoViewHolder) holder).mVideoPlayer;
if (videoPlayer == VideoPlayerManager.instance().getCurrentVideoPlayer()) {
VideoPlayerManager.instance().releaseVideoPlayer();
}
}
});
```
- 第二步:在RecyclerView的适配器Adapter中
```
public class VideoAdapter extends RecyclerView.Adapter {
private Context mContext;
private List