定义了两个用于处理视频文件的命令字符串,分别用于将视频文件转换为TS格式和将TS文件进行分割。下面是对这两个命令的详细说明:
1. 将视频文件转换为TS格式
final String CMD_TRANSFER_2TS="ffmpeg -y -i %s -vcodec copy -vbsf h264_mp4toannexb %s";
ffmpeg
: 调用FFmpeg工具。-y
: 覆盖输出文件而不提示。-i %s
: 输入文件,%s
是一个占位符,将在实际使用时替换为输入文件路径。-vcodec copy
: 直接复制视频流,而不重新编码。-vbsf h264_mp4toannexb
: 使用 H.264 比特流过滤器,将 H.264 流从MP4容器转换为Annex B格式。%s
: 输出文件,另一个占位符,将在实际使用时替换为输出文件路径。
2. 将TS文件分割
final String CMD_CUT_TS="ffmpeg -i %s -c copy -map 0 -f segment -segment_list %s -segment_time 30 %s/%s_%%4d.ts";
ffmpeg
: 调用FFmpeg工具。-i %s
: 输入文件,%s
是一个占位符,将在实际使用时替换为输入文件路径。-c copy
: 直接复制音视频流,而不重新编码。-map 0
: 映射所有流(视频、音频和字幕)。-f segment
: 使用segment
多路复用器,分割文件。-segment_list %s
: 指定用于保存分割文件列表的文件路径,%s
是一个占位符,将在实际使用时替换。-segment_time 30
: 每个片段的时长为30秒。%s/%s_%%4d.ts
: 输出文件的路径和命名格式,前两个%s
占位符将在实际使用时替换为目录路径和文件前缀,%%4d
表示4位数字编号。
示例使用
为了更好地理解如何使用这些命令,可以看一个具体的示例。假设我们有一个名为 input.mp4
的视频文件,我们想将其转换为TS格式并分割成30秒的片段。
转换为TS格式
String inputFilePath = "[input.mp](http://input.mp)4";
String outputFilePath = "output.ts";
String cmdTransfer2Ts = String.format(CMD_TRANSFER_2TS, inputFilePath, outputFilePath);
System.out.println(cmdTransfer2Ts);
// 运行命令
// ffmpeg -y -i [input.mp](http://input.mp)4 -vcodec copy -vbsf h264_mp4toannexb output.ts
分割TS文件
String inputTsFilePath = "output.ts";
String segmentListPath = "segments.m3u8";
String outputDir = "segments";
String outputFilePrefix = "segment";
String cmdCutTs = String.format(CMD_CUT_TS, inputTsFilePath, segmentListPath, outputDir, outputFilePrefix);
System.out.println(cmdCutTs);
// 运行命令
// ffmpeg -i output.ts -c copy -map 0 -f segment -segment_list segments.m3u8 -segment_time 30 segments/segment_%4d.ts
执行命令
在实际应用中,你可能会在Java代码中使用 Runtime.getRuntime().exec()
或 ProcessBuilder
来执行这些命令:
#### 使用 Runtime.getRuntime().exec()
try {
• // 执行转换命令
• Process process1 = Runtime.getRuntime().exec(cmdTransfer2Ts);
• process1.waitFor();
• // 执行分割命令
• Process process2 = Runtime.getRuntime().exec(cmdCutTs);
• process2.waitFor();
} catch (IOException | InterruptedException e) {
• e.printStackTrace();
}
使用 ProcessBuilder
try {
• // 执行转换命令
• ProcessBuilder pb1 = new ProcessBuilder(cmdTransfer2Ts.split(" "));
• Process process1 = pb1.start();
• process1.waitFor();
• // 执行分割命令
• ProcessBuilder pb2 = new ProcessBuilder(cmdCutTs.split(" "));
• Process process2 = pb2.start();
• process2.waitFor();
} catch (IOException | InterruptedException e) {
• e.printStackTrace();
}
这样,你就可以在Java程序中使用FFmpeg命令来处理视频文件了。
public class ScaleFilter {
private static final Logger logger= LoggerFactory.getLogger(ScaleFilter.class);
//用于从视频文件中提取一帧图片,并对图片进行缩放。以下是每个参数的含义:
//-i %s: 输入视频文件的路径,%s 是一个占位符,表示视频文件的路径。
//-y: 强制覆盖输出文件,如果输出文件已经存在。
//-vframes 1: 只提取一帧。
//-vf scale=%d:%d/a: 应用视频滤镜 scale 进行缩放,其中 %d 和 %d 是占位符,分别表示宽度和高度。/a 表示按原视频的宽高比进行调整。
//%s: 输出文件的路径,占位符表示输出图片文件的路径。
public static void createCover(File sourceFile, Integer width, File targeFile,Boolean outprintLog){
try {
String cmd="ffmpeg -i %s -y -vframes 1 -vf scale=%d:%d/a %s";
ProcessUtil.executeCommand(String.format(cmd,sourceFile.getAbsolutePath(),width,width,targeFile.getAbsolutePath()),
outprintLog);
}catch (Exception e){
logger.error("生成封面失败",e);
}
}
/**
* 图片压缩
* @param file
* @param thumbnailWith
* @param targetFile
* @param delSource
* @return
*/
public static Boolean createThumbnailWidthFFmpeg(File file,int thumbnailWith,File targetFile,Boolean delSource,Boolean outprintLog){
try {
BufferedImage src= ImageIO.read(file);
//
int sorceW=src.getWidth();
int sorceH=src.getHeight();
//
if (sorceW <= thumbnailWith){
return false;
}
compressImage(file,thumbnailWith,targetFile,delSource,outprintLog);
return true;
}catch (Exception e){
e.printStackTrace();
}
return false;
}
public static void compressImage(File sourceFile,int width,File targetFile,Boolean delSource,Boolean outprintLog){
try {
String cmd = "ffmpeg -i %s -vf scale=%d:-1 %s -y";
ProcessUtil.executeCommand(String.format(cmd,sourceFile.getAbsolutePath(),width,targetFile.getAbsolutePath()),outprintLog);
if (delSource){
FileUtils.deleteDirectory(sourceFile);
}
}catch (Exception e){
logger.error("压缩图片失败");
}
}
}