Git Product home page Git Product logo

m3u8manger's Introduction

License Download

M3U8Manger (M3U8管理器)

如果帮助到你,麻烦来个star,更欢迎你的fork

  • M3U8格式视频下载
  • 获取M3U8格式信息
  • 中途停止任务
  • 获取下载速度
  • 支持多任务下载
  • 支持url重定向处理过的m3u8
  • 支持直播缓存

温馨提示: 项目会一直维护, 请尽量通过issue渠道提bug和改进建议(绑定过邮箱,会第一时间回复)

体验app

扫描二维码:

或打开下面的地址

https://fir.im/2g5c

温馨提示:应用介绍里面有直播缓存教程

适用性

适用以下格式的m3u8格式(如果名字不是时间毫秒值的话,调用获取m3u8信息的方法将得不到开始时间,但不影响下载),当然有鉴权信息也是允许的

#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:10
#EXTINF:9.960,
1500480000074.ts
#EXTINF:10.190,
1500480009999.ts
#EXTINF:9.960,
1500480020246.ts
#EXTINF:9.960,
1500480030189.ts
#EXTINF:10.030,
...

导入:

compile 'com.jwkj:M3U8Manger:v2.3.0'

获取M3U8信息:

   M3U8InfoManger.getInstance().getM3U8Info(url, new OnM3U8InfoListener() {
            @Override
            public void onSuccess(M3U8 m3U8) {
                ELog.e("获取成功了" + m3U8);
            }

            @Override
            public void onStart() {
                ELog.e("开始获取信息");
            }

            @Override
            public void onError(Throwable errorMsg) {
                ELog.e("出错了" + errorMsg);
            }
        });

点播下载

下载M3U8格式的视频文件:

 M3U8DownloadTask task1 = new M3U8DownloadTask("1001");
//下载按钮监听事件
 public void onDownload(View view) {
        task1.download(url, new OnDownloadListener() {
            @Override
            public void onDownloading(final long itemFileSize, final int totalTs, final int curTs) {
                ELog.e(task1.getTaskId() + "下载中.....itemFileSize=" + itemFileSize + "\ttotalTs=" + totalTs + "\tcurTs=" + curTs);
            }

            /**
             * 下载成功
             */
            @Override
            public void onSuccess() {
                ELog.e(task1.getTaskId() + "下载完成了");
            }

            /**
             * 当前的进度回调
             *
             * @param curLenght
             */
            @Override
            public void onProgress(final long curLenght) {
                if (curLenght - lastLength > 0) {
                    final String speed = NetSpeedUtils.getInstance().displayFileSize(curLenght - lastLength) + "/s";
                    ELog.e(task1.getTaskId() + "speed = " + speed);
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            ELog.e("更新了");
                            tvSpeed1.setText(speed);
                            ELog.e(tvSpeed1.getText().toString());
                        }
                    });
                    lastLength = curLenght;

                }
            }

            @Override
            public void onStart() {
                ELog.e(task1.getTaskId() + "开始下载了");
            }

            @Override
            public void onError(Throwable errorMsg) {
                ELog.e(task1.getTaskId() + "出错了" + errorMsg);
            }
        });
    }

停止任务:

      task1.stop();

直播缓存

开启缓存

 String toFile="/sdcard/" + System.currentTimeMillis() + ".ts";
        tvSaveFilePathTip.setText("缓存目录在:/sdcard/11m3u8/\n最终导出的缓存文件在:"+toFile);
        M3U8LiveManger.getInstance()
                .setTempDir("/sdcard/11m3u8/")
                .setSaveFile(toFile)//(设置导出缓存文件)必须以.ts结尾
                .caching(url, new OnDownloadListener() {
                    @Override
                    public void onDownloading(long itemFileSize, int totalTs, int curTs) {
                      //此回调只有curTs有意义,表示开始缓存第几个ts
                    }

                    @Override
                    public void onSuccess() {
                        //此回调没有什么意义
                    }

                    @Override
                    public void onProgress(long curLength) {
                        if (curLength - lastLength > 0) {
                        //计算缓存速度
                            final String speed = NetSpeedUtils.getInstance().displayFileSize(curLength - lastLength) + "/s";
                            lastLength = curLength;
                        }
                    }

                    @Override
                    public void onStart() {
                        //开始缓存
                    }

                    @Override
                    public void onError(Throwable errorMsg) {
                        //缓存出错了
                    }
                });

