Using FFMPEG in Java Cheat Sheet

Overview

This cheat sheet contains code example that I use most frequently in my recent project that uses ffmpeg extensively to edit and create video.

Let’s get started.

Run ffmpeg in Java

To run a ffmpeg command from Java, use the following function.

 public static void runFFmpegCommand(String[] command) {
        try {
            logger.info("running ffmpeg command: {}", java.lang.String.join(" ", command));
            ProcessBuilder builder = new ProcessBuilder(command);
            builder.redirectErrorStream(true); // This merges the error stream with the standard output stream

            // Start the process
            Process process = builder.start();
            // Wait for the process to complete
            int exitCode = process.waitFor();
            if (exitCode == 0) {
                logger.info("FFMpeg exited successfully");
            } else {
                process.getErrorStream().transferTo(System.out);
                logger.error("FFMpeg exited with error code {}", exitCode);
            }
        } catch (IOException | InterruptedException e) {
            logger.error("Error running ffmpeg command", e);
        }
 }

Create a video from a single image with a duration

To create a video from a single image, with a duration, you can use the following function:

    public static CompletableFuture<String> createSingleImageVideo(String imagePath, int seconds, String outputPath) {
        return CompletableFuture.supplyAsync(() -> {
            String[] ffmpegCommand = {
                    ffmpegExecutablePath,
                    "-y",
                    "-loop", "1",
                    "-framerate", "30",
                    "-t", java.lang.String.valueOf(seconds),
                    "-i", imagePath,
                    "-c:v", "libx264",
                    "-vf", "fps=30,format=yuv420p",
                    outputPath
            };

            runFFmpegCommand(ffmpegCommand);

            logger.info("video created: {}", outputPath);
            return outputPath;
        });
    }

Explain:

  • Overwrite the output file without asking (-y).
  • Loop a single image (-loop 1) to create a video stream.
  • Set the framerate to 30 frames per second (-framerate 30).
  • Set the video duration to the specified number of seconds (-t followed by the value of seconds).
  • Use the specified image as the input (-i followed by imagePath).
  • Encode the video using the H.264 codec (-c:v libx264).
  • Apply a video filter to set the output framerate to 30 fps and format the video to yuv420p (-vf "fps=30,format=yuv420p"), ensuring compatibility with most video players.
  • Specify the output file path.

Join a video with an audio

This function joins a video with an audio.

    public static CompletableFuture<String> joinVideoWithAudio(String videoPath, String audioPath, String outputPath) {
        var ffmpegCommand = new String[]{
                ffmpegExecutablePath,
                "-y",
                "-i", videoPath,
                "-stream_loop", "-1",
                "-i", audioPath,
                "-c:v", "copy",
                "-c:a", "aac",
                "-b:a", "192k",
                "-shortest",
                outputPath
        };

        return CompletableFuture.supplyAsync(() -> {
            runFFmpegCommand(ffmpegCommand);
            return outputPath;
        });
    }

Explain:

  • ffmpegExecutablePath: This variable should contain the path to the FFmpeg executable. It’s not defined in the snippet you provided but is presumably defined elsewhere in your codebase.
  • -y: This option overwrites the output file without asking if it already exists.
  • -i videoPath: Specifies the input file path for the video.
  • -stream_loop -1: This option loops the input stream indefinitely. It’s applied to the next input file, which in this case is the audio file. This is useful if the audio file is shorter than the video file and you want it to repeat until the video ends.
  • -i audioPath: Specifies the input file path for the audio.
  • -c:v copy: Copies the video stream from the input file to the output file without re-encoding. This is faster and preserves the original quality of the video stream.
  • -c:a aac: Specifies the audio codec to use for the output file. Here, it uses AAC, a common audio codec that provides good quality at smaller file sizes.
  • -b:a 192k: Sets the audio bitrate to 192 kbps, which is a decent quality for most purposes.
  • -shortest: This option makes the output file’s duration equal to the shortest of the input streams. Without this, the video could continue playing in silence if the audio stream ends first, or the audio could keep playing without video if the video ends first.
  • outputPath: Specifies the file path for the output video file.

Conclusion

These quick formulas will help you get started quickly with FFMPEG in Java. Continue to explore the library to add more recipes to your cookbook.

Leave a Comment