Log in

View Full Version : Corrupted x264 video after Youtube upload


ZeB
7th April 2022, 06:44
I have a video that gets corrupted on some frames when uploading it on Youtube. It’s a time lapse of jpeg images loaded in Avisynth.

Example:
Frame from my x264 encode:
https://privat.bahnhof.se/wb166561/ffmpeg.png

Same frame from the Youtube video:
https://privat.bahnhof.se/wb166561/youtube.png

There are multiple frames like this, usually a few in row. The example is one of the worst frames.

I basically just followed this guide when encoding:
https://gist.github.com/mikoim/27e4e0dc64e384adbcb91ff10a2d3678

This is my command line (using ffmpeg):
ffmpeg.exe -i "input.avs" -c:v libx264 -profile:v high -bf 2 -g 25 -preset veryslow -crf 18 -pix_fmt yuv420p -movflags faststart "output.mp4"

I have tried re-encoding and uploading the video multiple times. Higher CRF-values (lower quality video) seems to make less corruption.

Has anyone experienced anything like this before? Is there anything I can change in my encode settings?

Emulgator
7th April 2022, 17:10
youtube reeencodes, do I see screenshots from the youtube encode or from your encode ?
Maybe you can share the youtube link, and the script "input.avs"

ZeB
8th April 2022, 06:21
youtube reeencodes, do I see screenshots from the youtube encode or from your encode ?
Maybe you can share the youtube link, and the script "input.avs"

First frame is from my encode and the second frame is from Youtube's 2560x1440 reencode (all resolutions from Youtubes reencodes have the corruption though).

Video:
https://youtu.be/iDtW8x1Sx-g
Check around 3:33 to see the corrupted frames.

Avisynth script:
video = ImageSource("E:\FTP\1\img%01d.jpg", start = 13900, end = 14396, fps = 50, info = true)
video = video + ImageSource("E:\FTP\2\img%01d.jpg", start = 1, end = 19100, fps = 100, info = true).ChangeFPS(50)
video = video + ImageSource("E:\FTP\2\img%01d.jpg", start = 19100, end = 41150, fps = 1600, info = true).ChangeFPS(50, false)
video = video + ImageSource("E:\FTP\2\img%01d.jpg", start = 41150, end = 48187, fps = 100, info = true).ChangeFPS(50)
video = video + ImageSource("E:\FTP\3\img%01d.jpg", start = 1, end = 13017, fps = 100, info = true).ChangeFPS(50)

video = video.ConvertToYV12(matrix="rec709")
return video

FranceBB
9th April 2022, 09:25
First frame is from my encode and the second frame is from Youtube's 2560x1440 reencode (all resolutions from Youtubes reencodes have the corruption though).

Google re-encodes every video to several codecs: H.264 for backwards compatibility, VP9 and AV1.
It's very likely that their decoding is broken for your H.264 files, especially if you're using a Long GOP like with a very long keyframe interval etc.

So, first thing first, if you wanna stick with H.264, you should try at least with keyint = framerate like so:

x264.exe "AVS Script.avs" --crf 18 --preset medium --profile High --level 4.1 --ref 4 --keyint 50 --slices 4 --bframe 3 --deblock -1:-1 --overscan show --range tv --log-level info --colormatrix bt709 --transfer bt709 --colorprim bt709 --videoformat component --nal-hrd vbr --vbv-maxrate 40000 --vbv-bufsize 30000 --aud --output "raw_video.h264"

ffmpeg.exe -i "AVS Script.avs" -vn -sn -c:a aac -b:a 550k -ar 44100 "audio.aac"

mp4box -add "raw_video.h264" -add "audio.aac" "final_output.mp4"


What's important here is not just the keyint = framerate and the reference frame set to 4, but also the --aud, so the unit access delimiters which might play a role.

If that still doesn't work and you don't mind moving away from H.264, then perhaps you can try to give Google something else like a DNX or a ProRes.

If you wanna go the ProRes route:

ffmpeg.exe -i "AVS Script.avs" -vcodec prores_ks -profile:v 3 -qscale:v 0 -vendor apl0 -color_range 1 -color_primaries 1 -color_trc 1 -colorspace 1 -c:a pcm_s24le -ar 44100 -f mov -y "output.mov"

pause

and I'm pretty sure it's gonna work.

rwill
9th April 2022, 21:16
He specified '-g 25' to ffmpeg so his keyframe interval should be 25 ?

@ZeB can you share the video you upload to youtube, like put it unmodified somewhere like a drive or something so people can download it and take a look at the stream ?

*edit*
maybe try '-profile:v main' instead of '-profile:v high' ?

ZeB
11th April 2022, 13:06
What's important here is not just the keyint = framerate and the reference frame set to 4, but also the --aud, so the unit access delimiters which might play a role.

I did some testing and the number of ref frames seems to be the problem. Default is 16.

My command line:
ffmpeg.exe -i "input.avs" -c:v libx264 -profile:v high -bf 2 -g 25 -refs X -preset veryslow -crf 18 -pix_fmt yuv420p -movflags faststart "output.mp4"

I just changed the number of ref frames.

15 ref frames, corruption:
https://youtu.be/ul4BkEtCtps

14 ref frames, corruption:
https://youtu.be/QLBlqoV6KxY

13 ref frames, corruption:
https://youtu.be/JarNcaMm5n0

12 ref frames, no corruption:
https://youtu.be/kHEHzIIWQ2g

