Java转成m3u8,hls格式
Java转成m3u8,hls格式
需求分析
大致思路
- 循环文件夹下面所有文件
- 判断当前文件是否是视频文件,如果是视频文件先转为ts文件
- 因为听别人说先转成ts之后再切片会快很多
- 转成ts文件,并为这些文件单独生成一个目录,如果目录不存在则新建一个目录
- 执行转换命令—转成ts文件
- 执行完成后,再将ts文件转成m3u8文件
详细流程
- 判断当前文件夹是否是一个目录
- 如果是目录就遍历下面的文件包括所以的文件。
- 循环这些子文件,如果当前的文件是文件并且是视频文件(写一个判断函数,因为格式不同)
- 循环完成后将这些视频转成ts,并为这些文件生成单独目录,转成ts文件命名为
output.ts
- 需要为这些文件单独写一个执行命令函数(封装)
- 转成ts后再将这些视频转成m3u8
方法实现
判断是否为文件函数
在类中定义正则表达式,以方便修改。
函数中使用文件名后缀方式判断当前文件是否是符合要求的视频文件。
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";/*** 判断是否符合想要的格式* mp4|avi|mkv* 通过文件后缀名哦安短** @param fileName 文件名称* @return 布尔值*/
private static boolean isVideoFile(String fileName) {return fileName.matches(isVideoFileRegex);
}
执行命令函数
因为在使用过程中需要使用两次命令行的操作,使用Java调起命令行,这是可以封装成单独的函数,使用时只需要将命令行传入即可。
命令行解释
创建了一个 ProcessBuilder
对象,并使用给定的命令字符串初始化它。ProcessBuilder
类用于创建操作系统进程,并提供一种从 Java 程序中启动外部命令的方式。
command.split(" ")
将输入的命令字符串分割成一个字符串数组,每个数组元素都是一个命令或参数。然后,这个数组被用来初始化 ProcessBuilder
对象,以便在后续步骤中启动一个新的进程来执行这些命令。
processBuilder.redirectErrorStream(true)
设置了当启动的进程产生错误流时,将错误流合并到标准输出流中。这意味着在执行命令时,任何由该命令生成的错误输出将会与标准输出一起被捕获,并可以通过 Java 程序进行处理。
ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));
processBuilder.redirectErrorStream(true);
processBuilder.start()
启动了之前创建的ProcessBuilder
对象,执行之前设置的命令。BufferedReader
对象将其连接到外部进程的标准输出流,程序可以读取外部进程的输出。这里使用了InputStreamReader
将字节流转换为字符流,然后通过BufferedReader
逐行读取外部进程的输出。- 在一个
while
循环中,程序持续读取外部进程的输出,直到输出结束。每读取一行输出,该行内容被打印到控制台上。 - 之后,通过调用
process.waitFor()
,程序会等待外部进程执行完毕。这会导致当前的线程暂停,直到外部进程执行完成。
try {Process process = processBuilder.start();// 将ffmpeg执行内容输出在控制台中BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待转换完成process.waitFor();
} catch (IOException | InterruptedException e) {throw new RuntimeException(e);
}
完整代码
// 输入文件夹
private static String inputDirectory = "C:\\Users\\13199\\Downloads";
// 输出m3u8文件
private static String outputM3u8FileName = "index.m3u8";
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";
// 选择切片时间
private static Integer HlsTime = 1;/*** 执行将文件转成m3u8 hls格式** @param command Ffmpeg 命令*/
private static void executeFfmpegCommand(String command) {ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));processBuilder.redirectErrorStream(true);try {Process process = processBuilder.start();// 将ffmpeg执行内容输出在控制台中BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待转换完成process.waitFor();} catch (IOException | InterruptedException e) {throw new RuntimeException(e);}
}
转成ts
- 根据输入文件路径
inputFilePath
确定了输出目录outputDirectory
。使用正则表达式\\.[^.]+$
来匹配文件路径中的文件扩展名,并将其替换为空字符串,从而得到输出目录的路径。 - 创建了一个
File
对象来代表输出目录,并检查该目录是否存在。如果输出目录不存在,用mkdirs()
方法来创建输出目录。 - 构建了一个输出文件的路径
outputFilePath
,这里假设输出文件的名称为 “output.ts”,并将其放在之前确定的输出目录中。 - FFmpeg 命令字符串
command
,该命令使用输入文件路径来进行转换,具体命令包括了输入文件、编解码器选项、关键帧选项等参数。 executeFfmpegCommand
将构建的 FFmpeg 命令字符串作为参数传递给该方法,以执行 FFmpeg 命令。- 最后,代码调用了一个名为
convertToM3U8
的方法,该方法可能用于将生成的视频文件转换为 M3U8 格式
// 输入文件夹
private static String inputDirectory = "C:\\Users\\13199\\Downloads";
// 输出m3u8文件
private static String outputM3u8FileName = "index.m3u8";
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";
// 选择切片时间
private static Integer HlsTime = 1;/*** 如果文件名 后缀符合将文件先转成ts类型文件* 有实验表名,先转成ts会快一点** @param inputFilePath 当前文件的路径*/
private static void convertToTs(String inputFilePath) {String outputDirectory = inputFilePath.replaceFirst("\\.[^.]+$", "");File directory = new File(outputDirectory);if (!directory.exists()) {directory.mkdirs();}String outputFilePath = outputDirectory + File.separator + "output.ts";String command = "ffmpeg -i " + inputFilePath + " -c copy -bsf:v h264_mp4toannexb -force_key_frames expr:gte(t,n_forced*" + HlsTime + ") -f mpegts " + outputFilePath;executeFfmpegCommand(command);convertToM3U8(outputDirectory);
}
转成m3u8
输出文件的路径 outputFilePath
,这个路径是由输入目录 inputDirectory
和一个名为 outputM3u8FileName
之后将这段代码放到之前封装好的执行命令函数中executeFfmpegCommand
// 输入文件夹
private static String inputDirectory = "C:\\Users\\13199\\Downloads";
// 输出m3u8文件
private static String outputM3u8FileName = "index.m3u8";
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";
// 选择切片时间
private static Integer HlsTime = 1;/*** 将文件转成hls类型,并且m3u8命名为index* 切片的ts以output.ts转换** @param inputDirectory 输入的文件夹*/
private static void convertToM3U8(String inputDirectory) {// 使用FFmpeg将ts文件转换成m3u8文件String outputFilePath = inputDirectory + File.separator + outputM3u8FileName;String command = "ffmpeg -i " + inputDirectory + File.separator + "output.ts" + " -c:v libx264 -c:a aac -force_key_frames expr:gte(t,n_forced*" + HlsTime + ") -hls_time " + HlsTime + " -hls_list_size 0 -f hls " + outputFilePath;executeFfmpegCommand(command);
}
自定义ts输出名
需要使用-hls_segment_filename
参数。这个参数可以帮助你自定义切片文件的命名规则。
如果要将输入的ts文件以1,2,3这种方式命名可以使用这个方法inputDirectory + File.separator + "%d.ts"
String segmentFilename = inputDirectory + File.separator + "%d.ts"; // 定义切片文件名规则
String command = "ffmpeg -i " + inputDirectory + File.separator + "output.ts" + " -c:v libx264 -c:a aac -force_key_frames expr:gte(t,n_forced*1) -hls_time 1 -hls_list_size 0 -f hls -hls_segment_filename " + segmentFilename + " " + outputFilePath; // 定义切片文件名规则
executeFfmpegCommand(command);
主函数
- 创建了一个
File
对象来代表输入目录inputDirectory
。 - 检查输入目录是否存在,并且确保它是一个目录而不是一个文件。
- 如果输入目录存在且是一个目录,获取了该目录下的所有文件列表,并遍历这些文件。
- 在遍历文件列表时,对每个文件进行检查,确保它是一个文件并且文件扩展名表明它是一个视频文件(使用了
isVideoFile
方法进行检查)。 - 对于每个找到的视频文件,代码创建了一个新的线程,并在该线程中调用了
convertToTs
方法,传递视频文件的绝对路径作为参数,以启动视频文件的转换过程。
// 输入文件夹
private static String inputDirectory = "C:\\Users\\13199\\Downloads";
// 输出m3u8文件
private static String outputM3u8FileName = "index.m3u8";
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";
// 选择切片时间
private static Integer HlsTime = 1;/*** 定义目录所在位置* 循环遍历这个目录文件,找到子目录的视频文件* 判断当前的文件是否是视频文件* 如果是文件夹则继续遍历** @param args main program arguments*/
public static void main(String[] args) {File directory = new File(inputDirectory);if (directory.isDirectory()) {File[] files = directory.listFiles();assert files != null;for (File file : files) {if (file.isFile() && isVideoFile(file.getName())) {String inputFilePath = file.getAbsolutePath();new Thread(() -> convertToTs(inputFilePath)).start();}}}
}
常规变量
// 输入文件夹
private static String inputDirectory = "C:\\Users\\13199\\Downloads";
// 输出m3u8文件
private static String outputM3u8FileName = "index.m3u8";
// 判断是否是视频文件正则
private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";
// 选择切片时间
private static Integer HlsTime = 1;
完整代码
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;@Data
public class NewTest {// 输入文件夹private static String inputDirectory = "C:\\Users\\13199\\Downloads";// 输出m3u8文件private static String outputM3u8FileName = "index.m3u8";// 判断是否是视频文件正则private static String isVideoFileRegex = ".*\\.(mp4|avi|mkv)$";// 选择切片时间private static Integer HlsTime = 1;/*** 定义目录所在位置* 循环遍历这个目录文件,找到子目录的视频文件* 判断当前的文件是否是视频文件* 如果是文件夹则继续遍历** @param args main program arguments*/public static void main(String[] args) {File directory = new File(inputDirectory);if (directory.isDirectory()) {File[] files = directory.listFiles();assert files != null;for (File file : files) {if (file.isFile() && isVideoFile(file.getName())) {String inputFilePath = file.getAbsolutePath();new Thread(() -> convertToTs(inputFilePath)).start();}}}}/*** 如果文件名 后缀符合将文件先转成ts类型文件* 有实验表名,先转成ts会快一点** @param inputFilePath 当前文件的路径*/private static void convertToTs(String inputFilePath) {String outputDirectory = inputFilePath.replaceFirst("\\.[^.]+$", "");File directory = new File(outputDirectory);if (!directory.exists()) {directory.mkdirs();}String outputFilePath = outputDirectory + File.separator + "output.ts";String command = "ffmpeg -i " + inputFilePath + " -c copy -bsf:v h264_mp4toannexb -force_key_frames expr:gte(t,n_forced*" + HlsTime + ") -f mpegts " + outputFilePath;executeFfmpegCommand(command);convertToM3U8(outputDirectory);}/*** 将文件转成hls类型,并且m3u8命名为index* 切片的ts以output.ts转换** @param inputDirectory 输入的文件夹*/private static void convertToM3U8(String inputDirectory) {// 使用FFmpeg将ts文件转换成m3u8文件String outputFilePath = inputDirectory + File.separator + outputM3u8FileName;String command = "ffmpeg -i " + inputDirectory + File.separator + "output.ts" + " -c:v libx264 -c:a aac -force_key_frames expr:gte(t,n_forced*" + HlsTime + ") -hls_time " + HlsTime + " -hls_list_size 0 -f hls " + outputFilePath;executeFfmpegCommand(command);}/*** 执行将文件转成m3u8 hls格式** @param command Ffmpeg 命令*/private static void executeFfmpegCommand(String command) {ProcessBuilder processBuilder = new ProcessBuilder(command.split(" "));processBuilder.redirectErrorStream(true);try {Process process = processBuilder.start();// 将ffmpeg执行内容输出在控制台中BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));String line;while ((line = reader.readLine()) != null) {System.out.println(line);}// 等待转换完成process.waitFor();} catch (IOException | InterruptedException e) {throw new RuntimeException(e);}}/*** 判断是否符合想要的格式* mp4|avi|mkv* 通过文件后缀名哦安短** @param fileName 文件名称* @return 布尔值*/private static boolean isVideoFile(String fileName) {return fileName.matches(isVideoFileRegex);}
}
相关文章:
Java转成m3u8,hls格式
Java转成m3u8,hls格式 需求分析 大致思路 循环文件夹下面所有文件判断当前文件是否是视频文件,如果是视频文件先转为ts文件 因为听别人说先转成ts之后再切片会快很多 转成ts文件,并为这些文件单独生成一个目录,如果目录不存在则新建一个目…...

