定义了两个用于处理视频文件的命令字符串,分别用于将视频文件转换为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("压缩图片失败");
        }
    }
}

刚学java菜鸡,永劫无间蚀月,王者荣耀王者,金铲铲小铂金,第五人格菜鸡,原神开服玩家,星穹铁道菜鸡,崩坏的菜鸡,闪耀暖暖,和平精英,LOL,CSGO,以及三A大作收集者等等。。。