鸿鸿蒙开源组件——蒙视频缓存引擎项目
VideoCache_ohos
本项目是基于开源项目AndroidVideoCache进行鸿蒙化的移植和开发的,可以通过项目标签以及github地址( https://github.com/danikula/AndroidVideoCache )追踪到原安卓项目版本,该项目的讲解介绍已在社区发布,可以通过网址( https://harmonyos.51cto.com/posts/3463 )访问相关内容。
项目介绍
- 项目名称:开源视频缓存引擎项目
- 所属系列:鸿蒙的第三方组件适配移植
- 功能:支持自动缓存视频并在断网状态下播放视频
- 项目移植状态:完成
- 调用差异:无
- 开发版本:sdk5,DevEco Studio2.1 beta3
- 项目作者和维护人:吕泽
- 邮箱:isrc_hm@iscas.ac.cn
- 原项目Doc地址:https://github.com/danikula/AndroidVideoCache
- 编程语言:Java
- 外部库依赖:无
由于本项目基于安卓版本移植开发,所以继承了安卓版本的部分问题,即在一些情况下无法ping通本地服务器,但不会影响视频的播放:
-
In some cases clients can't connect to local proxy server ('Error pinging server' error). May be it is result of previous error. Note in this case video will be played, but without caching.
-
原库由于设置的缓冲区的问题,大视频拖动进度条之后会卡顿很久才能继续播放。简单来说即是:以整个视频长度为基准,
-
A:进度条seekTo之后对应的视频长度;
-
B:seek开始时的用于缓存的临时文件的长度;
-
C:缓冲区长度(视频大小的20%),
-
如果A<=B+C,那么seekTo处于缓冲区以内,必须继续缓存等到B==A才可以在临时文件里读取缓存数据用于播放;
-
如果A>B+C,说明seekTo的位置在缓冲区外,这个时候则是请求网络数据之后直接写入socket用于播放,不进行缓存。
-
当视频总长度很大的时候C的值也会很大,这样就会造成缓冲区过长,拖动之后从B缓冲到A的时间需要很久,播放器需要卡顿很久才会继续播放, 例如当前临时文件大小B=20M,视频长度为3G,那么C=600M,假设A=590M,那么A<B+C,此时需要从20M下载网络数据缓存到590M才能继续播放。 为了解决这个问题,本库在原缓存方案上增加缓冲区设置功能,并新增了分段缓存功能。目前新增了分片缓存和分节点缓存两种方案。
策略介绍
-
默认缓存策略 边播放边缓存,将视频URL前面拼接上127.0.0.1与随机端口,通过本地服务端监听视频播放请求,并拦截该请求,然后将请求分发给本地的代理客户端,本地客户端利用HttpURLConnection下载网络数据缓存到本地临时文件,再读取临时文件缓存数据写入socket返回给播放器,所有数据下载完毕之后将临时文件重命名。由于播放数据是从缓存中获取,所以只要有缓存,断网状态下也可以播放视频。同时本方案使用了生产消费者模式,在弱网环境下请求数据慢的时候,读取线程会等待写入线程先写入缓存数据。另外本方案使用了随机流文件RandomAccessFile,通过文件指针跳转不同位置,来达到读写线程同时操作一个临时文件读写数据。本策略缓存顺序只能从前到后,每次写入数据都是在文件结尾。
-
分片缓存策略(新增) 本策略基于默认策略开发,效果是拖到哪里即从那开始缓存,同时读取缓存数据用于播放。缓存开始前根据seekTo的位置和当前URL命名的文件夹里的已经生成的碎片文件,先确认本次拖动是需要生成新的碎片文件还是使用已有的碎片文件(碎片文件以缓存起始点为名,以.download作为文件格式),再确认当前播放的碎片文件以及其缓存起始点与结束点。当前碎片文件缓存到结束点后,如果有与之相连的碎片文件,则将相连的碎片文件合并到当前碎片文件,合并完成删除相连的碎片文件,直至最后全部合并为一个文件后重命名。
-
分节点缓存策略(新增) 本策略基于默认策略开发,效果是拖到哪里即从那开始缓存,同时读取缓存数据用于播放。实现原理是使用一个临时文件,利用DatabaseHelper记录当前缓存的起止点,利用随机流文件RandomAccessFile的指针跳转至不同位置读写数据。缓存开始前根据seekTo的位置和记录的起止点确认本次缓存的起始点与结束点,缓存开始后利用RandomAccessFile读写数据,缓存到终止点结束本次的写入,每次缓存结束或者终止的时候都会记录当前缓存起止点到DatabaseHelper,如果记录的起始点有交叉或者相连则合并区间,当所有数据缓存完成后将临时文件重命名。
安装教程
-
下载弹幕库jar包VideoCache.jar。
-
启动 DevEco Studio,将下载的jar包,导入工程目录“entry->libs”下。
-
在moudle级别下的build.gradle文件中添加依赖,在dependences标签中增加对libs目录下jar包的引用。
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.har']) …… }
- 若此时jar包仍未被识别,可以在jar包上点击右键,选择“Add as Library”对包进行引用,选择需要引用的模块,并点击“OK”即引用成功。
在sdk4,DevEco Studio2.1 beta2下项目可直接运行 如无法运行,删除项目.gradle,.idea,build,gradle,build.gradle文件, 并依据自己的版本创建新项目,将新项目的对应文件复制到根目录下
使用说明
相关类名:HttpProxyCacheServer
- 实例化Strategy对象
// 使用默认的缓存策略 默认缓冲区大小 CacheStrategy strategy = new DefaultCacheStrategy(); // 使用默认的缓存策略 设置缓冲区大小为10M CacheStrategy strategy = new DefaultCacheStrategy(10 * 1024 * 1024); // 使用默认的缓存策略 设置缓冲区大小为视频比例的10% CacheStrategy strategy = new DefaultCacheStrategy(0.1f); // 使用分片缓存策略 CacheStrategy strategy = new SlicingCacheStrategy(); // 设置单个碎片文件的最小长度,少于这个长度,缓存完毕碎片文件将被删除丢弃 ((SlicingCacheStrategy) strategy).setMinSingleFileSize(10 * 1024 * 1024); // 设置每个碎片文件的缓存区的大小,如果拖动进度条之后播放位置处于某个碎片文件大小加缓存区大小之间,本次缓存使用该碎片文件,不会生成新的碎片文件 ((SlicingCacheStrategy) strategy).setMinFileCacheSize(10 * 1024 * 1024); // 使用分节点缓存策略 CacheStrategy strategy = new OneFileCacheStrategy(this);
- 实例化HttpProxyCacheServer对象
private HttpProxyCacheServer mCacheServerProxy=null;
public void onStart(Intent intent) {
//……
if (mCacheServerProxy == null) {
Context context = this;
mCacheServerProxy = new HttpProxyCacheServer(context);
}
//……
}
或者
private HttpProxyCacheServer mCacheServerProxy=null;
public void onStart(Intent intent) {
//……
private void initServerProxy() {
if (mCacheServerProxy == null) {
// 通过Builder创建代理服务对象
mCacheServerProxy = new HttpProxyCacheServer.Builder(this)
.diskUsage(new TotalCountLruDiskUsage(10)) // 设置缓存视频文件的策略为文件数缓存策略
.CacheStrategy(strategy) // 设置整体缓存策略
.fileNameGenerator(new Md5FileNameGenerator()) // 设置缓存文件重命名规则
.cacheDirectory(StorageUtils.getIndividualCacheDirectory(this)) // 设置视频缓存文件的根路径
.headerInjector(new EmptyHeadersInjector()) // 添加自定义的头部信息
.build();
}
}
//……
}
- 定义缓存相关函数mCacheListener
private CacheListener mCacheListener = new CacheListener() { @Override public void onCacheAvailable(File cacheFile, String url, int percentsAvailable) { // 默认缓存策略 缓存进度回调 } @Override public void onCachePartAvailable(File cacheFile, String url, List<long[]> percentsAvailables, long fileLength) { // 分片/分节点缓存策略 缓存进度回调 } };
- 定义缓存策略出错回调相关函数ReSetAfterErrorListener
mCacheServerProxy.setAttemptsTime(1); // 设置策略出错重试次数 // 设置策略出错回调监听 可以在分片/分节点策略播放视频出错的时候回调给用户处理(可以切换为默认策略或者关闭APP等) mCacheServerProxy.setListener(() -> { getUITaskDispatcher().asyncDispatch(this::replayIfError); }); };
- 使用HttpProxyCacheServer对象,进行缓存proxy的转化
//使用上述第二步的缓存函数
mCacheServerProxy.registerCacheListener(mCacheListener,URL);
//将URL转化为localUrl
localUrl = mCacheServerProxy.getProxyUrl(URL);
- 使用localUrl作为视频来源进行使用,缓存功能即可自动实现。
版本迭代
- v0.1.0-alpha
基本功能实现 - v0.2.0-alpha
解决了gradle sync时间过长的问题
消除了config.json中的冗余代码 - v0.3.0-alpha
1.原缓存策略增加缓冲区设置功能(按照大小/比例)。
2.增加缓存策略配置功能,可自定义缓存策略动态替换
3.增加分片缓存策略。
4.增加分节点缓存策略。
5.示例工程增加策略切换功能,分段缓存进度显示功能。
6.增加library库代码混淆功能。
版权和许可信息
- VideoCache_ohos经过Apache License, version 2.0授权许可。