jmeter之接口测试实现参数化(利用函数助手),参数值为1-9(自增的数字)
1.前言 思考:为什么不用postman,用postman的话就得导入csv文件/json文件 如果不想导入文件,postman是实现不了,因为postman每次只会运行一次 2.jmeter函数助手实现参数化 (1)新建“线程组”--新建“http…...

如何在 Ubuntu 22.04 上安装 Apache Web 服务器
前些天发现了一个人工智能学习网站,通俗易懂,风趣幽默,最重要的屌图甚多,忍不住分享一下给大家。点击跳转到网站。 如何在 Ubuntu 22.04 上安装 Apache Web 服务器 介绍 Apache HTTP 服务器是世界上使用最广泛的 Web 服务器。它…...

【python爬虫】爬虫编程技术的解密与实战
🌈个人主页:Sarapines Programmer🔥 系列专栏: 爬虫】网络爬虫探秘⏰诗赋清音:云生高巅梦远游, 星光点缀碧海愁。 山川深邃情难晤, 剑气凌云志自修。 目录 🌼实验目的 …...

VisualSVN Server下载安装和使用方法、服务器搭建、使用TortoiseSvn将项目上传到云端服务器、各种错误解决方法
VisualSVN Server下载安装和使用方法、服务器搭建、使用TortoiseSvn将项目上传到云端服务器、各种错误解决方法 0.写在前面00.电脑配置01.思路 1.VisualSVN Server下载安装01.下载02.安装03.电脑命名不能有中文04.制作VisualSVN Server快捷方式05.License limits exceeded, Som…...

