Search code examples
ffmpegffmpeg-php

Filter text disappearing after concat, why?


I'm trying to concatenate 2 videos, while at the same time adding some text to the second one. I'm using php-ffmpeg to do this, with the Sharapov extension, but I have the actual ffmpeg commands.

To do this it seems to encode the first video, then the second one with the text separately, and then joins them together. Problem is the text appears in the encoded (but un-joined) second video, but as soon as they are joined together it disappears.

Here are the commands:

ffmpeg '-y' '-i' 'video_in/first_vid.mp4' '-threads' '8' '-vcodec' 'libx264' '-acodec' 'aac' '-max_muxing_queue_size' '400' '-b:v' '1000k' '-refs' '6' '-coder' '1' '-sc_threshold' '40' '-flags' '+loop' '-me_range' '16' '-subq' '7' '-i_qfactor' '0.71' '-qcomp' '0.6' '-qdiff' '4' '-trellis' '1' '-b:a' '256k' '-ac' '2' '-pass' '1' '-passlogfile' '/tmp/ffmpeg-passes5b73814fa1e29qjif7/pass-5b73814fa1f5b' '/data/tmp/ffmpeg-7a580007c010377da19305b0836e7a4d-5b73814f9ff35.mp4'

    2%    2%    2%    4%    4%    6%    6%    6%    8%    8%    10%    10%    10%    12%    12%    12%    14%    14%    14%    16%    16%    18%    18%    18%    20%    20%    22%    22%    22%    24%    24%    24%    26%    26%    26%    28%    28%    28%    30%    30%    30%    32%    32%    34%    34%    34%    36%    36%    36%    38%    38%    38%    40%    40%    40%    42%    44%    44%    44%    46%    46%    46%    48%    48%    48%

ffmpeg '-y' '-i' 'video_in/first_vid.mp4' '-threads' '8' '-vcodec' 'libx264' '-acodec' 'aac' '-max_muxing_queue_size' '400' '-b:v' '1000k' '-refs' '6' '-coder' '1' '-sc_threshold' '40' '-flags' '+loop' '-me_range' '16' '-subq' '7' '-i_qfactor' '0.71' '-qcomp' '0.6' '-qdiff' '4' '-trellis' '1' '-b:a' '256k' '-ac' '2' '-pass' '2' '-passlogfile' '/tmp/ffmpeg-passes5b73814fa1e29qjif7/pass-5b73814fa1f5b' '/data/tmp/ffmpeg-7a580007c010377da19305b0836e7a4d-5b73814f9ff35.mp4'

    50%    50%    50%    52%    52%    52%    52%    52%    52%    54%    54%    54%    54%    54%    54%    56%    56%    56%    56%    56%    56%    58%    58%    58%    58%    58%    58%    60%    60%    60%    60%    60%    60%    62%    62%    62%    62%    62%    62%    64%    64%    64%    64%    64%    66%    66%    66%    66%    66%    66%    66%    68%    68%    68%    68%    68%    70%    70%    70%    70%    70%    72%    72%    72%    72%    72%    72%    72%    74%    74%    74%    74%    74%    74%    74%    76%    76%    76%    76%    76%    76%    76%    78%    78%    78%    78%    78%    78%    80%    80%    80%    80%    80%    80%    82%    82%    82%    82%    82%    84%    84%    84%    84%    84%    84%    84%    84%    84%    84%    86%    86%    86%    86%    86%    86%    88%    88%    88%    88%    88%    88%    88%    90%    90%    90%    90%    90%    90%    90%    90%    92%    92%    92%    92%    94%    94%    94%    94%    94%    94%    94%    94%    94%    96%    96%    96%    96%    96%    96%    96%    96%    98%    98%    98%    98%    98%    98%

ffmpeg '-y' '-i' 'video/second_vid.mp4' '-filter_complex' '[0:v]drawtext=fontfile=/usr/share/fonts/truetype/msttcorefonts/arial.ttf:text='test text':fontcolor='ffffff@1':fontsize=30:x=(w-tw)/2:y=50:alpha='if(lt(t,2),0,if(lt(t,4),(t-2)/2,if(lt(t,24),1,if(lt(t,26),(2-(t-24))/2,0))))'' '-threads' '8' '-vcodec' 'libx264' '-acodec' 'aac' '-max_muxing_queue_size' '400' '-b:v' '1000k' '-refs' '6' '-coder' '1' '-sc_threshold' '40' '-flags' '+loop' '-me_range' '16' '-subq' '7' '-i_qfactor' '0.71' '-qcomp' '0.6' '-qdiff' '4' '-trellis' '1' '-b:a' '256k' '-ac' '2' '-pass' '1' '-passlogfile' '/tmp/ffmpeg-passes5b738244e22e0b38pp/pass-5b738244e2412' '/data/tmp/ffmpeg-ed6a389106090a6a9f9c71c7c357400b-5b738244e2215.mp4'

    2%    2%    4%    6%    8%    10%    12%    14%    14%    16%    18%    18%    20%    22%    22%    24%    26%    28%    30%    30%    32%    34%    34%    36%    38%    40%    42%    44%    44%    46%    48%

