利用简单的IO操作实现M3U8文件之间的合并
先上代码:
1 @SneakyThrows //合并操作,最终文件不包含结束标识,方便多次合并
2 private static void mergeM3U8File(String source, String target) {
3
4 //读取target
5 List<String> sl = new ArrayList<>();
6 try (BufferedReader reader = new BufferedReader(new FileReader(source))) {
7 String line;
8 while ((line = reader.readLine()) != null) {
9 sl.add(line);
10 }
11 }
12 //读取source
13 List<String> tl = new ArrayList<>();
14 try (BufferedReader reader = new BufferedReader(new FileReader(target))) {
15 String line;
16 while ((line = reader.readLine()) != null) {
17 tl.add(line);
18 }
19 }
20 //合并且统一ts文件名
21 String filename = target.replace(dir,"");
22 filename = filename.replace(".m3u8","");
23 Long order = 0l;
24 if (tl.size() <= 0) {
25 for (String s : sl) {
26 if(s.startsWith("#")) tl.add(s);
27 else {
28 tl.add(filename + order + ".ts");
29 log.info("转存文件 {}{} 存在状态 {}", dir, s, Files.exists(Paths.get(dir + s)));
30 Files.copy(Paths.get(dir + s), Paths.get(dir + filename + order + ".ts"));
31 Files.delete(Paths.get(dir + s));
32 order++;
33 }
34 }
35 }
36 else {
37 //删除结束段落
38 if(tl.get(tl.size()-1).startsWith("#EXT-X-ENDLIST")) {
39 tl.remove(tl.size() - 1);
40 }
41 //获取文件序号(dir+filename+order.ts)
42 String s = tl.get(tl.size() - 1);
43 s = s.replace(".ts","");
44 s = s.replace(filename,"");
45 order = Long.parseLong(s);
46 //sl处理 获取头部标识的下标并移除头部
47 int i = 0;
48 for (i = 0; i < sl.size(); i++) {
49 if (sl.get(i).startsWith("#EXTINF")) break;
50 }
51 for (int j = 0; j < i; j++) {
52 sl.remove(0);
53 }
54 sl.remove(sl.size() - 1);
55 tl.add("#EXT-X-DISCONTINUITY");
56 //sl文件内容写入tl
57 for (int j = 0; j < sl.size(); j++) {
58 String s1 = sl.get(j);
59 if(s1.startsWith("#EXTINF")) //#EXTINF
60 tl.add(s1);
61 else//按规则写入文件索引
62 {
63 order++;
64 tl.add(filename + order + ".ts");
65 log.info("转存文件 {}{} 存在状态 {}",dir,s1,Files.exists(Paths.get(dir + s1)));
66 Files.copy(Paths.get(dir + s1), Paths.get(dir + filename + order + ".ts"));
67 Files.delete(Paths.get(dir + s1));
68 }
69 }
70 }
71 //生成新的buffer
72 StringBuffer buffer = new StringBuffer();
73 for (String t : tl) {
74 buffer.append(t).append(System.lineSeparator());
75 }
76 //写入文件
77 try (BufferedWriter writer = new BufferedWriter(new FileWriter(target))) {
78 writer.write(buffer.toString());
79 }
80 //清除source
81 Files.delete(Paths.get(source));
82 }
83
84 @SneakyThrows //给m3u8文件添加结束标识
85 private static void endM3u8(String m3u8) {
86 List<String> sl = new ArrayList<>();
87 try (BufferedReader reader = new BufferedReader(new FileReader(m3u8))) {
88 String line;
89 while ((line = reader.readLine()) != null) {
90 sl.add(line);
91 }
92 }
93 sl.add("#EXT-X-ENDLIST");
94 //生成新的buffer
95 StringBuffer buffer = new StringBuffer();
96 for (String t : sl) {
97 buffer.append(t).append(System.lineSeparator());
98 }
99 //写入文件
100 try (BufferedWriter writer = new BufferedWriter(new FileWriter(m3u8))) {
101 writer.write(buffer.toString());
102 }
103
104 }
关于m3u8文件的说明:
- #EXTM3U:文件头,标识这是一个M3U8文件。
- #EXT-X-VERSION:表示M3U8的版本号。
- #EXT-X-TARGETDURATION:表示每个分段的最长时间(以秒为单位)。
- #EXT-X-MEDIA-SEQUENCE:表示播放列表中的第一个分段的编号。
- #EXTINF:表示当前分段的播放时间长度(以秒为单位)和URI。
- #EXT-X-ENDLIST:表示播放列表结束。
- #EXT-X-STREAM-INF:表示变换码率视频流中的音视频属性。
- #EXT-X-DISCONTINUITY:表示两个分段之间的不连续性。
- #EXT-X-PROGRAM-DATE-TIME:表示当前分段的播放时间点。
- #EXT-X-BYTERANGE:表示分段的字节范围。
合并代码中的m3u8文件的格式:
* #EXTM3U
* #EXT-X-VERSION:3
* #EXT-X-TARGETDURATION:2
* #EXT-X-MEDIA-SEQUENCE:0
* #EXT-X-PLAYLIST-TYPE:EVENT
* #EXTINF:1.441000,
* 2052636967-12640237988249000.ts
* #EXTINF:1.848000,
* 2052636967-12640237988249001.ts
* #EXT-X-ENDLIST
关于代码中的一些说明:
1、由于m3u8文件中的ts文件索引规则一般是 m3u8文件名+索引号,因此在合并文件之前需要先统一索引文件名;
2、由于m3u8文件之间是相互独立的,所以要在写入外部m3u8索引文件之前加入 #EXT-X-DISCONTINUITY 标识,否则播放器会在播放完第一部分的m3u8文件之后停止播放;
3、关于m3u8文件的结束行 #EXT-X-ENDLIST 问题,大部分播放器在未识别到结束标识且已经读取到文件最后一行索引时,会不断的请求m3u8文件,获取新资源,可以通过这个特新来实现直播效果;
利用简单的IO操作实现M3U8文件之间的合并的更多相关文章
- uniapp中拿到base64转blob对象,或base64转bytes字节数组,io操作写入字节流文件bytes
1. uniAPP中拿到附件的base64如何操作,如word文件 /*** 实现思路:* 通过native.js的io操作创建文件,拿到平台绝对路径* 再通过原生类进行base64解码,拿到字节流b ...
- Python中的文件IO操作(读写文件、追加文件)
Python中文件的读写包含三个步骤:打开文件,读/写文件,关闭文件. 文件打开之后必须关闭,因为在磁盘上读写文件的功能是由操作系统提供的,文件作为对象,被打开后会占用操作系统的资源,而操作系统在同一 ...
- [python 学习] IO操作之读写文件
一.读取全部文件: # -*- coding: utf-8 -*- f = open('qq_url.txt','r'); print f.read(); f.close(); 二.读取规定长度文件 ...
- python 利用三方的xlrd模块读取excel文件,处理合并单元格
目的: python能使用xlrd模块实现对Excel数据的读取,且按照想要的输出形式. 总体思路: (1)要想实现对Excel数据的读取,需要用到第三方应用,直接应用. (2)实际操作时候和我 ...
- 【UNIX环境高级编程】文件 IO 操作 一 ( open | close | creat | lseek | write | read )
博客地址 : http://blog.csdn.net/shulianghan/article/details/46980271 一. 文件打开关闭操作相关函数介绍 1. open 函数 (1) op ...
- C# IO操作(二)File类和Directory类的常用方法
本篇主要介绍一些常用的IO操作,对文件和目录的操作:留给自己复习之用. 1.创建文件 string sPath1=Path.GetDirectoryName(Assembly.GetExecuting ...
- Linux系统编程:简单文件IO操作
使用Linux的文件API,经常看见一个东西,叫做文件描述符. 什么是文件描述符? (1)文件描述符其实实质是一个数字,这个数字在一个进程中表示一个特定的含义,当我们open打开一个文件时,操作系统在 ...
- [.NET] 利用 async & await 进行异步 IO 操作
利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html 序 上次,博主 ...
- 文件IO操作
前言 本文介绍使用java进行简单的文件IO操作. 操作步骤 - 读文件 1. 定义一个Scanner对象 2. 调用该对象的input函数族进行文件读取 (参见下面代码) 3. 关闭输入流 说明:其 ...
- 树莓派学习笔记——使用文件IO操作GPIO SysFs方式
0 前言 本文描写叙述假设通过文件IO sysfs方式控制树莓派 GPIO端口.通过sysfs方式控制GPIO,先訪问/sys/class/gpio文件夹,向export文件写入GPIO编号, ...
随机推荐
- Cesium渲染模块之Command
1. 引言 Cesium是一款三维地球和地图可视化开源JavaScript库,使用WebGL来进行硬件加速图形,使用时不需要任何插件支持,基于Apache2.0许可的开源程序,可以免费用于商业和非商业 ...
- Redis使用ZSET实现消息队列使用总结一
转载请注明出处: 目录 1.zset为什么可以做消息队列 2.zset实现消息队列的步骤 3.使用jedis实现消息队列示例 4.+inf与-inf 5.redis使用list与zset做消息队列有什 ...
- 解读 Servlet 源码:GenericServlet,ServletConfig,ServletContext
解读 Servlet 源码:GenericServlet,ServletConfig,ServletContext 每博一文案 人活着,就得随时准备经受磨难.他已经看过一些书,知道不论是普通人还是了不 ...
- 【git】学习笔记
一.git原理 git只能跟踪文本文件的变化,比如txt文件.程序代码等.而对于图片.视频等二进制文件的变化,就无法知道变化了哪里. git 分支的理解:如下图所示,git分支可以理解为是一个指针以及 ...
- CentOS 7下安装windows字体
1.在日常生产中打开文件时发现中文乱码,考虑到编码或者是否有中文字体库,在CentOS 7中执行命令发现字体列表命令无效. 上图发现字体库都没安装,接下来就会简单说一下CentOS 7 中安装字体库和 ...
- JQ-DOM与元素的操作
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 基于Label studio实现UIE信息抽取智能标注方案,提升标注效率!
基于Label studio实现UIE信息抽取智能标注方案,提升标注效率! 项目链接见文末 人工标注的缺点主要有以下几点: 产能低:人工标注需要大量的人力物力投入,且标注速度慢,产能低,无法满足大规模 ...
- 系统评价——层次分析法AHP的R语言实现(四)
对一个事物的评价往往会涉及多个因素或者多个指标,评价是在多个因素相互作用下的一个综合判断.多指标综合评价方法具有以下的特点:包含若干个指标,分别说明被评价对象的不同方面,评价方法最终要对被评价对象作出 ...
- day103:MoFang:用户登录部分:客户端提交登录信息&APICloud集成防水墙验证码&保存用户登录状态
目录 bug:修复jsonrpc修改源码以后celery无法运行的问题 1.客户端提交登录信息 2.在APICloud中集成防水墙验证码 3.保存用户登录状态 bug:修复jsonrpc修改源码以后c ...
- Oracle AUD审计 找出锁定用户的客户端IP
问题描述:运用AUD审计找出锁定用户的客户端IP 1.查询被锁用户 SELECT USERNAME, ACCOUNT_STATUS, LOCK_DATE FROM DBA_USERS WHERE AC ...