How can I convert a series of PNG images to a video for YouTube?

58,255

YouTube expects your video to be H.264-encoded. If you use libx264, stick to YouTube's encoding suggestions:

ffmpeg -framerate 10 -i image%03d.png -s:v 1280x720 -c:v libx264 \
-profile:v high -crf 20 -pix_fmt yuv420p daimler_man.mp4

Tips:

  • -qscale is a way to set quality, but -qscale alone is ambiguous. Use -qscale:v for video and -qscale:a for audio encoders that support it. Don't use this option unless you know what it means.

    x264 has a better option for setting quality: -crf. The Constant Rate Factor is a constant quality encoding mode. Lower values mean better quality, but anything below 18 might not be visually better. The default is 23, but something like 20 would be better since YouTube re-encodes your video again.

  • -pix_fmt yuv420p should be used to enable 4:2:0 downsampling for the PNG input, which usually isn't downsampled at all (4:4:4, as observed in your output) and often contains an Alpha channel. YouTube won't handle this correctly.

  • -r is not needed for setting the output framerate, as YouTube will handle almost all frame rates anyway. When reading 10 images per second as input, changing the output frame rate to something higher (e.g. 30) will only duplicate frames, which is not necessary.

  • -s:v 1380x720 is a weird resolution. Think about using the native 16:9 720p resolution 1280×720, and re-generating your plots if necessary. This will spare you some trouble and letterboxing issues on YouTube, and sticking to unusual dimensions might prevent your video from being shown in full resolution or offered at the 720p quality setting.

  • Use the MP4 container instead of MOV, which YouTube suggests you to use. MP4 is virtually identical in functionality to MOV, but has better support in playback devices. In general, prefer that over MOV when you can.

Share:
58,255

Related videos on Youtube

Raffael
Author by

Raffael

Updated on September 18, 2022