So it seems like the h264 decoder that Youtube uses has problems with a higher number of ref frames. Isn't that weird, I would guess that they would use I high "quality" decoder? Can it be because of performance? I lower quality decoder can be faster?

Thank you for your help!

rwill
11th April 2022, 15:01
I did some testing and the number of ref frames seems to be the problem.
------
13 ref frames, corruption:
------
12 ref frames, no corruption:
------
So it seems like the h264 decoder that Youtube uses has problems with a higher number of ref frames. Isn't that weird, I would guess that they would use I high "quality" decoder? Can it be because of performance? I lower quality decoder can be faster?



Well, 2560x1440 has 14400 Macroblocks.

H.264 Level 5.2 supports a decoded picture buffer size of up to 184320 Macroblocks, so at your resolution 12.8 ref pictures.

The next level (6.0) supports a DPB of 696320 ( so 48.35 ref pictures of your resolution ).

Maybe your stream does not have the correct level set ? Or youtubes H.264 decoder initializes at Level 5.2 for whatever reason ? I don't know if they are using hardware or software decode - a hardware decoder could explain such behavior.

nevcairiel
11th April 2022, 15:13
Level 6 is generally not well supported in hardware due to DPB limits - assuming they use a hardware decoder for acceleration, which is certainly a likely scenario.

Generally, that many ref frames are often not very beneficial, and for >1080p you might also benefit from using newer codecs.

benwaggoner
11th April 2022, 23:47
You don't want to exceed the number of reference frames for your profile, level, and frame size listed here: https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels. Level 4.2 is generally quite safe to use these days. As said, if you want to go above 1080p, I'd suggest using x265 and HEVC.

ZeB
12th April 2022, 09:01
Well, 2560x1440 has 14400 Macroblocks.

H.264 Level 5.2 supports a decoded picture buffer size of up to 184320 Macroblocks, so at your resolution 12.8 ref pictures.

The next level (6.0) supports a DPB of 696320 ( so 48.35 ref pictures of your resolution ).

Maybe your stream does not have the correct level set ? Or youtubes H.264 decoder initializes at Level 5.2 for whatever reason ? I don't know if they are using hardware or software decode - a hardware decoder could explain such behavior.

That makes a lot of sense. The encode reports as "High@L6" in Mediainfo. So the stream is correct, right?

I guess that level 5.2 (12 ref frames) is the maximum recommended when encoding for Youtube.

Command line:
ffmpeg.exe -i "input.avs" -c:v libx264 -profile:v high -level:v 5.2 -bf 2 -g 25 -preset veryslow -crf 18 -pix_fmt yuv420p -movflags faststart "output.mp4"

This works without any corruption.

No mentions of levels in their own guide, just profile "high":
https://support.google.com/youtube/answer/1722171


You don't want to exceed the number of reference frames for your profile, level, and frame size listed here: https://en.wikipedia.org/wiki/Advanc..._Coding#Levels. Level 4.2 is generally quite safe to use these days. As said, if you want to go above 1080p, I'd suggest using x265 and HEVC.

If using x265, what settings is recommended? When searching information everyone just seems to recommend h264 instead. Youtube also recommends h264 in the "official" guide. It just mentions that h265 is supported.

rwill
12th April 2022, 10:29
That makes a lot of sense. The encode reports as "High@L6" in Mediainfo. So the stream is correct, right?

I guess that level 5.2 (12 ref frames) is the maximum recommended when encoding for Youtube.

Command line:
ffmpeg.exe -i "input.avs" -c:v libx264 -profile:v high -level:v 5.2 -bf 2 -g 25 -preset veryslow -crf 18 -pix_fmt yuv420p -movflags faststart "output.mp4"

This works without any corruption.

No mentions of levels in their own guide, just profile "high":
https://support.google.com/youtube/answer/1722171



If using x265, what settings is recommended? When searching information everyone just seems to recommend h264 instead. Youtube also recommends h264 in the "official" guide. It just mentions that h265 is supported.


Regarding the level the stream is correct then.

However if you look at the evolution of the H.264 standard here:

https://www.itu.int/itu-t/recommendations/rec.aspx?rec=14659

in appendix A, Table A-1, the level limits...

H.264 (V10) (02/2016) does not list a level higher than 5.2, like, there is no level 6.0 or higher.
H.264 (V11) (10/2016) does list level 6 and higher.

So higher resolutions and higher DPB sizes got first added in October 2016.

So maybe decoders done before ~10/2016 are somewhat untested with Levels limits above 5.2, who knows.

I wonder what would happen if one uploads some crafted 1440p video which uses 16 ref frames and then only references ref frames whose size exceed the level 5.2 limits to youtube. Maybe one would be able to dump some hardware reserved memory of the youtube server ? maybe the job crashes the youtube decoder and breaks something ? I am eager to find out but at the same time am somewhat scared that Youtube might get grumpy when messing with their setup.

For x265 I'd just use "-preset slow" or slower and "-tune ssim" with some nice high bitrate or low crf. Oh and I'd specify a level. Maybe Level 5 High Tier like some UHD Bluray ?

benwaggoner
14th April 2022, 20:31
I've never seen a real-world H.264 file that used more than Level 5.2 on purpose. The only reason those get made is because x264 doesn't do a good job of setting a default level or constraining parameters to those legal for the target level.

for x265, a good start would be x265 --preset slow --rksip 2 --profile main10 --no-sao --crf 12.

Whether x264 or x265 is better for you depends on whether you're more constrained by encode time or file size/upload time. x265 takes longer to encode, but delivers equivalent quality at a lower bitrate.