Java - 同时将视频和音频写入FFmpeg

3

大家好,

我正在开发一个工具,可以通过执行Java进程并将视频帧提供给其使用FFmpeg来渲染视频。

我目前使用以下FFmpeg命令: ffmpeg -y -f rawvideo -pix_fmt rgb24 -s %WIDTH%x%HEIGHT% -r %FPS% -i - -an -c:v libx264 -preset ultrafast -pix_fmt yuv420p "%FILENAME%.mp4", 其中占位符显然会被替换为实际值。

我用于初始化FFmpeg的代码:

    //commandArgs is a list of command line arguments for FFmpeg

    List<String> command = new ArrayList<String>();
    command.add("ffmpeg");
    command.addAll(commandArgs);

    process = new ProcessBuilder(command).directory(outputFolder).start();
    OutputStream exportLogOut = new FileOutputStream("export.log");
    new StreamPipe(process.getInputStream(), exportLogOut).start();
    new StreamPipe(process.getErrorStream(), exportLogOut).start();
    outputStream = process.getOutputStream();
    channel = Channels.newChannel(outputStream);

然后,我有以下方法来编写一个包含视频帧的ByteBuffer到FFmpeg:
public void consume(ByteBuffer buf) {
    try {
        channel.write(buf);
        ByteBufferPool.release(buf);
    } catch(Exception e) {
        e.printStackTrace();
    }
}

现在,我的问题是如何将同步音频数据写入输出文件?我认为我需要使用多个管道,当然我还需要修改命令行参数,但我需要帮助:

1) what kind of Audio Data do I need to feed FFmpeg with?
2) how do I feed Audio and Video in one go?
3) how do I keep Audio and Video synchronized?

非常感谢您提供的任何帮助!

你好, CrushedPixel

2个回答

3
这就是复用格式的作用,理想情况下,您需要使用一个复用格式来提供数据给FFmpeg。FFmpeg内部实现此操作的示例是ffmpeg.exe和ffserver.exe之间的交互,并通过一种称为FFM的自定义/内部流文件格式完成。有关实现的完整细节可以在这里找到。您还可以使用其他复用格式,例如简单的AVI。由于文件提供时间戳,同步是自动的。
至于音频数据类型,它可以是任何类型,大多数人会使用原始的、交错的PCM音频(浮点或int16)。

只要确保同步输入,您可能能够从两个“命名管道”输入或类似输入中进行输入。 - rogerdpack
@rogerdpack,是否有可能在任何操作系统上安全地获取命名管道? - CrushedPixel
@rogerdpack 我一开始犹豫是否建议使用命名管道,因为同步问题,但是如果你可以在外部保持视频帧率和音频采样率恒定连续,那就更容易了。 - Ronald S. Bultje

1

这不是一个选项,因为我们不能在AGPL许可证下分发我们的工作。 - CrushedPixel
我可能是错的,但AGPL许可证适用于修改和分发humble-video,而不是将humble-video作为库/API使用的软件。此外,https://github.com/artclarke/xuggle-xuggler上还有一个旧版本的软件,已经被弃用,它是GPL许可证,如果符合您的要求,可以使用。 - Radu Toader
你错了 - 我们必须将我们的工具作为AGPL/GPL分发,但这对我们的项目来说是不可能的。无论如何还是谢谢 :) - CrushedPixel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接