Python模块与包:扩展功能、提高效率的利器
文章目录 一、引言1.1 模块与包对于Python开发的重要性1.2 Python作为拥有丰富生态系统的编程语言 二、为什么学习模块与包2.1 复用代码:利用现有模块与包加速开发过程2.2 扩展功能:通过模块与包提供的功能增强应用的能力 三、模块的使用3.1 导入模块&am…...

【每日一题】4.LeetCode——杨辉三角
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有限,欢迎各位大佬指点&…...

蓝桥杯(Python)每日练Day5
题目 OJ1229 题目分析 题目完全符合栈的特征,后进先出。如果能够熟练使用列表的9种方法那么这道题很容易解出。 题解 a[]#存衣服 nint(input()) for i in range(n):llist(input().split())#判断每一步的操作if len(l[0])2:a.append(l[1])else:while a.pop()!l…...

SpringCloud(二)
Spring Cloud 文章目录 Spring Cloud任务三:Spring Cloud与微服务架构1.Spring Cloud课程内容介绍2.单体应用架构2.1 互联网应用架构演进2.2 单体应用架构 3.垂直应用架构4.SOA应用架构5.微服务应用架构介绍6.微服务架构核心思想及优缺点7.微服务架构的核心概念8.Sp…...

【java】常见的面试问题
目录 一、异常 1、 throw 和 throws 的区别? 2、 final、finally、finalize 有什么区别? 3、try-catch-finally 中哪个部分可以省略? 4、try-catch-finally 中,如果 catch 中 return 了,finally 还会执行吗&#…...