Comments

  • Raffael
    Raffael almost 2 years

    I have a sequence of PNGs (here is one specimen) which I turn into a video with ffmpeg:

    ffmpeg -r 10 -i image%03d.png -s 1380x720 -c:v libx264 -qscale 10 -r 30
           basf_merck_libx264.mp4
    

    With VLC it looks all nice and dandy but on youtube all I see is gray!? why?

    enter image description here

    After a while a horizontal bar with colorful spots is shown:

    enter image description here

    When I add '-pix_fmt yuv420p' to the command then youtube shows the clip correctly. But then the highest quality I can choose is 480p which is to low for this purpose.

    ffmpeg output

    C:\Users\Raffael\Documents\proj>ffmpeg -r 10 -i image%03d.png -s 1380x720 -c:v libx264 -qscale 10 -r 30 basf_merck_libx264.mp4
    ffmpeg version N-48785-g2ea3f37 Copyright (c) 2000-2013 the FFmpeg developers
      built on Jan 12 2013 20:45:33 with gcc 4.7.2 (GCC)
      configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnu
    tls --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-libopencore-amrnb --enable-l
    ibopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libtwol
    ame --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib
    --enable-filter=frei0r
      libavutil      52. 14.100 / 52. 14.100
      libavcodec     54. 86.100 / 54. 86.100
      libavformat    54. 59.107 / 54. 59.107
      libavdevice    54.  3.102 / 54.  3.102
      libavfilter     3. 32.100 /  3. 32.100
      libswscale      2.  1.103 /  2.  1.103
      libswresample   0. 17.102 /  0. 17.102
      libpostproc    52.  2.100 / 52.  2.100
    Input #0, image2, from 'image%03d.png':
      Duration: 00:00:02.04, start: 0.000000, bitrate: N/A
        Stream #0:0: Video: png, rgb24, 1380x720, 25 fps, 25 tbr, 25 tbn, 25 tbc
    Please use -q:a or -q:v, -qscale is ambiguous
    File 'basf_merck_libx264.mp4' already exists. Overwrite ? [y/N] y
    using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle Cache64
    [libx264 @ 00000000021c6fe0] profile High 4:4:4 Predictive, level 3.2, 4:4:4 8-bit
    [libx264 @ 00000000021c6fe0] 264 - core 129 r2230 1cffe9f - H.264/MPEG-4 AVC codec - Copyleft 2003-2012 - http://www.videolan.org/x264.html - options:
     cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 dead
    zone=21,11 fast_pskip=1 chroma_qp_offset=4 threads=3 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_int
    ra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahea
    d=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
    Output #0, mp4, to 'basf_merck_libx264.mp4':
      Metadata:
        encoder         : Lavf54.59.107
        Stream #0:0: Video: h264 ([33][0][0][0] / 0x0021), yuv444p, 1380x720, q=-1--1, 15360 tbn, 30 tbc
    Stream mapping:
      Stream #0:0 -> #0:0 (png -> libx264)
    Press [q] to stop, [?] for help
    frame=  151 fps= 16 q=-1.0 Lsize=    1995kB time=00:00:04.96 bitrate=3290.5kbits/s dup=100 drop=0
    video:1992kB audio:0kB subtitle:0 global headers:0kB muxing overhead 0.127092%
    [libx264 @ 00000000021c6fe0] frame I:1     Avg QP:22.19  size: 57949
    [libx264 @ 00000000021c6fe0] frame P:54    Avg QP:26.90  size: 36277
    [libx264 @ 00000000021c6fe0] frame B:96    Avg QP:21.56  size:   236
    [libx264 @ 00000000021c6fe0] consecutive B-frames:  5.3%  1.3% 85.4%  7.9%
    [libx264 @ 00000000021c6fe0] mb I  I16..4: 71.1%  2.5% 26.4%
    [libx264 @ 00000000021c6fe0] mb P  I16..4:  0.6%  0.5%  5.7%  P16..4:  3.1%  2.1%  2.9%  0.0%  0.0%    skip:85.0%
    [libx264 @ 00000000021c6fe0] mb B  I16..4:  0.2%  0.1%  0.0%  B16..8:  4.7%  0.1%  0.0%  direct: 0.0%  skip:94.9%  L0:77.6% L1:22.3% BI: 0.1%
    [libx264 @ 00000000021c6fe0] 8x8 transform intra:7.7% inter:5.2%
    [libx264 @ 00000000021c6fe0] coded y,u,v intra: 59.5% 54.3% 52.9% inter: 1.3% 1.0% 0.6%
    [libx264 @ 00000000021c6fe0] i16 v,h,dc,p: 81% 15%  4%  0%
    [libx264 @ 00000000021c6fe0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 10%  5% 64%  3%  2%  4%  3%  4%  3%
    [libx264 @ 00000000021c6fe0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 27% 13% 21%  7%  6%  7%  6%  7%  6%
    [libx264 @ 00000000021c6fe0] Weighted P-Frames: Y:0.0% UV:0.0%
    [libx264 @ 00000000021c6fe0] ref P L0: 65.3%  9.0% 20.2%  5.5%
    [libx264 @ 00000000021c6fe0] ref B L0: 73.0% 21.7%  5.3%
    [libx264 @ 00000000021c6fe0] ref B L1: 90.8%  9.2%
    [libx264 @ 00000000021c6fe0] kb/s:3241.64
    

    I collected the information on my web-site: http://www.joyofdata.de/blog/hd-clips-with-ffmpeg-for-youtube-and-vimeo/

    • slhck
      slhck over 11 years
      Please supply the full, uncut console output for the FFmpeg command(s). Pixel formats aren't related to the dimensions, so you should always be able to select more than 480p resolution on YouTube if your source is 720p and above.
    • Raffael
      Raffael over 11 years
      added the output of the ffmpeg command. The clip watched with VLC still shows the old larger resolution. But youtube offers me just 480p.
  • Peter Cordes
    Peter Cordes over 9 years
    I don't think the comments about -qscale make sense. For libx264, it's the same as setting -qp, isn't it? It's an option that applies to x264 compression, so the source being PNG is irrelevant. Regardless, -crf is a better choice than -qp or -b:v for one-pass with a target quality. (rather than a target bitrate).
  • Peter Cordes
    Peter Cordes over 9 years
    you should fix the duplicate frames effect, too. -framerate 10 -i input -r 30 will generate duplicates when outputting to mp4. (not to mkv, for reasons relating to ffmpeg supporting vfr in mkv, I think.) If your content is 10 fps, just make a 10 fps output video. I think youtube supports whatever framerate you want (up to 60). Cell phone cameras record variable-frame-rate h.264 video in mp4 (esp. in low light), so if you can upload those directly to youtube, then you'll be fine.
  • slhck
    slhck over 9 years
    @PeterCordes Absolutely. I had taken the -r 30 from the OP's command without changing it.
  • Radon Rosborough
    Radon Rosborough about 6 years
    With a command based off the one in this answer (ffmpeg -y -framerate 1 -i static_image.png -i bg_music.mp3 -s:v 1280x720 -c:v libx264 -profile:v high -crf 20 -pix_fmt yuv420p output.mp4), unfortunately I still get the mysterious "video has failed to process" error. Not sure how to debug it, unfortunately.
  • rolandog
    rolandog over 3 years
    @RadonRosborough, you may need to re-encode the audio to AAC? And, perhaps use other helpful flags. I was having trouble with sending a png slideshow with audio through WhatsApp; after reading H.264 encoding docs I came up with a solution that worked for me; I'll paste it in my next comment.
  • rolandog
    rolandog over 3 years
    There may be some redundant options (I think 'crf' defaults to 23; and I can't remember if -shortest is the new behaviour); anyhow. Here's my solution ffmpeg -i durations.txt -i audio.m4a -map 0:v:0 -map 1:a:0 -codec:v libx264 -preset veryslow -tune stillimage -profile:v baseline -pix_fmt yuv420p -crf 23 -c:a aac -b:a 128k -movflags +faststart -shortest output.mp4 (you'll get a warning of duplicate frames, but that's what you want). In the durations.txt you have to follow a specific format for the 'concat' feature.