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…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...