简体   繁体   English

如何在Java中合并音频和视频

[英]How to merge audio and video in Java

We have created an application that records web camera streams using Xuggler, but video and audio are separated. 我们创建了一个使用Xuggler记录网络摄像头流的应用程序,但视频和音频是分开的。

We need to merge, not concatenate, these two files. 我们需要合并而不是连接这两个文件。

How can this be done in Java? 如何在Java中完成?

If you have audio and video file then you can merge them to a single audio video file using FFmpeg: 如果您有音频和视频文件,则可以使用FFmpeg将它们合并到单个音频视频文件中:

  1. Download FFmpeg: http://ffmpeg.zeranoe.com/builds/ 下载FFmpeg: http//ffmpeg.zeranoe.com/builds/
  2. Extract downloaded file to specific folder, say c:\\ffmpeffolder 将下载的文件解压缩到特定文件夹,例如c:\\ ffmpeffolder
  3. Using cmd move to specific folder c:\\ffmpeffolder\\bin 使用cmd移动到特定文件夹c:\\ ffmpeffolder \\ bin
  4. Run following command: $ ffmpeg -i audioInput.mp3 -i videoInput.avi -acodec copy -vcodec copy outputFile.avi This is it. 运行以下命令:$ ffmpeg -i audioInput.mp3 -i videoInput.avi -acodec copy -vcodec copy outputFile.avi就是这样。 outputFile.avi will be the resulting file. outputFile.avi将是生成的文件。

You can call ffmpeg using Java as follows: 您可以使用Java调用ffmpeg,如下所示:

public class WrapperExe {

 public boolean doSomething() {

 String[] exeCmd = new String[]{"ffmpeg", "-i", "audioInput.mp3", "-i", "videoInput.avi" ,"-acodec", "copy", "-vcodec", "copy", "outputFile.avi"};

 ProcessBuilder pb = new ProcessBuilder(exeCmd);
 boolean exeCmdStatus = executeCMD(pb);

 return exeCmdStatus;
} //End doSomething Function

private boolean executeCMD(ProcessBuilder pb)
{
 pb.redirectErrorStream(true);
 Process p = null;

 try {
  p = pb.start();

 } catch (Exception ex) {
 ex.printStackTrace();
 System.out.println("oops");
 p.destroy();
 return false;
}
// wait until the process is done
try {
 p.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("woopsy");
p.destroy();
return false;
}
return true;
 }// End function executeCMD
} // End class WrapperExe

I would recommend to look into ffmpeg and merge them trough command line with the required arguments needed for merging the video and audio files. 我建议查看ffmpeg并通过命令行将它们与合并视频和音频文件所需的必需参数合并。 You can use java Process to execute native processes. 您可以使用java Process来执行本机进程。

depending on the formats, you could use JMF, the Java Media Framework, which is ancient and was never that great, but might be good enough for your purposes. 根据格式的不同,您可以使用JMF,Java Media Framework,这是古老而且从未如此出色,但可能足以满足您的需求。

If it doesn't support your formats, you could use the FFMPEG wrapper which, if I am remembering correctly, provides a JMF interface but uses FFMPEG: http://fmj-sf.net/ffmpeg-java/getting_started.php 如果它不支持你的格式,你可以使用FFMPEG包装器,如果我没记错的话,它提供了一个JMF接口但是使用了FFMPEG: http//fmj-sf.net/ffmpeg-java/getting_started.php

As the other answers suggested already, ffmeg does seem to be the best solution here. 正如其他答案已经提出的那样,ffmeg似乎确实是最好的解决方案。

Here the code I ended up with: 这里的代码我最终得到:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;

public static File mergeAudioToVideo(
        File ffmpegExecutable,  // ffmpeg/bin/ffmpeg.exe
        File audioFile,
        File videoFile,
        File outputDir,
        String outFileName) throws IOException, InterruptedException {

    for (File f : Arrays.asList(ffmpegExecutable, audioFile, videoFile, outputDir)) {
        if (! f.exists()) {
            throw new FileNotFoundException(f.getAbsolutePath());
        }
    }

    File mergedFile = Paths.get(outputDir.getAbsolutePath(), outFileName).toFile();
    if (mergedFile.exists()) {
        mergedFile.delete();
    }

    ProcessBuilder pb = new ProcessBuilder(
            ffmpegExecutable.getAbsolutePath(),
            "-i",
            audioFile.getAbsolutePath(),
            "-i",
            videoFile.getAbsolutePath() ,
            "-acodec",
            "copy",
            "-vcodec",
            "copy",
            mergedFile.getAbsolutePath()
    );
    pb.redirectErrorStream(true);
    Process process = pb.start();
    process.waitFor();

    if (!mergedFile.exists()) {
        return null;
    }
    return mergedFile;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM