I am trying to transcode a *.mov file into a *.mp4 file using JAVE, which calls ffmpeg. Both input file and output file are in InputStream and OutputStream forms. That means I need to pass InputStream and OutputStream as -i and -y parematers for ffmpeg. How do I do that ?
//Read a movfile.mov converted into a FileInputStream
InputStream fileInputStream = getFileInputStream();
OutputStream fileOutputStream = new FileOutputStrea(outputMP4File) //Output
Process p = Runtime.exec("ffmpeg -i - -y -");
InputStream pInStrm = p.getInputStream();
OutputStream pOutStrm = p.getOutputStream();
int vin = 0, vout = 0;
Thread read = new Thread() {
byte[] buff = new byte[4096];
void run() {
while ((vin=fileInputStream.read(buf))!=-1) {
pOutStrm.write(buf, 0, vin);
}
}
}; read.start();
Thread write = new Thread() {
byte[] buff = new byte[4096];
void run() {
while ((vout=pInStrm.read(buf))!=-1) {
fileOutputStream.write(buf, 0, vout);
}
}
}; write.start();
But I keep getting "IOException: pipe is closed" error. Could somebody help me out ? Alternatively if there is any JAVA API that could do this transcoding(on Windows and RedHat Linux), that would be very helpful
Thanks
That is not going to work that way.
Remember that JAVE merely acts as a wrapper to an ffmpeg executable, that is you supply parameters, like target encoding, loudness, etc. and then basically tell JAVE to call fmpeg and pass the settings, you entered using Java methods as parameters to the ffmpeg executable.
This step requires that the settings, you specify are 1. Serializable 2. Known to the ffmpeg executable
Now you could argue that at least some InputStreams, like FileInputStream are somehow serializable, as there is a low level File Descriptor that corresponds to this InputStream, but consider a ByteArrayInputStream - I don't know how Java implements on each platform but I somehow doubt, that there is a corresponding File Descriptor.
The crucial point however is, that an ffmpeg executable does not and should not know what a Java object of type InputStream is. The best it could do (at least on posix systems) is take an integer number (the File DescriptorE) and try to read data from it. However, a lot of things can go wrong, when working with a File Descriptor. For example it might be seekable, if it is a file, for example or not, if it actually represents data read from a socket.
Gladly, on Posix systems, for every process there are at least 3 File Descriptors, that is STDIN, STDOUT and STDERR. This corresponds to a concept where you can pipe input/output from one process to another. I don't know if or how this works on Windows, but on OSX or Linux you can pipe data into an ffmpeg executable. This actually means, that you instruct ffmpeg to read from the STDIN File Descriptor.
Sadly, JAVE does not implement this particular feature of ffmpeg, that is, there is no method, that pipes data into ffmpegs STDIN.
FWIW. You could write some native (c/c++) code and pass down a Java Object 'DecodeFeed', using JNI (http://en.wikipedia.org/wiki/Java_Native_Interface) that holds both an Inputstream and an OutputStream
The native code, you have to write could include the ffmpeg sources and use them to decode/transcode input that is read from DecodeFeed.in and then written back to DecodeFeed.out.
I am doing that in an Android project, you might want to look at for reference. https://github.com/fscz/FFmpeg-Android
Alternatively, you could fork JAVE and implement this feature yourself. As you might know Java offers a way to run an executable by calling Runtime.exec. This call will return an instance of Process class that offers Process.getOutputStream. If you write to this Outputstream, you actually write to the just created process's STDIN.
See http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html for documentation on how to spawn and write to a process.
And see http://ffmpeg.org/ffmpeg.html for the available command line options (including reading from STDIN) for ffmpeg.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With