lisamelton / video-transcoding-scripts

Utilities to transcode, inspect and convert videos.
MIT License
603 stars 76 forks source link

--480 Preset? #15

Closed scottwf closed 9 years ago

scottwf commented 9 years ago

I just found your script and it looks like just what I need right now, but I also have some kids show that I've ripped at 720 and really only need 480 to save space. Is it a lot of work to add an additional resize preset?

lisamelton commented 9 years ago

Scott,

Thanks. I think you're the first person who's requested this feature. Congratulations! :)

Seriously, I've considered adding a --480p option before. The problem with an implementing it is deciding on the best value for a horizontal constraint because a "perfect" value isn't possible.

Let me explain...

Here's the current code for the three different constraint options:

    --720p|--resize)
        [ "$1" == '--resize' ] && deprecated_and_replaced "$1" '--720p'
        constrain_width='1280'
        constrain_height='720'
        ;;
    --1080p)
        constrain_width='1920'
        constrain_height='1080'
        ;;
    --2160p)
        constrain_width='3840'
        constrain_height='2160'
        ;;

Notice anything similar about those widths and heights? Yes, they're all perfect 16x9 aspect ratios.

So, if the height is 480 then what's the width if we stick to 16x9? Unfortunately that's not an integer. Basically, it's 853.3333333.... And we need not just an integer, but an even-numbered integer. That means we have to approximate the value by choosing 854 like this:

    --480p)
        constrain_width='854'
        constrain_height='480'
        ;;

But if we do that, then the video will always have to be scaled narrower by one pixel when displayed.

Can you live with that imprecision? If so, I can add this feature in my next update.

(And anybody else reading this, please feel free to comment. Thanks!)

finnhughes commented 9 years ago

I think you may be over thinking it Don, I'd guess this is going to be played on an HD display, assuming it's a telly that's 1920 pixels wide and the video is going to be watched fullscreen it's being scaled by a fractional number of pixels anyway. I'm not aware of any screen standard that's an even multiple of 854. Also I think any player that expects 16:9 480p will be expecting 854. As a side note all that scaling would make me tempted to turn down some of the sharpening x264 does since it's just going to be smeared anyway, not that I'd ever take the time to do the investigation mind.

The main reason I'm replying is because I don't use twitter but wanted to say how awesome this project is :)

I've used variations of all your older bitrate control approaches but this new one seems both novel and a perfect fit for your (and my) use case. I also don't know why setting the VBV buffer to half the bitrate is the magic number. I wonder whether you're effectively disabling some of the "cleverness" of the encoder by preventing it trying to spread the bits evenly over many different types of frames, instead it has to fallback on making sure each frame chooses similar quantizers to those around it. OK that's wild speculation, but it feels like it's probably an implementation detail of x264 rather than something that is implied by the standard. Have you had any other discussions on what makes it work in a place I can read it?

lisamelton commented 9 years ago

Finn,

I like to think it's being careful and deliberate when adding a feature to make sure people understand the side effects. :)

These constraints mean the output video, after the pixels being scaled one direction, will then be scaled in the orthogonal when displayed. This could be noticeable when then scaling up something that small to an HD screen.

Then again, maybe you'll never see it. But it's best to know before I do the typing. :)

And, thanks, I'm glad you like the scripts.

As for the VBV buffer trick, I suspect setting it to half the maximum rate prevents the x264 encoder from being too aggressive. In fact, your geeky guess may very well be correct. The developers don't have much documentation on this other than their source code. And I haven't yet found anyone else writing about it either.

I know from extensive testing I did last month that setting the buffer size to the minimum or setting it to the same value as the maximum rate still has unpleasant and ugly side effects for some inputs at these low bitrate targets, e.g. 5 Mbps for 1080p.

scottwf commented 9 years ago

I'm sure glad there are people smarter than me that create great scripts for people like me to run and request our features. I'm pretty sure that when my kids are watching Sid the Science Kid via Plex they won't notice a little imprecision. Thanks

lisamelton commented 9 years ago

Scott,

I'll consider that a "yes" then. :)

OK, I'll probably have the feature in sometime in the next few days. I'm trying to gather features together this time before I make a new release. I'll leave this issue open until then.

BTW, two thumbs up on Plex. That's a great product. However, I don't have much experience with "Sid the Science Kid." :)

lisamelton commented 9 years ago

Scott,

It turns out that constraining the video to 854x480 pixels doesn't really save all that much space compared to using the --720p option because the target bitrate is almost as big.

So, I'll have to noodle on this one awhile before I check in a change.

Perhaps the right way to do this is to finally expose the constraint controls in the API with --constrain-width and --constrain-height options.

finnhughes commented 9 years ago

Isn't the target bitrate 2Mbps v.s. 4Mbps? Having said that it does make sense to me that x264 is going to hit your quality constraints with 4Mbps 720p where it struggles with 2Mbps 480p. Since increasing the number of pixels tends to make them more similar H.264 can do a better job at compressing the pixels, that's a bit dependent on content. With a scene like grass panning at the right (wrong) distance HD can have enough detail to show the individual blades where SD just shows a sea of green and then HD will be much more expensive to encode than SD. The example content given by Scott is animated which I'd guess is a good example of content where increasing the resolution is very cheap...

A side note is that you get the same behaviour when changing the framerate. Also (IIRC) when x264 introduced 10bit encoding they found it more efficient than 8bit even on 8bit content, simply because the internal representations had more information to work with.

lisamelton commented 9 years ago

No, the target bitrate isn't 2 Mbps because the proposed constraint width we're talking about is larger than 720 pixels. The way the script works now is that anything that fits inside a 720x576 pixel boundary gets a 2 Mbps target, and anything larger gets a 4 Mbps (or even still larger) target.

And I was stupidly forgetting this last night when I added the code snippet above to the script. :)

All I need to do to solve the problem is simply modify the boundary check so 854x480 gets the 2 Mbps target. Since it's actually smaller in terms of the number of pixels it can contain compared to 720x576, this should be fine from a rate control standpoint.

However, it should be noted that this could mean these "480p" videos are at H.264 level 3.1 instead of level 3.0 because they're wider than 720 pixels. But I'll need to test that to be sure. And even if is, that's probably not a deal breaker for the implementation.

lisamelton commented 9 years ago

OK, the new patch works and, using a Blu-ray Disc rip as input, produces better quality output than a DVD. At least for widescreen content.

Plus, it remains at H.264 level 3.0 like DVD output.

I'll probably check this in tomorrow after some more testing and when I complete this other patch I'm working on.

lisamelton commented 9 years ago

The --480p option is now in version 5.10. Let me know how it works for you.

I'll close this issue, but feel free to continue commenting here.