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

13

18

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/

Raffael

Posted 2013-01-13T21:54:45.477

Reputation: 1 029

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. – slhck – 2013-01-13T22:06:41.687

added the output of the ffmpeg command. The clip watched with VLC still shows the old larger resolution. But youtube offers me just 480p. – Raffael – 2013-01-13T22:12:52.803

Answers

34

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.

slhck

Posted 2013-01-13T21:54:45.477

Reputation: 182 472

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 – 2015-01-15T01:04:11.687

1you 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. – Peter Cordes – 2015-01-15T07:38:47.820

@PeterCordes Absolutely. I had taken the -r 30 from the OP's command without changing it. – slhck – 2015-01-15T08:23:06.600

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. – Radon Rosborough – 2018-04-21T04:32:47.960