获取开始缓存到当前时间的ts文件

 String filePath = M3U8LiveManger.getInstance().getCurrentTs();

温馨提示:此方法会自动合并当次任务所下载的所有ts文件,如果你不需要此方法,也可以使用com.hdl.m3u8.utils.MUtils.merge(java.util.List<java.io.File>, java.lang.String)方法来合并,当然自己写合并方法也是可以的

停止缓存

 M3U8LiveManger.getInstance().stop();

版本记录

v2.x

v2.3.0(2018.03.07)

  • 【新增】支持缓存直播类型的m3u8

v2.2.3(2018.03.06)

  • 【优化】支持更多格式的ts命名

v2.1.9(2017.11.21)

  • 【优化】支持url重定向处理过的m3u8

v2.1.8(2017.11.21)

  • 【新增】支持m3u8中的ts名字为非时间毫秒值的格式(此时ts的开始时间为0)

v2.1.7(2017.09.12)

  • 【新增】设置下载线程数方法(默认3个,建议不要设置超过5个)

v2.1.6(2017.08.15)

  • 【新增】设置连接超时时间、读取超时时间

v2.1.4、v2.1.5(2017.08.14)

  • 【优化】延迟删除临时文件(因为存取速度比较低的设备可能存在未移动完成而被删除情况)

v2.1.3(2017.08.14)

  • 【优化】网络不稳定时的数据抖动问题

v2.1.2(2017.08.14)

  • 【新增】设置是否清除临时目录的方法

v2.1.1(2017.08.14)

  • 【修复】文件生成与设置的文件名字不一致问题

v2.0.8(2017.08.14)

  • 【修复】设置文件保存路径时,会多出文件夹

v2.0.7(2017.08.14)

  • 【修复】设置文件保存路径方法被隐藏

v2.0.6(2017.08.14)

  • 【新增】断点续传
  • 【新增】支持多任务
  • 【优化】下载速度不准确问题

V1.x

v1.0.8(2017.08.08)

  • 【新增】onLoadFileSizeForItem方法(获取单个ts文件的平均大小)
    • 可根据这个平均值x总的切片个数(total)=总文件的大小

v1.0.7(2017.07.31)

  • 【修复】获取M3U8信息不走onStart的bug

v1.0.6

  • 【修复】指定下载的区间时间不准问题

v1.0.5

  • 【修复】下载成功走的是onStart
  • 【新增】指定下载的区间

v1.0.4

  • 【新增】获取M3U8基本信息方法
  • 【新增】停止任务方法

v1.0.3

  • 【修复】url失效时抛出异常
  • 【新增】M3U8开始、结束时间

m3u8manger's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

m3u8manger's Issues

如何获取正在进行的下载任务信息

如何获取正在进行的下载任务信息,因为不可能一直在下载管理页面,如果用户退出后想在后台下载,过会再进下载任务管理页面查看呢

可以断点续传吗

有个错误
java.lang.NumberFormatException: For input string: "http://vali.cp31.ott.cibntv.net/657336C1E3B4571B1153A6E28/0300011501576AD30D0029132629A1DFA5FB02-87CA-5E89-7D82-FF5862B03A33.flv.ts?sid=050260411822420e45e55_01&sign=2ed144f976fbdd7c0770ee747e361395&ctype=50&ts_start=0.0&ts_end=11"
at java.lang.Long.parseLong(Long.java:443)
at java.lang.Long.parseLong(Long.java:485)
at com.hdl.m3u8.bean.M3U8Ts.getLongDate(M3U8Ts.java:44)
at com.hdl.m3u8.bean.M3U8.getStartTime(M3U8.java:63)
at com.hdl.m3u8.utils.MUtils.getLimitM3U8Ts(MUtils.java:125)
at com.hdl.m3u8.M3U8Manger.download(M3U8Manger.java:284)
at com.hdl.m3u8.M3U8Manger.access$1000(M3U8Manger.java:26)
at com.hdl.m3u8.M3U8Manger$3.run(M3U8Manger.java:195)

.

.

