根据M3U8地址下载视频
下面展示的是通过M3U8地址,把这个地址转为一个视频文件;只是一个基本案例,当然,有些下载的M3U8文件里面格式是不一样的,还有的是加过密的,道理都是一个道理。
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.io.IOUtils; /**
* 根据M3U8地址下载视频
* IOUtils.copyLarge 需要引入commons.io包
*
* java.version 1.7
*/
public class M3U8Downloader { /** m3u8地址 */
private static String url = "http://playertest.longtailvideo.com/adaptive/bipbop/gear4/prog_index.m3u8";
/** 正式文件存储地址(合并之后的文件) */
private static String tofile = "E:\\m3u8\\Movie.ts";
/** 临时文件存储地址(M3U8视频段) */
private static String tofileTemp = "E:\\m3u8\\temp"; private static ExecutorService executor = Executors.newFixedThreadPool(10); public static void main(String[] args) throws IOException, InterruptedException {
//解析M3U8地址为对象
M3U8 m3u8 = parseIndex(url); //根据M3U8对象获取时长
float duration = getDuration(m3u8);
System.out.println("时长: " + ((int) duration / 60) + "分" + (int) duration % 60 + "秒"); //根据M3U8对象下载视频段
download(m3u8, tofileTemp); //关闭线程池
executor.shutdown();
System.out.println("等待下载中...");
while (!executor.isTerminated()) {
Thread.sleep(100);
} //合并文件
merge(m3u8, tofile, tofileTemp); System.out.println("下载完成,合并的文件在: " + tofile);
} /**
* 根据M3U8对象获取时长
* @param m3u8
* @return
*/
private static float getDuration(M3U8 m3u8){
float duration = 0;
for (M3U8Ts ts : m3u8.getTsList()) {
duration += ts.getSeconds();
}
return duration;
} /**
* 合并文件
* @param m3u8
* @param tofile
* @throws IOException
*/
public static void merge(M3U8 m3u8, String tofile, String tofileTemp) throws IOException {
File file = new File(tofile);
FileOutputStream fos = new FileOutputStream(file); File fileTempDir = new File(tofileTemp);
for (File fileTemp : fileTempDir.listFiles()) {
IOUtils.copyLarge(new FileInputStream(fileTemp), fos);
} fos.close();
} /**
* 根据M3U8对象下载视频段
* @param m3u8
* @param tofile
* @throws IOException
*/
public static void download(final M3U8 m3u8, final String tofileTemp) throws IOException {
final File dir = new File(tofileTemp);
if (!dir.exists()) {
dir.mkdirs();
} for (final M3U8Ts ts : m3u8.getTsList()) {
executor.execute(new Runnable() {
@Override
public void run() {
try {
FileOutputStream writer = new FileOutputStream(new File(dir, ts.getFile()));
IOUtils.copyLarge(new URL(m3u8.getBasepath() + ts.getFile()).openStream(), writer);
writer.close();
System.out.println("视频段: " + ts + "下载完成");
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
} /**
* 解析M3U8地址为对象
* @param url M3U8地址
*/
static M3U8 parseIndex(String url) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream())); String basepath = url.substring(0, url.lastIndexOf("/") + 1); M3U8 ret = new M3U8();
ret.setBasepath(basepath); String line;
float seconds = 0;
while ((line = reader.readLine()) != null) {
if (line.startsWith("#")) {
if (line.startsWith("#EXTINF:")) {
line = line.substring(8);
if (line.endsWith(",")) {
line = line.substring(0, line.length() - 1);
}
if (line.contains(",")) {
line = line.substring(0, line.indexOf(","));
}
seconds = Float.parseFloat(line);
}
continue;
}
if (line.endsWith("m3u8")) {
return parseIndex(basepath + line);
}
ret.addTs(new M3U8Ts(line, seconds));
seconds = 0;
}
reader.close(); return ret;
} static class M3U8 {
private String basepath;
private List<M3U8Ts> tsList = new ArrayList<M3U8Ts>(); public String getBasepath() {
return basepath;
} public void setBasepath(String basepath) {
this.basepath = basepath;
} public List<M3U8Ts> getTsList() {
return tsList;
} public void setTsList(List<M3U8Ts> tsList) {
this.tsList = tsList;
} public void addTs(M3U8Ts ts) {
this.tsList.add(ts);
} @Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("basepath: " + basepath);
for (M3U8Ts ts : tsList) {
sb.append("\nts: " + ts);
} return sb.toString();
} } static class M3U8Ts {
private String file;
private float seconds; public M3U8Ts(String file, float seconds) {
this.file = file;
this.seconds = seconds;
} public String getFile() {
return file;
} public void setFile(String file) {
this.file = file;
} public float getSeconds() {
return seconds;
} public void setSeconds(float seconds) {
this.seconds = seconds;
} @Override
public String toString() {
return file + " (" + seconds + "sec)";
}
}
}
根据M3U8地址下载视频的更多相关文章
- 关于m3u8格式的视频文件ts转mp4下载和key加密问题
一,利用网站浏览器F12键,利用谷歌浏览器插件找到视频的.m3u8文件,并打开. 二,打开m3u8文件后,里面有很多.ts的链接,和key的链接. 三,保存为html文件,下载ts文件,代码如下:可加 ...
- 怎么下载腾讯课堂M3U8格式的视频
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 用过腾讯课堂的小伙伴们可能 ...
- Python3 根据m3u8下载视频,批量下载ts文件并且合并
Python3 根据m3u8下载视频,批量下载ts文件并且合并 m3u8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少 ...
- 关于怎么提取m3u8地址
摘自: https://blog.51cto.com/4373601/1920758 很长时间没有写博客了,这一段时间比较忙,接下来的日子要坚持写博客了,后期抽空会把这一年多的测试心得补上来,写博客其 ...
- M3U8地址在谷歌浏览器中播放
该案例git码云地址:https://gitee.com/kawhileonardfans/hls-player-example 1.下载插件 插件地址:https://files.cnblogs.c ...
- ffmpeg 安装,转视频格式为m3u8,压缩视频
# ffmpegffmpeg 安装,转视频格式为m3u8,压缩视频 ## ffmpeg 安装直接安装: apt-get install ffmpeg 运行 `ffmpeg` 看是否出现版本号以判断是否 ...
- 使用you-get下载视频网站视频或其他
使用you-get下载视频网站视频或其他 文/玄魂 目录 使用you-get下载视频网站视频或其他 前言 1.1 下载.安装 依赖 exe安装 pip安装 Antigen安装 Git 克隆源码 Hom ...
- 在Windows上安装FFmpeg程序的方法(you-get下载视频必备程序)
FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进的音频/视频编解码库libavcodec. 该程序 ...
- python you-get 下载视频
python使用you-get模块下载视频 pip install you-get # 安装先 怎么用 进入命令行: you-get url 暂停下载:ctrl + c ,继续下载重复 y ...
随机推荐
- MySQL 批量更新、删除数据shell脚本
#!/bin/bash. ~/.bash_profilelog=/tmp/update_log_1_$(date +%F).logvstart=1step=100vstop=$((${vstart}+ ...
- EventLoop
文章资料来自 Node.js 事件循环机制 JS灵魂之问(下) EventLoop的中国名字叫事件循环,这个玩意真的是高深莫测,一般开发都用不到,代码只管写就行,虽然不用懂,但是面试就是要问,这对我这 ...
- 微信小程序是什么
官方的开发文档 微信小程序写的不多,随便写写 创建项目,分析工具 微信小程序有专门的编辑工具,去官网下载 然后申请一个小程序项目,获得一个appId,然后进入编辑工具就可以直接开发了 编辑工具可以设置 ...
- ucosiii 移植
最近想在 f429 上面使用 mdk526 版本的 IDE,配合 HAL 和ucosiii.考虑到的方法是对比 v7 开发板的 ucosiii 和裸机程序,找出需要修改的地方,然后对比 v6 开发板的 ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-forward
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...
- 安装phpmyadmin数据可视化
1.下载压缩包,并且解压 cd /usr/local/src wget https://files.phpmyadmin.net/phpMyAdmin/4.9.4/phpMyAdmin-4.9.4-a ...
- 入门QT5 D1 Widget的移动
又重温了一遍C++之后来看QT教程了.QT之前也看过,不过都是很长时间之前了,一直也用到. 反过来再一学,这是和学新的是一样一样的. 首先创建新项目. 1.点击NEW PROJECT 2.Applit ...
- pandas中na_values与keep_default_na
我们在使用pandas读取文件时,常会遇到某个字段为NaN. 一般情况下,这时因为文件中包含空值导致的,因为pandas默认会将 '-1.#IND', '1.#QNAN', '1.#IND', '-1 ...
- sql ,类型转换,日期截取格式
字符型 转换成整型 CONVERT(int ,字段) 只取年月日格式 CONVERT(varchar(10), ZB.drive_time, 120 ) SELECT CONVERT(VARCHAR, ...
- 第四篇Django之模板语言
Django之模板语言 一 模板的执行 模板的创建过程,对于模板,其实就是读取模板(其中嵌套着模板的标签),然后将Model中获取的数据插入到模板中,最后将信息返回给用户 def current_da ...