You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何利用FFMPEG Java包装库创建HLS主播放列表及分段元数据

我完全懂你现在的困扰——不少Java FFmpeg包装库能搞定基础编码和单码率HLS分段,但要生成带多分辨率、多带宽的主播放列表和对应变体流,确实没那么容易。结合你的需求,我给你两个靠谱的解决方案:

一、用活跃的Java FFmpeg包装库实现:Jaffree

Jaffree是目前维护最活跃的Java FFmpeg包装库之一,它既可以封装FFmpeg底层API,也能灵活构建FFmpeg命令并执行,对HLS多变体流的支持非常到位,完全能满足你生成主元数据文件+多码率分段的需求。

代码示例(生成多码率HLS主播放列表)

import io.github.kokorin.jaffree.ffmpeg.FFmpeg;
import io.github.kokorin.jaffree.ffmpeg.Input;
import io.github.kokorin.jaffree.ffmpeg.Output;

public class MultiBitrateHlsGenerator {
    public static void main(String[] args) {
        FFmpeg.atPath()
                // 输入源文件
                .addInput(Input.fromPath("input.mp4"))
                // 生成720p变体流:码率2M,带宽2500k
                .addOutput(Output.toPath("hls/720p.m3u8")
                        .addArguments("-c:v", "libx264", "-crf", "23", "-preset", "medium")
                        .addArguments("-c:a", "aac", "-b:a", "128k")
                        .addArguments("-s", "1280x720", "-b:v", "2000k")
                        .addArguments("-hls_time", "10", "-hls_list_size", "0"))
                // 生成480p变体流:码率1M,带宽1200k
                .addOutput(Output.toPath("hls/480p.m3u8")
                        .addArguments("-c:v", "libx264", "-crf", "23", "-preset", "medium")
                        .addArguments("-c:a", "aac", "-b:a", "128k")
                        .addArguments("-s", "854x480", "-b:v", "1000k")
                        .addArguments("-hls_time", "10", "-hls_list_size", "0"))
                // 生成主播放列表,并映射变体流的元数据
                .addArguments("-master_pl_name", "master.m3u8")
                .addArguments("-var_stream_map", 
                        "v:0,a:0,bandwidth=2500000,resolution=1280x720,name:720p " +
                        "v:1,a:1,bandwidth=1200000,resolution=854x480,name:480p")
                .execute();
    }
}

这段代码会自动生成:

  • master.m3u8主播放列表(包含两个变体流的引用及带宽、分辨率元数据)
  • 720p.m3u8/480p.m3u8媒体播放列表
  • 对应分辨率的TS分段文件

二、直接调用FFmpeg命令行(你提到的方案)

如果包装库的灵活性达不到预期,直接执行FFmpeg命令是最稳妥的选择——毕竟FFmpeg本身对HLS多码率的支持非常成熟,能覆盖所有自定义需求。

示例FFmpeg命令

ffmpeg -i input.mp4 \
  # 720p变体流配置
  -c:v libx264 -crf 23 -preset medium -s 1280x720 -b:v 2000k \
  -c:a aac -b:a 128k \
  -hls_time 10 -hls_list_size 0 -hls_segment_filename "hls/720p_%03d.ts" hls/720p.m3u8 \
  # 480p变体流配置
  -c:v libx264 -crf 23 -preset medium -s 854x480 -b:v 1000k \
  -c:a aac -b:a 128k \
  -hls_time 10 -hls_list_size 0 -hls_segment_filename "hls/480p_%03d.ts" hls/480p.m3u8 \
  # 生成主播放列表
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0,bandwidth=2500000,resolution=1280x720,name:720p v:1,a:1,bandwidth=1200000,resolution=854x480,name:480p"

Java中执行命令的示例

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class FFmpegCommandRunner {
    public static void main(String[] args) throws IOException, InterruptedException {
        ProcessBuilder pb = new ProcessBuilder(
                "ffmpeg",
                "-i", "input.mp4",
                // 720p参数
                "-c:v", "libx264", "-crf", "23", "-preset", "medium", "-s", "1280x720", "-b:v", "2000k",
                "-c:a", "aac", "-b:a", "128k",
                "-hls_time", "10", "-hls_list_size", "0", "-hls_segment_filename", "hls/720p_%03d.ts", "hls/720p.m3u8",
                // 480p参数
                "-c:v", "libx264", "-crf", "23", "-preset", "medium", "-s", "854x480", "-b:v", "1000k",
                "-c:a", "aac", "-b:a", "128k",
                "-hls_time", "10", "-hls_list_size", "0", "-hls_segment_filename", "hls/480p_%03d.ts", "hls/480p.m3u8",
                // 主播放列表参数
                "-master_pl_name", "master.m3u8",
                "-var_stream_map", "v:0,a:0,bandwidth=2500000,resolution=1280x720,name:720p v:1,a:1,bandwidth=1200000,resolution=854x480,name:480p"
        );

        // 重定向错误流到输出流,方便排查问题
        pb.redirectErrorStream(true);
        Process process = pb.start();

        // 启动线程读取输出,避免进程阻塞
        new Thread(() -> {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 等待命令执行完成
        int exitCode = process.waitFor();
        System.out.println("FFmpeg执行完成,退出码:" + exitCode);
    }
}

关键参数说明

  • -master_pl_name: 指定生成的主播放列表文件名
  • -var_stream_map: 核心参数,用于映射变体流并指定带宽、分辨率、名称等元数据(如果不显式指定带宽,FFmpeg会自动计算)
  • -hls_time: 每个媒体分段的时长(单位:秒)
  • -hls_list_size: 设置为0表示保留所有分段文件,不自动清理旧分段

注意事项

  • 确保使用FFmpeg 4.0及以上版本,旧版本可能不支持部分HLS多变体流参数
  • 用Java包装库时,注意依赖的FFmpeg平台包要适配你的操作系统(比如Jaffree的ffmpeg-platform会自动适配)
  • 处理大文件时,一定要用线程读取输出流,避免缓冲区满导致进程阻塞

内容的提问来源于stack exchange,提问作者Caffeinated Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:56:49