jack
jack

Reputation: 41

How to run FFmpeg command in background from Java?

I am running a FFmpeg command from Java Runtime.getRuntime().exec. FFmpeg command basically cuts the images from live stream. Actually, when I run this command without & then it works fine for five minutes after that it stops cutting images.

But, when I use & in FFmpeg command it does not work at all.

There is no problem in live stream as when I ran this FFmpeg command from Linux it's working fine.

So, how to run an FFmpeg command in background from Java?

Upvotes: 4

Views: 12563

Answers (6)

Mahozad
Mahozad

Reputation: 24482

The FFmpeg is published as part of the JavaCV library and can be used in JVM projects.

Here is an example real-world app on GitHub using that.

Add the required dependencies in your build file (list of supported OSes):

implementation("org.bytedeco:ffmpeg:7.1-1.5.11") // Common dependency
// The dependency containing executables for the preferred OS
implementation("org.bytedeco:ffmpeg:7.1-1.5.11:windows-x86_64-gpl")

Example in Java:

public class Demo {
    private final String pathToFFmpeg = Loader.load(ffmpeg.class);
    public void demo() throws IOException {
        var ffmpegProcess = new ProcessBuilder()
                .command(
                        pathToFFmpeg,
                        // These are the same options you would pass to FFmpeg CLI
                        "-i", "/absolute/path/to/video.mp4"
                )
                .start();
        try (var reader = new BufferedReader(new InputStreamReader(ffmpegProcess.getErrorStream()))) {
            reader
                    .lines()
                    .forEach(System.out::println);
        }
    }
}

Example in Kotlin:

class Demo() {
    private val pathToFFmpeg = Loader.load(ffmpeg::class.java)
    fun demo() {
        ProcessBuilder()
            .command(
                pathToFFmpeg,
                // These are the same options you would pass to FFmpeg CLI
                "-i",
                "absolute/path/to/video.mp4"
            )
            .runCatching { start() }
            .onFailure { println("Starting the FFmpeg process for probing failed") }
            .getOrNull()
            ?.errorStream
            ?.reader()
            ?.useLines { lines -> lines.forEach(::println) }
    }
}

Upvotes: 1

nitin
nitin

Reputation: 591

String livestream = "/Users/videos/video_10/video_1.mp4";

String folderpth = "/Users/videos/video_10/photos";

String cmd="/opt/local/bin/ffmpeg -i "+ livestream +" -r 10 "+folderpth+"/image%d.jpeg"; 

Process p = Runtime.getRuntime().exec(cmd);

The video was 10 sec. long and it created 100 jpeg's in photos folder. You have to provide the absolute path of the folder.

Also to find the path for ffmpeg binary use which ffmpeg in terminal. Mine was /opt/local/bin/ffmpeg.

Upvotes: 1

Martin Magakian
Martin Magakian

Reputation: 3766

I know you ask for help for your command line problem in Java but you might be interest in an other solution.

Maybe you can give a try to this library: http://code.google.com/p/jjmpeg/

It's a wrapper for ffmpeg. Maybe you can try to create a java thread and run your command.

Upvotes: 1

dekz
dekz

Reputation: 815

Are you passing the arguments in an array? If it works for a while are you giving it all the expected arguments? (print it out and check). Here is an example of my ffmpeg that I dug out for you.

String[] ffmpeg = new String[] {"ffmpeg", "-ss", Integer.toString(seconds),"-i", in, "-f", "image2", "-vframes", "1", out};
Process p = Runtime.getRuntime().exec(ffmpeg);

Upvotes: 0

Brian Agnew
Brian Agnew

Reputation: 272237

The '&' is a shell directive to drop the task into the background. Running from Process.exec() doesn't involve the shell.

If your process is stalling (i.e. running but just not working) then I suspect that it's blocked waiting for you to consume stdout/stderr. You have to do this using threads to prevent the process blocking waiting for you to consume its output. See this SO answer for more details.

To run it in the background (i.e. whilst your Java process does other stuff) you need to:

  1. spawn a new thread
  2. invoke the process via Process.exec in this thread
  3. consume stdout/stderr (both in separate threads) and finally get the exit code

Upvotes: 3

Thomas Mueller
Thomas Mueller

Reputation: 50087

You wrote it stops working after minutes. Did you check the exit code (Process.exitValue()). Also, did you check output stream and error stream from the external process?

Upvotes: 0

Related Questions