ffmpeg '-y' '-i' 'video/second_vid.mp4' '-filter_complex' '[0:v]drawtext=fontfile=/usr/share/fonts/truetype/msttcorefonts/arial.ttf:text='test text':fontcolor='ffffff@1':fontsize=30:x=(w-tw)/2:y=50:alpha='if(lt(t,2),0,if(lt(t,4),(t-2)/2,if(lt(t,24),1,if(lt(t,26),(2-(t-24))/2,0))))'' '-threads' '8' '-vcodec' 'libx264' '-acodec' 'aac' '-max_muxing_queue_size' '400' '-b:v' '1000k' '-refs' '6' '-coder' '1' '-sc_threshold' '40' '-flags' '+loop' '-me_range' '16' '-subq' '7' '-i_qfactor' '0.71' '-qcomp' '0.6' '-qdiff' '4' '-trellis' '1' '-b:a' '256k' '-ac' '2' '-pass' '2' '-passlogfile' '/tmp/ffmpeg-passes5b738244e22e0b38pp/pass-5b738244e2412' '/data/tmp/ffmpeg-ed6a389106090a6a9f9c71c7c357400b-5b738244e2215.mp4'

    52%    52%    54%    54%    56%    56%    58%    58%    60%    60%    62%    64%    66%    68%    70%    70%    72%    74%    76%    76%    78%    80%    82%    84%    86%    86%    88%    88%    90%    90%    92%    94%    96%    98%

ffmpeg '-y' '-f' 'concat' '-safe' '0' '-i' '/data/tmp/ffmpeg-concat-5b73814f9fe10' '-c' 'copy' 'video_out/done_vid.mp4'

(For some reason it seems to run the encoding of each video command again at 50%)

So when I play ffmpeg-ed6a389106090a6a9f9c71c7c357400b-5b738244e2215.mp4, the text is in there, but when I play the output file (done_vid.mp4), the text isn't there.

What's going on?

UPDATE: Here are the ffprobes of the 2 temp files in case they help:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'data/tmp/ffmpeg-7a580007c010377da19305b0836e7a4d-5b73814f9ff35.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.83.100
  Duration: 00:02:25.17, start: 0.000000, bitrate: 1247 kb/s
    Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 999 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 47.95 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 242 kb/s (default)
    Metadata:
      handler_name    : SoundHandler


Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'data/tmp/ffmpeg-ed6a389106090a6a9f9c71c7c357400b-5b738244e2215.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf57.83.100
  Duration: 00:01:30.03, start: 0.000000, bitrate: 322 kb/s
    Stream #0:0(und): Video: h264 (High 4:4:4 Predictive) (avc1 / 0x31637661), yuv444p, 1280x720 [SAR 1:1 DAR 16:9], 61 kb/s, 23.98 fps, 23.98 tbr, 19184 tbn, 47.96 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 258 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

Solution

  • The problem

    Your first video output is yuv420p, but your second video output is yuv444p. Both should be yuv420p, so add format=yuv420p to the end of your filterchain:

    '-filter_complex' '[0:v]drawtext=fontfile=/usr/share/fonts/truetype/msttcorefonts/arial.ttf:text='test text':fontcolor='ffffff@1':fontsize=30:x=(w-tw)/2:y=50:alpha='if(lt(t,2),0,if(lt(t,4),(t-2)/2,if(lt(t,24),1,if(lt(t,26),(2-(t-24))/2,0))))',format=yuv420p'
    

    Other stuff

    • Since you're re-encoding everything anyway use the concat filter, then you can do everything in one command.
    • Do you really want to perform two passes? Use one pass with -crf instead of -b:v unless you are targeting a specific output file size. See FFmpeg Wiki: H.264.
    • You don't need to declare -threads. The encoder will automatically choose an appropriate value.
    • Use the encoding presets (see wiki link above). Then you can stop encoding like it is 2006 and you can remove all of this: '-refs' '6' '-coder' '1' '-sc_threshold' '40' '-flags' '+loop' '-me_range' '16' '-subq' '7' '-i_qfactor' '0.71' '-qcomp' '0.6' '-qdiff' '4' '-trellis' '1'.
    • I'll assume you're making videos to be played via progressive download. If that's the case add the -movflags +faststart output option so it can begin playback before it is completely downloaded by the viewer.