Re: Flash Movie Conversion with Java (FFMPEG)
Process process = Runtime.getRuntime().exec(convertCommand);
exitValue = doWaitFor(process);
Mark Rafn wrote:
For more control of environment and commandline, you might need
ProcessBuilder rather than Runtime.exec().
Vince <info@netscape.com> wrote:
What would the advantage be to use ProcessBuilder instead of Runtime?
You get more control over what's actually run - you can give a List<String> or
String[] of params rather than a single String, so you can avoid extra
quoting if the parameters have spaces or special characters in them, you
can set the working directory, and you can control the environment. You
can also set up one ProcessBuilder, and start() it multiple times, if that
fits your use case.
In your simple case, you can also redirectErrorStream(true) before starting
the process, and then you won't have to read the error stream from the
Process.
Anyway the doWaitFor method (see the appended code in my original post)
does constantly read - with a sleeper of 500ms - the input and error
streams of the process...
Right, but polling for output is pretty gross. It's simpler to spin off a
thread to read the input. Hacky sample that should be expanded:
// WARNING: partial and not tested, so errors are likely
builder.setRedirectErrorStream(true);
Process p = builder.start();
final InputStream procStdOut = p.getInputStream();
// start a thread to read the stdout
new Thread("process InputStream handler for " + processName) {
public void run() {
byte[512] buf; // deal with larger blocks than 1 char at a time!
int amtRead;
try {
// read until EOF, blocking when there's nothing to read
while ((amtRead = procStdOut.read(buf) != -1) {
// do something with amtRead bytes of buf
System.out.write(buf, 0, amtRead);
}
} catch (IOException e) {
// shouldn't ever happen for this type of stream
// note failure, queue to retry or whatever you want.
LOGGER.error("impossible IOException!", e);
}
}
}.run();
int exitCode = p.waitFor();
Really? Would you provide a link to the bug report?
http://www.google.ch/search?hl=de&q=java+waitfor+hangs&meta=
http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=1
These aren't bugs or issues with Process.waitFor(). And they're not win32
specific - it applies to almost all systems.
JavaDoc for java.lang.Process even says "Because some native platforms only
provide limited buffer size for standard input and output streams, failure to
promptly write the input stream or read the output stream of the subprocess
may cause the subprocess to block, and even deadlock."
Upload and convert can happen at different times, right?
If I do understand your question right then no or basically almost no.
Oh. Why not? Video conversion is a slow, expensive process, and you
shouldn't try to do it all at once.
Let me explain, the file gets uploaded and written to the HD, then
straight away FFMPEG gets launched. As soon as the process stops, the
original movie gets deleted from the HD and only the converted one remains.
I'd call that a broken design. It's just plain not going to scale well.
Allow upload to
some spool directory, and have a separate process (possibly in the same VM,
probably not) do the conversion using a pool of converters so that only N
are converting at a time.
May you elaborate a bit more on this one?
Sure. Don't process the file right away. Save it to some directory (or DB
blob or whatnot) for incoming files, and have a separate system that
converts the format and deletes the original. That separate system can work
on N files at once, so you can optimize the memory, cpu, and disk usage for
large numbers of requests.
It does mean that you have to show your users a slightly different UI, as they
can now have files queued for processing and files ready for use.
--
Mark Rafn dagon@dagon.net <http://www.dagon.net/>