tags:

views:

95

answers:

3

Hi,
I am working with ffmpeg to generate previews, but I get this error in the middle of the execution of my program:

"ffmpeg": java.io.IOException: error=24, Too many open files

Does anybody know how to solve or how to avoid it??
I add the piece of code where I use ffmpeg:

    for (int j = 0; j < temp.length; j++) {
                                                if(j==2){
                                                    String preview = temp2[i] + temp[j] +".jpg";
                                                    Process p = Runtime.getRuntime().exec("ffmpeg -i anotados/" +temp2[i] + " -r 1 -ss 00:00:"+temp[j]+" -t 1 -s 158x116 imagenes/" + preview);

                                                    TextOut.write(preview+"\n");
                                                }
 }
+1  A: 

Check your ulimit -n output to see how many open files processes spawned from that shell are allowed to have. Historical Unix systems had a limit of 20 files, but default on my Ubuntu desktop is 1024 open files.

You may need to raise the number of open files you are allowed in the /etc/security/limits.conf file. Or, you may need to modify your application to more aggressively close open files.

Another possibility is a system-wide limit on number of files that may be open. I don't know which modern systems would still have such limits in place, but a first place to look would be sysctl -a output. (Well, maybe second place, after system documentation.)

sarnold
oerfect, thank you so much!
mujer esponja
A: 

Every time Runtime is used, it opens stdout, stderr and stdin. Make sure you close these streams when you're done with exec(). Something like

    if(j==2){
       String preview = temp2[i] + temp[j] +".jpg";
       Process p = Runtime.getRuntime().exec("ffmpeg -i anotados/" +temp2[i] + " -r 1 -ss      00:00:"+temp[j]+" -t 1 -s 158x116 imagenes/" + preview);
       TextOut.write(preview+"\n");

       //try this here 
       //add exception handling if necessary
       InputStream is = p.getInputStream();
       InputStream es = p.getErrorStream();
       OutputStream os = p.getOutputStream();
       is.close();
       es.close();
       os.close();
}
Zaki
A: 

Note that each call to Runtime.exec will spawn a new process that's run in parallel. Are you sure you want to spawn processes as fast as the loop can go? You probably want to int exitValue = p.waitFor() to wait for the process to complete. If you need some concurrency, I'd recommend scheduling tasks using a java.util.concurrent.ThreadPoolExecutor.

For example, without much error checking, something like so:

final ExecutorService executor = Executors.newFixedThreadPool(2);

for (int j = 0; j < temp.length; j++) {
    if(j==2) {
        final String preview = temp2[i] + temp[j] +".jpg";
        final String ffmpegPreviewCommand = "ffmpeg -i anotados/" +temp2[i] + " -r 1 -ss 00:00:"+temp[j]+" -t 1 -s 158x116 imagenes/" + preview;

        executor.submit(new Callable() {
            @Override
            public Object call() throws Exception {
                final Process p = Runtime.getRuntime().exec(ffmpegPreviewCommand);
                final int exitValue = p.waitFor();
                //TODO Check ffmpeg's exit value.

                TextOut.write(preview+"\n");
            }
        });
}

// This waits for all scheduled tasks to be executed and terminates the executor.
executor.shutdown();

}

Look at java.util.concurrent.Executors to pick an executor that fits your needs.

Ronald Blaschke