404,不支持分片类型的视频下载

不支持下面的这种m3u8格式下载


#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:19

#EXT-X-KEY:METHOD=AES-128,URI="http://www.mypsy365.com/hls/219/clef/LvU3ngZQ2stq2pXw7G69XxG4tyqr1r5y",IV=0x6e8b379f08fed6340d11025cb016e095
#EXTINF:7.800000,
http://ese1a1b2c8d5xn-pub.pub.qiqiuyun.net/headLeader-0/20151116032554-1l3sw31kc9pcgcs0/08240ac0d835086d_sd_seg_0_68d3b7d825fdcc9b55ff2a1d5676c8f5?schoolId=11285&fileGlobalId=1c17ce8bd5124ca2b358984f4a6bae88
#EXT-X-DISCONTINUITY
#EXT-X-KEY:METHOD=AES-128,URI="http://www.mypsy365.com/hls/149/clef/5RsxQElityxxsB4EQPx9m6o3YK5H06Gq",IV=0xb1cab025e664c613360378d3288fb116
#EXTINF:18.880000,
http://ese1a1b2c8d5xn-pub.pub.qiqiuyun.net/courselesson-75/20151104074940-r83w2x6genkockcg/aacd2acbddb2dfb9_sd_seg_0_0f87d35be12ca76fa47ec48156ecfbeb?schoolId=11285&fileGlobalId=1c17ce8bd5124ca2b358984f4a6bae88
#EXT-X-KEY:METHOD=AES-128,URI="http://www.mypsy365.com/hls/149/clef/5RsxQElityxxsB4EQPx9m6o3YK5H06Gq",IV=0x2e1ef34daa2713b4ab824666ef690703
#EXTINF:10.000000,
http://ese1a1b2c8d5xn-pub.pub.qiqiuyun.net/courselesson-75/20151104074940-r83w2x6genkockcg/aacd2acbddb2dfb9_sd_seg_1_1df26d56636550142dbc045a05bed196?schoolId=11285&fileGlobalId=1c17ce8bd5124ca2b358984f4a6bae88
#EXT-X-KEY:METHOD=AES-128,URI="http://www.mypsy365.com/hls/149/clef/5RsxQElityxxsB4EQPx9m6o3YK5H06Gq",IV=0x6115553f05719264de614c82bfcb6cfd
#EXTINF:10.000000,
http://ese1a1b2c8d5xn-pub.pub.qiqiuyun.net/courselesson-75/20151104074940-r83w2x6genkockcg/aacd2acbddb2dfb9_sd_seg_2_404e07d5bcb53ae5878c2cfce3bd4067?schoolId=11285&fileGlobalId=1c17ce8bd5124ca2b358984f4a6bae88
#EXT-X-KEY:METHOD=AES-128,URI="http://www.mypsy365.com/hls/149/clef/5RsxQElityxxsB4EQPx9m6o3YK5H06Gq",IV=0xe0236536ba85ce9acfc1c548404ad38b
#EXT-X-ENDLIST

https 协议未找到

07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │ downloadM3U8onFailure: ffmpeg version n3.0.1 Copyright (c) 2000-2016 the FFmpeg developers
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   built with gcc 4.8 (GCC)
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   configuration: --target-os=linux --cross-prefix=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/bin/arm-linux-androideabi- --arch=arm --cpu=cortex-a8 --enable-runtime-cpudetect --sysroot=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/sysroot --enable-pic --enable-libx264 --enable-libass --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-fontconfig --enable-pthreads --disable-debug --disable-ffserver --enable-version3 --enable-hardcoded-tables --disable-ffplay --disable-ffprobe --enable-gpl --enable-yasm --disable-doc --disable-shared --enable-static --pkg-config=/home/vagrant/SourceCode/ffmpeg-android/ffmpeg-pkg-config --prefix=/home/vagrant/SourceCode/ffmpeg-android/build/armeabi-v7a --extra-cflags='-I/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/include -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all' --extra-ldflags='-L/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/lib -Wl,-z,relro -Wl,-z,now -pie' --extra-libs='-lpng -lexpat -lm' --extra-cxxflags=
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libavutil      55. 17.103 / 55. 17.103
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libavcodec     57. 24.102 / 57. 24.102
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libavformat    57. 25.100 / 57. 25.100
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libavdevice    57.  0.101 / 57.  0.101
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libavfilter     6. 31.100 /  6. 31.100
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libswscale      4.  0.100 /  4.  0.100
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libswresample   2.  0.101 /  2.  0.101
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │   libpostproc    54.  0.100 / 54.  0.100
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │ https protocol not found, recompile FFmpeg with openssl, gnutls,
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │ or securetransport enabled.
07-27 14:43:37.587 13515-13515/com.ttxinli.ttxinli E/DownloadController: │ https://preview.mypsy365.com/app_dev.php/hls/232/stream/sd/aF6F9qgiZqZtBXHlMpYlxUFEmPKaxaTc.m3u8?1532673817: Protocol not found

