6

We have created an application that records web camera streams using Xuggler, but video and audio are separated.

We need to merge, not concatenate, these two files.

How can this be done in Java?

Jonas G. Drange
  • 8,749
  • 2
  • 27
  • 38
kashif181
  • 315
  • 2
  • 11

5 Answers5

5

If you have audio and video file then you can merge them to a single audio video file using FFmpeg:

  1. Download FFmpeg: http://ffmpeg.zeranoe.com/builds/
  2. Extract downloaded file to specific folder, say c:\ffmpeffolder
  3. Using cmd move to specific folder c:\ffmpeffolder\bin
  4. Run following command: $ ffmpeg -i audioInput.mp3 -i videoInput.avi -acodec copy -vcodec copy outputFile.avi This is it. outputFile.avi will be the resulting file.
arslaan ejaz
  • 1,001
  • 13
  • 31
  • Very Helpful really now if you explain that whether it be possible by java code – kashif181 Aug 06 '12 at 11:41
  • If your application is a Java Applet, as you state in your comment, and if you need the generated movie in the client side, you would need to send the recorded streams to the server, then make the ffmpeg merge on server, and return the encoded file to the applet. – Bigger Aug 08 '12 at 02:23
  • Some good links on the topic: * http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs * http://flowplayer.org/forum/7/12671 Building an mp4(x264) output with mp3 sound which is compatible with most videoplayers command using ffmpeg: `ffmpeg -i audiofile.mp3 -i moviefile.avi -acoded libfaac -vcodec libx264 output.mp4` You need to have `ffmpeg` built in with `x264` and `liblame` support for that. And watch out for copyright infringement due to mp3/x264 licenses, how you do it do not mind ;) – cristobal Aug 13 '12 at 21:29
4

You can call ffmpeg using Java as follows:

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
codegeek
  • 32,236
  • 12
  • 63
  • 63
  • Hi @codegeek, don't mind me shoot a tangent here, what if they were live streams instead of audio files? how to stream as it encodes without waiting for the whole file to be finished? – Matical Jun 25 '13 at 15:41
1

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. You can use java Process to execute native processes.

cristobal
  • 462
  • 5
  • 14
1

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.

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

Bjorn Roche
  • 11,279
  • 6
  • 36
  • 58
0

As the other answers suggested already, ffmeg does seem to be the best solution here.

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;
}
Jonas_Hess
  • 1,874
  • 1
  • 22
  • 32