JeffMony / JeffVideoCache

Better than AndroidVideoCache, it supports M3U8 and MP4
Apache License 2.0
290 stars 65 forks source link

忽略了一种切片suffix情况,望修复 #21

Open kaihuang666 opened 2 years ago

kaihuang666 commented 2 years ago

你好,在查阅您的代码后,发现M3U8Seg类中对切片进行了suffix判断,其中忽略了一些重定向的链接并没有后缀,因此需要在最后添加默认.ts

JeffMony commented 2 years ago

有例子吗?

kaihuang666 commented 2 years ago

有例子吗?

EXTM3U

EXT-X-VERSION:3

EXT-X-MEDIA-SEQUENCE:0

EXT-X-ALLOW-CACHE:YES

EXT-X-TARGETDURATION:6

EXTINF:5.120000,

https://sf3-ttcdn-tos.pstatp.com/obj/tos-cn-i-dy/b0b540bbf8454bc9b41612824d6b263b

EXTINF:5.000000,

https://sf3-ttcdn-tos.pstatp.com/obj/tos-cn-i-dy/a6182f2e0ae64029921d6a02363237f1

EXTINF:5.000000,

https://sf3-ttcdn-tos.pstatp.com/obj/tos-cn-i-dy/246e15ece9b449159c22a94c5a219bf0 比如这类的切片,没有后缀,在生成本地文件就是/....../3没有后缀,请求时会报错找不到index,你只需要修改一下获取suffix的方法,在发现结果为empty时返回默认.ts后缀就行

kaihuang666 commented 2 years ago

有例子吗?

另外,我就我自己的情况提个建议,我看你seek部分的代码,其实是客户端加入一个标记,服务端在request时发现标记才进行任务的seek

这对于边下边播比较友好,但是具体到播放器时ijkplayer播放视频会有部分帧回弹的问题,也就是客户端发生seek时,可能仍然会请求seek前的帧,然后再请求seek后的帧,因为你代码中客户端设置的标记可能会跳到seek前去,这样播放就卡了。

这个问题在m3u8中严重,流文件能正常seek,打开accurate seek能够减少一定的发生概率,但是终归这种hls媒体没办法很快定位到新的帧上去。

我的个人建议是:m3u8 seek后请求新切片,一律允许seek操作 public M3U8SegResponse(HttpRequest request, String parentUrl, String videoUrl, Map<String, String> headers, long time, String fileName) throws Exception { super(request, videoUrl, headers, time); mParentUrl = parentUrl; mSegUrl = videoUrl; mSegFile = new File(mCachePath, fileName); LogUtils.i(TAG, "SegFilePath="+mSegFile.getAbsolutePath()); mFileName = mSegFile.getName(); mM3U8Md5 = getM3U8Md5(fileName); if (mHeaders == null) { mHeaders = new HashMap<>(); } mHeaders.put("Connection", "close"); mSegIndex = getSegIndex(fileName); mResponseState = ResponseState.OK; LogUtils.i(TAG, "index="+mSegIndex+", parentUrl="+mParentUrl+", segUrl="+mSegUrl); //此处无需判断map中是否有seek position VideoProxyCacheManager.getInstance().seekToCacheTaskFromServer(mParentUrl, mSegIndex); } //防止频繁或重复seek操作,用handler延时操作(因此在M3U8SegResponse未缓存的切片并不是通过cacheTask下载的,这里延迟1秒并不会造成卡顿,当然为了保证线程安全,应对相关seek方法进行锁保护) public synchronized void seekToCacheTaskFromServer(String url, int segIndex) { seekHandler.removeCallbacksAndMessages(null); seekHandler.postDelayed(new Runnable() { @Override public void run() { VideoCacheTask cacheTask = mCacheTaskMap.get(url); if (cacheTask != null) { cacheTask.seekToCacheTaskFromServer(segIndex); } } }, 1000);

}