两个问题 IntentService中使用 m3u8加密分片

在IntentService种使用会有 java.lang.IllegalStateException Handler sending message to a Handler on a dead thread
我自己改动了mHandler

private Handler mHandler = new Handler(Looper.getMainLooper())

实际项目中都是加密分片。都不能直接播放ts文件。还是需要用m3u8文件才能播放,如果要本地播放的还需要写有索引和密匙的m3u8文件才能播放。

下载失败,切片Url需要去重

这是一个测试地址:
http://cn1.fa1244.cn/hls/20190516/6d271eaa73b2e4cb51d13831b0c1ab4c/1557976262/index.m3u8
类似这种的,返回的切片跟basepath有一部分url是重复,需要去除重复路径,否则报404错误。
basepath是这个,
http://cn1.fa1244.cn/hls/20190516/6d271eaa73b2e4cb51d13831b0c1ab4c/1557976262/
而切片是这样的,
/hls/20190516/6d271eaa73b2e4cb51d13831b0c1ab4c/1557976262/film_00000.ts
在M3U8DownloadTask类下280行左右拼接路径时需要做去重处理,其他地方还没发现,望楼主采纳。

get basepath wrong

the old code is:
String basepath = realUrl.substring(0, realUrl.lastindexOf("/") + 1);
but this code may get the wrong path :

mp4下载

是否可以兼容一下MP4等格式的或者有什么方法判断一下url是否可以使用m3u8Manger下载,试了一下使用MP4地址调用getM3U8Info会有问题,oom

下载问题

2个问题:ts切片顺序不对,合并的视频需要再编码,时间轨不对。

我试了下,有点问题,大神

https://video.x.zhihuiya.com/v1-m3u8-aq0/m3u82020-05-28%2019-26-06_1_15907306352330f0d9b35f01ae9d5352ba3d66b33ca0b.m3u8

在您的demo上替换了url地址,后点击下载按钮

E/onStart(Main2Activity.java:141): 1001开始下载了
E/onError(Main2Activity.java:148): 1001出错了java.lang.Throwable: 404
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=1
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=2
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=3
E/onStart(Main2Activity.java:141): 1001开始下载了
E/onError(Main2Activity.java:148): 1001出错了java.lang.Throwable: 404
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=4
E/onError(Main2Activity.java:148): 1001出错了java.lang.Throwable: 404
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=6
E/onError(Main2Activity.java:148): 1001出错了java.lang.Throwable: 404
E/onDownloading(Main2Activity.java:103): 1001下载中.....itemFileSize=0 totalTs=627 curTs=6

demo下载视频oom了

11-25 15:01:59.270 5030-5296/com.hdl.m3u8demo E/AndroidRuntime: FATAL EXCEPTION: Thread-5
Process: com.hdl.m3u8demo, PID: 5030
java.lang.OutOfMemoryError: Failed to allocate a 1024 byte allocation with 9433776 free bytes and 8MB until OOM; failed due to fragmentation (required continguous free 8192 bytes for a new buffer where largest contiguous free 0 bytes)
at java.lang.StringFactory.newStringFromChars(StringFactory.java:218)
at java.io.BufferedReader.readLine(BufferedReader.java:367)
at java.io.BufferedReader.readLine(BufferedReader.java:400)
at com.hdl.m3u8.utils.MUtils.parseIndex(MUtils.java:46)
at com.hdl.m3u8.M3U8InfoManger$2.run(M3U8InfoManger.java:62)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.