Java calls ffmpeg to process the video and records the pits encountered

need

Automatically superimpose a background image on a video with a transparent background

Execute ffmpeg command 1 based on JavaCV cross-platform

The minimum dependency of this requirement found by my test:

<!-- Optional GPL builds with (almost) everything enabled -->
    <dependency>
      <groupId>org.bytedeco</groupId>
      <artifactId>ffmpeg-platform-gpl</artifactId>
      <version>5.0-1.5.7</version>
    </dependency>

Core code:

  String ffmpeg = Loader.load(org.bytedeco.ffmpeg.ffmpeg.class);
  String tempFilePath = newVideoName;
  ProcessBuilder pb = new ProcessBuilder(ffmpeg,
      "-y", "-i", BACKGROUND_PNG, "-c:v", "libvpx-vp9", "-i", aliVideoUrl, "-filter_complex",
      "[0][1]overlay=0:0[video2];[video2]select=between(n\\,1\\,54000)", "-b:v", "2m", "-r",
      "30", "-c:v", "libx264", "-pix_fmt", "yuv420p", "-profile:v", "high", "-preset:v",
      "veryslow", "-tune", "film", "-level", "4.2", tempFilePath);
  pb.inheritIO().start().waitFor();
  File tempFile = new File(tempFilePath);

Pit 1 Insufficient memory

Insufficient memory of the server caused the actual failure of compositing videos. Many composite files are only 48B, but there is no error log related to them.
Each server node originally only had 2G memory, which was resolved after capacity expansion.

Pit 2 Multiple ffmpeg processes in parallel lead to heavy IO load, which in turn leads to io error?

This is just speculation. The phenomenon is that I will have multiple Java threads, and each thread will call the ffmpeg command. There is a probability that the synthesized video is missing the latter part, and io error, read error can be observed in the log. The larger the source video and the higher the number of Java threads, the greater the probability of this happening. When I change the Java program to single thread, there is no such problem. But when I tried to use the iostat command to observe the IO status of the server node, I did not observe evidence of the so-called heavy IO load. 2

Pit 3 When using Java to operate ffmpeg, it sometimes gets stuck

It only happens on my local Mac, not on the server. I searched for the reason for a long time, and finally found that my Mac automatically hibernated after running for a period of time. . But also record this pit that many people have encountered:

Pit 4 Process's waitFor deadlock problem and solution

The general idea is: when the Runtime object calls exec (cmd), the JVM will start a child process, which will establish three pipeline connections with the JVM process: standard input, standard output and standard error stream. Assuming that the program is constantly writing data to the standard output stream and standard error stream, and the JVM does not read it, it will not be able to continue writing data when the buffer is full, and Java's waitfor() is blocked waiting for the child process to complete. So it will eventually cause blocking in waitfor(). The main solution is that Java should consume the io stream of this buffer in time, or directly prevent ffmpeg from outputting logs. Some references:

When using Procees+Runtime to operate ffmpeg, the operation of relatively large files will be stuck, but cmd can open ffmpeg normally.

As mentioned in the Java process.waitFor() stuck problem-loglevel quiet , you can also directly add parameters to the ffmpeg command to prevent the output log.

Process's waitFor deadlock problem and solution


  1. How to call ffmpeg across platforms? The easiest cross-platform implementation of ffmpeg commands based on JavaCV in history ↩︎

  2. Detailed explanation of Linux IO real-time monitoring iostat command↩︎

Guess you like

Origin blog.csdn.net/qq_23204557/article/details/127104085