虚幻UE 插件-像素流送实现和优化
本笔记记录了像素流送插件的实现和优化过程。 UE version:5.3 文章目录 一、像素流送二、实现步骤1、开启像素流送插件2、设置参数3、打包程序4、打包后的程序进行像素流参数设置5、下载NodeJS6、下载信令服务器7、对信令服务器进行设置8、启动像素流送 三、优化1、…...

Vue2 props组件通信
一、父组件向子组件传值 1、流程图 2、父组件代码 <template><div class"app"><UserInfo:usernameusername:ageage:isSingleisSingle:carcar:hobbyhobby></UserInfo></div> </template><script> import UserInfo from .…...

重构改善既有代码的设计-学习(三):重新组织数据
1、拆分变量(Split Variable) 有些变量用于保存一段冗长代码的运算结果,以便稍后使用。这种变量应该只被赋值一次。 如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任,它就应该被…...
群狼调研(长沙品牌忠诚度测试)|广告效果测评方法
广告效果测评方法可以根据具体的目标和需求而有所差异,以下是一些常见的广告效果测评方法: 1.品牌调研和调查:通过定量或定性的调研和调查方法,评估广告对品牌认知、品牌形象和品牌偏好的影响,包括品牌知名度、品牌关联…...

Gradle学习笔记:Gradle的使用方法
文章目录 1.初始化项目2.构建脚本语言选择3.项目命名4.项目构建过程 1.初始化项目 创建一个test空文件夹,在该文件夹下打开终端,并执行命令:gradle init. 会有一个选项让你选择项目的类型。下面是每个选项的含义和用途: basic&am…...

少儿编程 2023年12月电子学会图形化编程等级考试Scratch二级真题解析(选择题)
2023年12月scratch编程等级考试二级真题 选择题(共25题,每题2分,共50分) 1、在制作推箱子游戏时,地图是用数字形式储存在电脑里的,下图是一个推箱子地图,地图表示如下:第一行( 111111)第二行( 132231) 第三行( 126621) 第四行( ) 第五行( 152321) 第六行( 111111 ) 根…...

基于Java+SpringMvc+vue+element实现上海汽车博物馆平台
基于JavaSpringMvcvueelement实现上海汽车博物馆平台 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系统 …...

Sybase PowerDesigner15安装配置
1,软件介绍 Power Designer 是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型,还可以为数据仓…...

基于物联网设计的水稻田智能灌溉系统(STM32+华为云IOT)
一、项目介绍 随着科技的不断发展和人们生活水平的提高,农业生产也逐渐向智能化、高效化的方向发展。水稻作为我国主要的粮食作物之一,其生长过程中的灌溉管理尤为重要。传统的灌溉方式往往依赖于人工观察和控制,不仅效率低下,而…...

【数据结构】数据结构初识
前言: 数据结构是计算存储,组织数据的方式。数据结构是指相互间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 Data Structure Vi…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...