MergeAudioVideo source code:
import java.io.*;
import javax.media.*;
import javax.media.control.TrackControl;
import javax.media.datasink.*;
import javax.media.format.*;
import javax.media.protocol.*;
import java.net.*;
public class MergeAudioVideo{
public static void main(String args[]){
if(args.length>1){
System.out.println("Please wait...");
merging(args[0],args[1]);
System.out.println("Merging finished");
}
else
System.out.println("Invalid files input");
System.exit(0);
}
//merge the sound and video files
public static void merging(String audioFileName, String videoFileName){
//Declare and initialize StateHelper objects: sha,shv, and shm
//sha for audio processor, shvfor audio process, and shm for merge processor
StateHelper sha=null;
StateHelper shv=null;
StateHelper shm=null;
//Declare and initialize processor objects for audio, video, and merged data
Processor audioProcessor=null;
Processor videoProcessor=null;
Processor mergeProcessor=null;
//create MediaLocator objects for audio and video files
MediaLocator audioLocator=null;
MediaLocator videoLocator=null;
MediaLocator outLocator=null;
try{
File audioFile=new File(audioFileName);
audioLocator=new MediaLocator(audioFile.toURI().toURL());
File videoFile=new File(videoFileName);
videoLocator=new MediaLocator(videoFile.toURI().toURL());
//Create MediaLocator for merged output file
File outFile=new File(System.currentTimeMillis()+"mergedvideo.mov");
outLocator=new MediaLocator(outFile.toURI().toURL());
}catch(MalformedURLException me){System.exit(-1);}
//create datasources
DataSource audioDataSource=null;
DataSource videoDataSource=null;
DataSource mergedDataSource=null;
DataSource arrayDataSource[]=null;
try{
audioDataSource = Manager.createDataSource(audioLocator); // your audio file
videoDataSource = Manager.createDataSource(videoLocator); //your video file
mergedDataSource = null; // data source to combine video with audio
arrayDataSource= new DataSource[2]; //data source array
}catch(IOException ie){System.exit(-1);}
catch(NoDataSourceException ie){System.exit(-1);}
//format array for input audio and video
Format[] formats=new Format[2];
formats[0]=new AudioFormat(AudioFormat.IMA4_MS); //create audio format object
formats[1]=new VideoFormat(VideoFormat.JPEG); //create video format object
//create media file content type object
FileTypeDescriptor outftd=new FileTypeDescriptor(FileTypeDescriptor.QUICKTIME);
//create processor objects for video and audio
try{
videoProcessor = Manager.createProcessor(videoDataSource);
shv=new StateHelper(videoProcessor);
audioProcessor = Manager.createProcessor(audioDataSource);
sha=new StateHelper(audioProcessor);
}catch(IOException ie){System.exit(-1);}
catch(NoProcessorException ne){System.exit(-1);}
//Configure processors
if (!shv.configure(10000))
System.exit(-1);
if (!sha.configure(10000))
System.exit(-1);
//Realize processors
if (!shv.realize(10000))
System.exit(-1);
if (!sha.realize(10000))
System.exit(-1);
//return data sources from processors so they can be merged
arrayDataSource[0]=audioProcessor.getDataOutput();
arrayDataSource[1]=videoProcessor.getDataOutput();
//start the processors
videoProcessor.start();
audioProcessor.start();
//create merged data source, connect, and start it
try{
mergedDataSource=Manager.createMergingDataSource(arrayDataSource);
mergedDataSource.connect();
mergedDataSource.start();
}catch(IOException ie){System.exit(-1);}
catch(IncompatibleSourceException id){System.exit(-1);}
//processor for merged output
try{
mergeProcessor=Manager.createRealizedProcessor(new ProcessorModel(mergedDataSource,formats,outftd));
shm=new StateHelper(mergeProcessor);
}catch(IOException ie){System.exit(-1);}
catch(NoProcessorException ie){System.exit(-1);}
catch(CannotRealizeException ie){System.exit(-1);}
//set output file content type
mergeProcessor.setContentDescriptor(new ContentDescriptor(FileTypeDescriptor.QUICKTIME));
//query supported formats
TrackControl tcs[] =mergeProcessor.getTrackControls();
Format f[] = tcs[0].getSupportedFormats();
if (f == null || f.length <= 0)
System.exit(100);
//set track format
tcs[0].setFormat(f[0]);
//get datasource from the mergeProcessor so it is ready to write to a file by DataSink filewriter
DataSource source =mergeProcessor.getDataOutput();
//create DataSink filewrite for writing
DataSink filewriter = null;
try {
filewriter = Manager.createDataSink(source, outLocator);
filewriter.open();
} catch (NoDataSinkException e) {
System.exit(100);
} catch (IOException e) {
System.exit(100);
} catch (SecurityException e) {
System.exit(100);
}
// now start the filewriter and mergeProcessor
try {
mergeProcessor.start();
filewriter.start();
} catch (IOException e) {
System.exit(-1);
}
// wait 2 seconds for end of media stream
shm.waitToEndOfMedia(2000);
shm.close();
filewriter.close();
}
}
//The StateHelper class help you determine the states of the processors
class StateHelper implements ControllerListener {
Processor p = null;
boolean configured = false;
boolean realized = false;
boolean prefetched = false;
boolean eom = false;
boolean failed = false;
boolean closed = false;
public StateHelper(Processor pr) {
p= pr;
p.addControllerListener(this);
}
public boolean configure(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.configure();
while (!configured && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return configured;
}
public boolean realize(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.realize();
while (!realized && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return realized;
}
public boolean prefetch(int timeOutMillis) {
long startTime = System.currentTimeMillis();
synchronized (this) {
p.prefetch();
while (!prefetched && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie) {}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return prefetched && !failed;
}
public boolean waitToEndOfMedia(int timeOutMillis) {
long startTime = System.currentTimeMillis();
eom = false;
synchronized (this) {
while (!eom && !failed) {
try {
wait(timeOutMillis);
} catch (InterruptedException ie){}
if (System.currentTimeMillis() - startTime > timeOutMillis)
break;
}
}
return eom && !failed;
}
public void close() {
synchronized (this) {
p.close();
while (!closed) {
try {
wait(100);
} catch (InterruptedException ie) {}
}
}
p.removeControllerListener(this);
}
public synchronized void controllerUpdate(ControllerEvent ce) {
if (ce instanceof RealizeCompleteEvent) {
realized = true;
} else if (ce instanceof ConfigureCompleteEvent) {
configured = true;
} else if (ce instanceof PrefetchCompleteEvent) {
prefetched = true;
} else if (ce instanceof EndOfMediaEvent) {
eom = true;
} else if (ce instanceof ControllerErrorEvent) {
failed = true;
} else if (ce instanceof ControllerClosedEvent) {
closed = true;
} else {
return;
}
notifyAll();
}
}
The process of merging an audio file and an video file is not too hard to understand. You need three MeidaLocator objects to point to the source audio file and video file, and the last one MediaLocator is needed for the output merged file. To read the data of the audio file and video file, you can use the createDataSource (MediaLocator locator) method of the Manager class. This method returns the DataSource object that contains the data of the audio or video file. You will call this method two times. One for reading the data of the audio file and another one for reading the data of the video file. One you have the DataSource objects you can pass them to the processors to start the merging process. To process the files, you also will define three processor objects. One is to process the data of the audio file; one is for video file; and another one for the output merged file. Before the processors can fully perform their, they must be configured and realized. The StateHelper class helps to do these tasks. To merge the two source files, the createMergingDataSource(DataSource[] data) method of the Manager class is used. This method returns a new DataSource that combines the DataSource elements of the DataSource array together. One you have the merged data source, you can create a DataSink object that acts a a file writer to write the merged data to the output file. You might like to read Sound Recording post to get the related information about Processor, DataSource, and DataSink.
![]() |
![]() |