ffmpeg实现视频转码

发布于:2025-04-15 ⋅ 阅读:(27) ⋅ 点赞:(0)

ffmpeg 实现视频转码

什么是视频编码

视频上传成功后需要对视频进行转码处理。

什么是视频编码?

查阅百度百科如下:

首先我们要分清文件格式和编码格式:

  • 文件格式:是指 .mp4.avi.rmvb
  • 这些不同扩展名的视频文件的文件格式,视频文件的内容主要包括视频和音频,其文件格式是按照一定的编码格式去编码,并且按照该文件所规定的封装格式将视频、音频、字幕等信息封装在一起,
  • 播放器会根据它们的封装格式去提取出编码,然后由播放器解码,最终播放音视频。

音视频编码格式:通过音视频的压缩技术,将视频格式转换成另一种视频格式,通过视频编码实现流媒体的传输。比如:一个 .avi 的视频文件原来的编码是 a,通过编码后编码格式变为 b,音频原来为 c,通过编码后变为 d。

音视频编码格式各类繁多,主要有几下几类:

  1. MPEG 系列

    • (由 ISO[国际标准组织机构] 下属的 MPEG[运动图象专家组] 开发 )视频编码方面主要是 Mpeg1(vcd 用的就是它)、Mpeg2(DVD 使用)、Mpeg4(的 DVDRIP 使用的都是它的变种,如:divx,xvid 等)、Mpeg4 AVC(正热门);
    • 音频编码方面主要是 MPEG Audio Layer 1/2、MPEG Audio Layer 3(大名鼎鼎的 mp3)、MPEG-2 AAC 、MPEG-4 AAC 等等。
    • 注意:DVD 音频没有采用 Mpeg 的。
  2. H.26X 系列

    • (由 ITU[国际电传视讯联盟] 主导,侧重网络传输,注意:只是视频编码)包括 H.261、H.262、H.263、H.263+、H.263++、H.264(就是 MPEG4 AVC-合作的结晶)
    • 目前最常用的编码标准是视频 H.264,音频 AAC。

提问:

H.264 是编码格式还是文件格式?

H.264(也称为 AVC,即高级视频编码)是一种视频编码格式,也就是一种视频压缩标准。它定义了如何对视频数据进行压缩、编码与解码。

  • 简单来说,H.264 描述的是视频数据的压缩算法,而不是存储文件的格式。
  • 通常,我们会将经过 H.264 编码的视频数据存储在不同的容器文件中,例如 MP4、MKV、AVI 等。

mp4 是编码格式还是文件格式?

MP4(MPEG-4 Part 14)是一种容器文件格式。它用于存储多媒体数据,比如视频、音频、字幕等。容器格式本身不定义视频或音频如何编码,而是作为一个“包装”,能够包含多种编码格式的数据。

常见的情况是:

  • 视频部分使用 H.264 编码,
  • 音频部分使用 AAC 编码,
  • 然后一起存储在 MP4 文件中。

小结

  • H.264:是一种视频编码标准,用于压缩视频数据。
  • MP4:是一种容器格式,用于存储音视频数据,可以包含使用 H.264 编码的视频和其他编码格式的音频数据。

代码示例

@Slf4j
public class FfmpegProcess {

    static String inputFile = VideoConstant.VIDEO_FILE_PATH1;
    static String inputFile2 = VideoConstant.VIDEO_INPUT_PATH;
    static String transcodeFile = VideoConstant.OUTPUT_FILE_PREFIX + "\\transcode.avi";
    
    public static void main(String[] args) throws Exception {
        String command = getVideoTranscodeCommand(inputFile2, transcodeFile);

        System.out.println("执行命令: " + command);
        // 创建操作系统进程
        ProcessBuilder builder = new ProcessBuilder();

        // 执行命令
        executeCommand(builder, command, "windows");

        // 合并标准输出和标准错误输出流
        builder.redirectErrorStream(true);
        Process process = builder.start();

        // 异步读取输出流,避免阻塞
        CompletableFuture<Void> future = readOutputAsync(process.getInputStream());

        int exitCode = process.waitFor();
        if (exitCode == 0) {
            System.out.println("执行成功");
        } else {
            System.err.println("执行过程中出现错误,退出代码:" + exitCode);
        }
    }

    /**
     * 获取视频转码的命令
     *
     * @param inputFile     输入文件路径
     * @param transcodeFile 转码文件路径
     * @return 视频转码的命令
     */
    private static String getVideoTranscodeCommand(String inputFile, String transcodeFile) {
        return String.format("%s -y -i %s %s", VideoConstant.FFMPEG_PATH, inputFile, transcodeFile);
    }

    /**
     * 异步读取 ffmpeg 输出流
     */
    private static CompletableFuture<Void> readOutputAsync(InputStream inputStream) {
        return CompletableFuture.runAsync(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                log.error("读取 ffmpeg 输出流异常", e);
            }
        });
    }

    /**
     * 执行命令
     *
     * @param builder 进程构建器
     * @param command 命令
     * @param osType  操作系统类型
     */
    private static void executeCommand(ProcessBuilder builder, String command, String osType) {
        switch (osType) {
            case "windows":
                builder.command("cmd", "/c", command);
                break;
            case "Linux":
            case "macOS":
                builder.command("bash", "-c", command);
                break;
            default:
                throw new RuntimeException("不支持的操作系统类型");
        }
    }
}

网站公告

今日签到

点亮在社区的每一天
去签到