jeffmony / jeffvideocache Goto Github PK
View Code? Open in Web Editor NEWBetter than AndroidVideoCache, it supports M3U8 and MP4
License: Apache License 2.0
Better than AndroidVideoCache, it supports M3U8 and MP4
License: Apache License 2.0
比如我的M3U8文件是这样的:
#EXTM3U
#EXT-X-VERSION:7
#EXT-X-STREAM-INF:BANDWIDTH=128000,CODECS="mp4a.40.34"
000_00000.m3u8
#EXT-X-STREAM-INF:BANDWIDTH=320000,CODECS="mp4a.40.34"
001_00000.m3u8
这是两个音轨
我如何使用JeffVideoCache在这两个音轨间切换呢?
当有多段缓存时,Mp4CacheTask.getRequestRange() 返回的分段会忽略一部分已经缓存的分段。
以下图为例,当一个视频具有三段缓存时,如果 position 在 cache1 和 cache2 之间,则最终返回的分段的起点为 position,终点为 cache3 的起点,cache2 会被忽略,被再缓存一次。
以我目前的理解,正确的返回值应该是 VideoRange(finalStart, firstEnd),即起点为 position,终点为 cache2 的起点。缓存完这一段后,Mp4VideoCacheThread.notifyOnCacheRangeCompleted()
会被调用去缓存下一段,补上所有的“洞”。
比如拖动进度条怎么处理,缓存进度怎么显示?
请大佬指教!!
开代理播放m3u8时,快进到未缓存的位置会卡住
期待..估计会火
来自客户端的seek操作seekToCacheTaskFromClient要自己实现?
如题。
大佬,我又来了。。。
我在demo apk中换了好些个mp4连接,都无法成功播放..
测试连接:
https://vdse.bdstatic.com//e52b1ca2bcaef6e01a346135f63a7a66.mp4?authorization=bce-auth-v1%2F40f207e648424f47b2e3dfbb1014b1a5%2F2021-06-23T15%3A20%3A04Z%2F-1%2Fhost%2F409b0d7a837ac9c76c0aa04ac6f197d22accb63137cdb2884166d74198892d6d
这里是测试用的视频:
链接: https://pan.baidu.com/s/1XzZSpA5NBzMzlwdR98xwxA?pwd=9m16 提取码: 9m16 复制这段内容后打开百度网盘手机App,操作更方便哦
下面是我测试抓取的日志信息:
2023-01-16 14:47:20.145 17675-19649/cn.kuwo.player I/SocketProcessTask: SocketProcessTask 创建: 37770
2023-01-16 14:47:20.145 17675-19666/cn.kuwo.player I/SocketProcessTask: sRequestCountAtomic : 1
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求URL:/aHR0cDovL2FyLnBsYXllci5yZjAxLnN5Y2RuLmt1d28uY24vN2M5N2I3ZmZlOGZkNDk1MmE4Mjk1YjRiM2ViYjQxZjkvNjNjNGYyZjgvcmVzb3VyY2UvbTIvNjMvOTIvMjQ0MjEyNTI5Ny5tcDQmamVmZm1vbnlfdmlkZW8mbm9uX20zdTgmamVmZm1vbnlfdmlkZW8mMzk0NDczMV83X01QNCZqZWZmbW9ueV92aWRlbyZ1bmtub3du
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Method:GET
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求KeepAlive:false
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:remote-addr:127.0.0.1
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:icy-metadata:1
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:http-client-ip:127.0.0.1
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:host:127.0.0.1:42053
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:range:bytes=0-
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:connection:close
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:user-agent:Lavf/57.83.100
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: 请求Header:accept:/
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: request.parseRequest end
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: request url=http://werewrewt2442125297.mp4
2023-01-16 14:47:20.147 17675-19666/cn.kuwo.player D/SocketProcessTask: http://42125297.mp4
non_m3u8
unknown
2023-01-16 14:47:20.148 17675-19666/cn.kuwo.player D/SocketProcessTask: request mSocket-->37770
2023-01-16 14:47:20.159 17675-19649/cn.kuwo.player I/SocketProcessTask: SocketProcessTask 创建: 37772
2023-01-16 14:47:20.159 17675-19667/cn.kuwo.player I/SocketProcessTask: sRequestCountAtomic : 2
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求URL:/aHR0cDovL2FyLnBsYXllci5yZjAxLnN5Y2RuLmt1d28uY24vN2M5N2I3ZmZlOGZkNDk1MmE4Mjk1YjRiM2ViYjQxZjkvNjNjNGYyZjgvcmVzb3VyY2UvbTIvNjMvOTIvMjQ0MjEyNTI5Ny5tcDQmamVmZm1vbnlfdmlkZW8mbm9uX20zdTgmamVmZm1vbnlfdmlkZW8mMzk0NDczMV83X01QNCZqZWZmbW9ueV92aWRlbyZ1bmtub3du
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Method:GET
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求KeepAlive:false
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:remote-addr:127.0.0.1
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:icy-metadata:1
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:http-client-ip:127.0.0.1
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:host:127.0.0.1:42053
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:range:bytes=22100255-
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:connection:close
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:user-agent:Lavf/57.83.100
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: 请求Header:accept:/
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: request.parseRequest end
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: request url=http://n
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: http://42125297.mp4
non_m3u8
unknown
2023-01-16 14:47:20.160 17675-19667/cn.kuwo.player D/SocketProcessTask: request mSocket-->37772
2023-01-16 14:47:20.163 17675-19666/cn.kuwo.player W/System.err: at cn.kuwo.cache.socket.SocketProcessTask.run(SocketProcessTask.java:82)
2023-01-16 14:47:20.163 17675-19666/cn.kuwo.player E/SocketProcessTask: socket request failed, exception=cn.kuwo.cache.common.VideoCacheException: send response failed:
2023-01-16 14:47:20.163 17675-19666/cn.kuwo.player W/SocketProcessTask: finally Socket solve count = 1
你好,在查阅您的代码后,发现M3U8Seg类中对切片进行了suffix判断,其中忽略了一些重定向的链接并没有后缀,因此需要在最后添加默认.ts
能直接生成本地代理链接给GSYvideoplayer或其他的播放器用吗
可以用MediaPlayer实现吗,在demo 里按照IjkPlayer 模板实现试了一下, MediaPlayer 一直报错, 找不到原因。。。
IJKpalyer播放器播放时,一直有错误打印,就是这个HttpRequest.parseRequest,明明请求失败了,但是却又有响应M3U8SegRespons,很奇怪
E/libOpenSLES: frameworks/wilhelm/src/android/AudioPlayer_to_android.cpp:1197: pthread_mutex_lock_timeout_np returned 110
I/M3U8CacheTask: startDownloadSegTask index=15, url=http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/bh2MVpba.ts
I/IJKMEDIA: Opening 'http://127.0.0.1:43252/aHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvaW5kZXgubTN1OCZqZWZmbW9ueV9zZWcmaHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvODAwa2IvaGxzL0llM29nald3LnRzJmplZmZtb255X3NlZyYvNjVkNWJlYzU1NGMyNjRjY2UwMDMzMzYxZGI4MTExMWYvMS50cyZqZWZmbW9ueV9zZWcmdW5rbm93bg' for reading
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 1
W/System.err: java.net.SocketException: Can't read inputStream
W/System.err: at com.owen.tv91.player.videocache.socket.request.HttpRequest.parseRequest(HttpRequest.java:69)
W/System.err: at com.owen.tv91.player.videocache.socket.SocketProcessTask.run(SocketProcessTask.java:43)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
W/SocketProcessTask: socket request failed, exception=java.net.SocketException: Can't read inputStream
I/SocketProcessTask: finally Socket solve count = 1
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 131073
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 131074
I/SocketProcessTask: sRequestCountAtomic : 2
D/SocketProcessTask: request url=http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8&jeffmony_seg&http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/Ie3ogjWw.ts&jeffmony_seg&/65d5bec554c264cce0033361db81111f/1.ts&jeffmony_seg&unknown
http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8
http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/Ie3ogjWw.ts
/65d5bec554c264cce0033361db81111f/1.ts
unknown
I/M3U8SegResponse: SegFilePath=/storage/emulated/0/Android/data/com.owen.tv91/files/Video/jeffmony/65d5bec554c264cce0033361db81111f/1.ts
I/M3U8SegResponse: index=1, parentUrl=http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8, segUrl=http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/Ie3ogjWw.ts
I/M3U8CacheTask: startDownloadSegTask index=16, url=http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/eT4tl0JI.ts
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 2
D/M3U8SegResponse: FileLength=600472, segLength=0, FilePath=/storage/emulated/0/Android/data/com.owen.tv91/files/Video/jeffmony/65d5bec554c264cce0033361db81111f/1.ts
D/M3U8SegResponse: Send M3U8 ts file end, this=com.owen.tv91.player.videocache.socket.response.M3U8SegResponse@15185347
I/M3U8CacheTask: startDownloadSegTask index=17, url=http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/j8N36jCp.ts
W/System.err: java.net.SocketException: Can't read inputStream
at com.owen.tv91.player.videocache.socket.request.HttpRequest.parseRequest(HttpRequest.java:69)
at com.owen.tv91.player.videocache.socket.SocketProcessTask.run(SocketProcessTask.java:43)
W/System.err: at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
I/IJKMEDIA: Opening 'http://127.0.0.1:43252/aHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvaW5kZXgubTN1OCZqZWZmbW9ueV9zZWcmaHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvODAwa2IvaGxzL3k2UERrYVNhLnRzJmplZmZtb255X3NlZyYvNjVkNWJlYzU1NGMyNjRjY2UwMDMzMzYxZGI4MTExMWYvMi50cyZqZWZmbW9ueV9zZWcmdW5rbm93bg' for reading
W/System.err: at java.lang.Thread.run(Thread.java:818)
W/SocketProcessTask: socket request failed, exception=java.net.SocketException: Can't read inputStream
I/SocketProcessTask: finally Socket solve count = 1
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 1
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 131073
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 131074
D/IJKMEDIA: FFP_MSG_VIDEO_SIZE_CHANGED: 1280, 720
D/IJKMEDIA: SDL_VoutFFmpeg_CreateOverlay(w=1280, h=720, fmt=RV32(0x32335652, dp=0xb06c8da0)
I/SocketProcessTask: sRequestCountAtomic : 2
D/SocketProcessTask: request url=http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8&jeffmony_seg&http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/y6PDkaSa.ts&jeffmony_seg&/65d5bec554c264cce0033361db81111f/2.ts&jeffmony_seg&unknown
D/SocketProcessTask: http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8
http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/y6PDkaSa.ts
/65d5bec554c264cce0033361db81111f/2.ts
unknown
I/M3U8SegResponse: SegFilePath=/storage/emulated/0/Android/data/com.owen.tv91/files/Video/jeffmony/65d5bec554c264cce0033361db81111f/2.ts
index=2, parentUrl=http://cdn.hainvyou.com/20220117/HQCVcfUf/index.m3u8, segUrl=http://cdn.hainvyou.com/20220117/HQCVcfUf/800kb/hls/y6PDkaSa.ts
I/tv.danmaku.ijk.media.player.IjkMediaPlayer: onNativeInvoke 2
D/M3U8SegResponse: FileLength=281248, segLength=0, FilePath=/storage/emulated/0/Android/data/com.owen.tv91/files/Video/jeffmony/65d5bec554c264cce0033361db81111f/2.ts
D/M3U8SegResponse: Send M3U8 ts file end, this=com.owen.tv91.player.videocache.socket.response.M3U8SegResponse@39b1d540
D/IJKMEDIA: ANativeWindow_setBuffersGeometry: w=580, h=326, f=�(0x1) => w=1280, h=720, f=RV32(0x32335652)
D/IJKMEDIA: FFP_MSG_VIDEO_SIZE_CHANGED: 1280, 720
W/System.err: java.net.SocketException: Can't read inputStream
I/IJKMEDIA: Opening 'http://127.0.0.1:43252/aHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvaW5kZXgubTN1OCZqZWZmbW9ueV9zZWcmaHR0cDovL2Nkbi5tYWludnlvdS5jb20vMjAyMjAxMTcvSFFDVmNmVWYvODAwa2IvaGxzLzBhemhGc3ZlLnRzJmplZmZtb255X3NlZyYvNjVkNWJlYzU1NGMyNjRjY2UwMDMzMzYxZGI4MTExMWYvMy50cyZqZWZmbW9ueV9zZWcmdW5rbm93bg' for reading
W/System.err: at com.owen.tv91.player.videocache.socket.request.HttpRequest.parseRequest(HttpRequest.java:69)
at com.owen.tv91.player.videocache.socket.SocketProcessTask.run(SocketProcessTask.java:43)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
W/SocketProcessTask: socket request failed, exception=java.net.SocketException: Can't read inputStream
I/SocketProcessTask: finally Socket solve count = 1
看了一下源码,不知道是不是和这while循环有关,正常流程是不是也要关闭socket
public void run() {
try {
//....................................
while(!mSocket.isClosed()) { // 修改方式1:这里改成if
request.parseRequest();
BaseResponse response;
//....................................
if (TextUtils.equals(ProxyCacheUtils.M3U8, videoTypeInfo)) {
response = new M3U8Response(request, videoUrl, headers, currentTime);
} else if (TextUtils.equals(ProxyCacheUtils.NON_M3U8, videoTypeInfo)) {
response = new Mp4Response(request, videoUrl, headers, currentTime);
} else {
//无法从已知的信息判定视频信息,需要重新请求
//....................................
} else if (url.contains(ProxyCacheUtils.SEG_PROXY_SPLIT_STR)) {
//说明是M3U8 ts格式的文件
//....................................
} else {
throw new VideoCacheException("Local Socket Error url");
}
/*******************************************************************************
ProxyCacheUtils.close(mSocket); // 修改方式2:这里响应之后得关闭该socket
********************************************************************************/
}
} catch (Exception e) {
e.printStackTrace();
LogUtils.w(TAG,"socket request failed, exception=" + e);
} finally {
ProxyCacheUtils.close(outputStream);
ProxyCacheUtils.close(inputStream);
ProxyCacheUtils.close(mSocket);
int count = sRequestCountAtomic.decrementAndGet();
LogUtils.i(TAG, "finally Socket solve count = " + count);
}
}
}
如果想要使用本地代理播放ijkplayer模式 需要如何做?求求了。。。
框架没有缓存key文件,应该是exoplayer在下载加密key
当 mVideoRangeMap 为空时,为什么从 0 开始缓存,而不是从 position 开始缓存
public VideoRange getRequestRange(long position) {
if (mVideoRangeMap.size() == 0) {
return new VideoRange(0, mTotalSize);
}
...
}
1、在android11上如果使用ijkplayer就会崩溃;
2、播放非MP4和m3u8时,如mkv、avi、aov等等格式,会一直下载完才会播放,比如30分钟1个G的视频,必须下载完才行,期间不会播放;
假设文件大小有100mb ,需要将这100mb缓存完才能播放,缓存一部分时 为啥不能播放?求解
目前运行demo,开代理后拖动进度跳会卡死,期待框架的完美运行哦,作者加油哦
缓存全部视频数据的话,占用空间比较大。想只缓存前 3 秒数据,请问需要怎么做呢?
分析后发现问题出在这里。
类 Mp4Response.java
方法 public void sendBody(Socket socket, OutputStream outputStream, long pending) throws Exception{
}
如下代码
while (bufferLength > 0 && (readLength = randomAccessFile.read(buffer, 0, (int) bufferLength)) != -1) {
offset += readLength;
outputStream.write(buffer, 0, readLength);
randomAccessFile.seek(offset);
bufferLength = (avilable - offset + 1) > bufferedSize ? bufferedSize : (avilable - offset + 1);
}
这里判断条件有问题。当第一次seek到结尾的时候,缓存文件中前面段没写入的数据,此段数据为空数据,再次往回seek,此时read 后,readLength 长度不是-1,但向buffer数组中写入的全是0,播放器接受到的全是空数据,也跳不出while循环。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.