Search code examples
phpffmpegshell-exec

How to run multiple ffmpeg tasks in php shell_exec


I am trying to do the below tasks.

  1. Convert video from webm to mp4 format
  2. Resize the video
  3. Add watermark to the bottom right
  4. Generate the thumbnail

I am able to do it by running multiple shell commands. Is there a way to do all four tasks in one go. For example

$watermark = "https://dummyimage.com/150x50/bf1fbf/ffffff.png";
shell_exec("ffmpeg -i test.webm -vf scale=100:-1, {$watermark} -filter_complex overlay=x=(main_w-overlay_w):y=(main_h-overlay_h) test.mp4 -ss 00:00:01.000 -vframes 1 test.jpg");

Solution

  • Use a single instance of -filter_complex to do all filtering:

    $watermark = "https://dummyimage.com/150x50/bf1fbf/ffffff.png";
    shell_exec("ffmpeg -i test.webm -i '{$watermark}' -filter_complex '[0:v]scale=100:-2[bg];[1]rotate=-3*PI/180[fg];[bg][fg]overlay=x=(main_w-overlay_w):y=(main_h-overlay_h):format=auto,format=yuv420p,split=outputs=2[vid][img]' -map '[vid]' -map 0:a test.mp4 -map '[img]' -ss 00:00:01.000 -frames:v 1 test.jpg");
    
    • See FFmpeg Filtering Documentation.

    • Your ffmpeg must have support for the HTTPS protocol to use HTTPS inputs. See ffmpeg -protocols to check. Otherwise, download the PNG first before running ffmpeg.

    Explanation of the filtergraph

    • [0:v]scale=100:-2[bg] - Take video from input #0 ([0:v]), scale to 100 pixels wide, auto-scale height to preserve aspect, but make sure it is divisible by 2 (a requirement of libx264). Label the scale output [bg] (you can give it any name).

    • [1]rotate=-3*PI/180[fg] Rotate input #1 ([1]) by -3 degrees. Name this [fg].

    • [bg][fg]overlay=x=(main_w-overlay_w):y=(main_h-overlay_h):format=auto - Overlay [bg] under [fg]. Place overlay in bottom right. format option allows it to auto select an appropriate pixel format for best quality.

    • format=yuv420p Use format filter to make pixel format yuv420p. This is for chroma-subsampling compatibility as non-FFmpeg based players can only support YUV 4:2:0 H.264.

    • split=outputs=2[vid][img] Split the output from the filtering into two identical streams named [vid] and [img]. This is required when making two outputs using the same filtered output because you can't re-use the same filter output more than once.