ekisu / mpv-webm

Simple WebM maker for mpv, with no external dependencies.
MIT License
571 stars 33 forks source link

Make 2-pass encoding actually work. #6

Closed ekisu closed 4 years ago

ekisu commented 6 years ago

It turns out that the script is using an incorrect way to 2-pass encode. The correct way shouldn't output to NUL or /dev/null on the first pass, but instead output to the same file of the second pass call, only adding flags=+pass1 and flags=+pass2 to ovcopts on each call.

As it turns out though, using 2-pass encoding (at least with libvpx) with mpv actually results in terrible video quality, way worse than a simple single pass encode. I'm not sure if this is a mpv bug, or I'm just doing it wrong.

"correct" two pass encode single pass encode

ekisu commented 6 years ago

A bit more info on this:

It seems that mpv's first pass log file is broken.

TheAMM commented 6 years ago

I looked into this - going through mpv's source, ffmpeg's source, how they save the frame statistics (base64 encoded chunks btw), how they load it (I almost expected an "Aha!" with the base64 padding but no, they're aligned). From what I've seen, there should be nothing wrong with how mpv saves (or reads) the log, but I don't work with C.

(I did find out that ffmpeg's and mpv's logs generated from the same file differ in a pattern but I suppose that's just a libvpx or some other version difference.)

Anyhow, when I started experimenting with doing 2-pass VP8 encodes and swapping the logfiles around, I realized both fail at doing it properly. Both ffmpeg and mpv have that fuzzy start (it gets better after a few seconds, but pales in comparison to the first frame of a plain 1-pass encode) when doing the equivalence of -b:v 417607 -minrate 417607 -maxrate 417607. So welp. I'm inclined to believe libvpx is just fucked up on 2-pass.

Could you share your working ffmpeg 2-pass arguments, if it was libvpx/VP8 you succeeded with? I did my tests with ffmpeg version N-89056-gd8ea66ab33-static from John's static builds and a somewhat older mpv 0.25.0-365-g8e20ef4. Also, I did not test 2-passing h.264, so it could be broken in mpv and fine with ffmpeg.

ekisu commented 6 years ago

Could you share your working ffmpeg 2-pass arguments

For the encode in the OP (renamed ffmpeg's output pass logfile): actually this wasn't in the OP, link.

.\ffmpeg -i '.\[HorribleSubs] Aho Girl - 02 [720p].mkv' -ss 00:02:15.000 -to 00:02:25.000 -c:v libvpx -crf 10 -pass 1 -b:v 1998k -threads 4 -an -passlogfile testlogfile test.webm
.\mpv.com '.\[HorribleSubs] Aho Girl - 02 [720p].mkv' --start 00:02:15.000 --end 00:02:25.000 --ovc libvpx --aid no --ovcopts=b=1998k,threads=4,flags=+pass2 test.webm

mpv --version:

mpv e272dccb2 (C) 2000-2017 mpv/MPlayer/mplayer2 projects
 built on Thu Oct 12 00:40:00 AEDT 2017
ffmpeg library versions:
   libavutil       55.79.100
   libavcodec      57.108.100
   libavformat     57.84.100
   libswscale      4.9.100
   libavfilter     6.108.100
   libswresample   2.10.100
ffmpeg version: git-2017-10-11-e4d5310a

ffmpeg binary: ffmpeg version N-86809-g012620a, Zeranoe static builds.

Anyhow, when I started experimenting with doing 2-pass VP8 encodes and swapping the logfiles around, I realized both fail at doing it properly.

I'm not really into this, so I don't know how would a proper 2-pass be like - I assume that what ffmpeg generates should be the closest to a proper one. However, at least by swapping logfiles mpv produces a similar output to what ffmpeg does (2-pass with mpv generates a 700KB video, both single-pass and ffmpeg 2-pass output have at least 2MB).

I did find out that ffmpeg's and mpv's logs generated from the same file differ in a pattern but I suppose that's just a libvpx or some other version difference.

I don't see the pattern there. It would be interesting to see the logs with the same libvpx/libavcodec for both ffmpeg and mpv.

TheAMM commented 6 years ago

I don't see the pattern there

Look for the lone | in the middle, it marks the differing lines. In those logs the mpv log will differ every 144 bytes (mpv has 22 x 00 00 7a 40 and ffmpeg has 18 x d8 66 14 41 and 4 x d4 66 14 41).

I'm not really into this, so I don't know how would a proper 2-pass be like

I don't really either, but I expect a 2-pass not to fuzz out at the start. If 1-pass can do it with even with bitrate constraint, shouldn't a 2-pass do it better?

Using shorter clips (15 seconds instead of the ~80 seconds my test video was) I've arrived at the same state, mpv's first pass sucks. However, with the 80s clip, even with ffmpeg the start will always blur for whatever reason.


Egh, I ran a lot of tests, on ffmpeg, on mpv, different logfiles, different durations, options, so forth, enough to make my head spin and get me wholly confused on what exactly works anymore. I'll return to this later with a clearer mind, but since "long" clips seem to blur out even with ffmpeg, it'd be easy to just stick with 1-pass.

ekisu commented 6 years ago

@deterenkelt 2-pass is working on the ffmpeg branch, which I still have to test throughly to merge into master (but don't have a lot of time/interest right now).

As for Nadeshiko, I'm not the best at reading bash code (it just looks like gibberish to me at first sight), but I might look at it later.