lisamelton / video_transcoding

Tools to transcode, inspect and convert videos.
MIT License
2.39k stars 160 forks source link

Transcoding video captured from an HDMI capture device #141

Closed ddribin closed 7 years ago

ddribin commented 7 years ago

Hi all,

I'm trying to use transcode-video in what's probably an unintended use case, and I've got a few questions.

But first, let me start off with what I'm trying to do. I use Open Broadcasting Software (OBS) to stream video games to Twitch.tv from an Elgato HD60 HDMI capture device. OBS also simultaneously saves recordings locally. OBS will stream to Twitch at around 2500 Kbps, but for recording, I use a much higher quality setting, which they call Indistinguishable Quality, and is supposed to be indistinguishable from lossless. As you might imagine, this creates pretty large files.

This is where I'm thinking transcode-video might come in handy. The local OBS recordings are 720p30 at around 21 Mbps. Sometimes I'll use OBS to record only, without streaming, and then it captures 1080p60, which clocks in up to 30 Mbps. I'm thinking of using transcode-video to shrink down these massive files for posterity and save archival disk space.

So here's my questions:

  1. Is it crazy to to use transcode-video for this? The ~3x disk savings is very enticing, but am I sacrificing a quality that I will regret later? Things seem to look okay to me, but I'm not an expert. I may be better off tweaking the OBS recording settings, but I would think non-realtime transcoding would easily provide better results.

  2. When transcoding a 1080p60 video, by default transcode-video uses 30 FPS. I can obviously override that with --limit-rate 60, but does than mean I should be targeting a higher bitrate? I'm assuming the 6000 Kbps target is for 24 FPS movies, not 60 FPS video.

  3. For some videos, I'll get a bunch of VBV underflow warnings while transcoding. What does this mean? Is it bad? Or can I just ignore it?

  4. What exactly does --quick do? I can't really seem to notice a difference, and it seems like magic. ;-)

Thanks!

-Dave

lisamelton commented 7 years ago

@ddribin Great to hear from you, dude! And let me just say after reading about what you're trying to do, what a geek! :)

OK, here are my answers to your questions:

  1. No, this is a perfect scenario for transcode-video and plays to its strengths of compression and portability. However, keep in mind that when I transcode anything myself, e.g. Blu-ray or DVD rips, I never get rid of the high-bitrate, huge-ass originals. That's why god invented the NAS. And on the seventh day, he made hard disks cheap. So, let the lord bless you with a few terabytes. :) Seriously, I recommend you try both -- tweaking your recording settings and using transcode-video -- and then see which one you like better.

  2. Good question. I've actually never considered this since I don't transcode "live" video. But doubling the output bitrate seems excessive. Why not try a 25 or 50% bump using the --target option and compare that to the default?

  3. Ignore the VBV underflow warnings. To quote from the FAQ section in the README:

    ...these warnings are simply a side effect of my special ratecontrol system. The x264 video encoder within HandBrake is just being overly chatty. Ignore it. Nothing is wrong with the output from transcode-video.

  4. The --quick option is magic! :) Basically I'm tweaking x264's reference frames, b-frames, partitions, motion estimation and ratecontrol lookahead settings to speed things up without sacrificing quality like the fast, faster, veryfast, etc. presets. The key is to never fuck with subpixel motion estimation and mode decision settings like those presets do because that's where you really start to get noticeable blocking and other artifacts. I use the --quick option for all my transcodings now but I don't always recommend it for archival-delete-the-original scenarios. Your mileage may vary.

Is there anything else I can confuse you about?

ddribin commented 7 years ago

@donmelton Thanks for the quick response! Sorry for slacking on my reply. Work is... well, you know how it goes. And, yeah.... once a geek, always a geek, I think. ;-)

Replies to your answers:

  1. Yeah, maybe I do just keep the originals around and buy a few more disks. I'm not sure it makes much sense to keep originals and transcodes, though. That would just use more space than originals alone. If I do transcode, I would delete the originals. But that's the scary part.

    Then again, on the other hand, I'm not sure I need the original quality, when the transcode looks so damn good. Streaming is going to potentially create tons of video. It's pretty easy to sit down and stream or record for 3-4 hours, creating a 50 GB file. Backing all that up to other local/NAS disks and/or uploading it to something like Backblaze will take a lot of space and time. I may be willing to sacrifice quality for the perf gains of smaller files.

    I mean, let's be honest. The vast majority of this stuff no one, even future me, is ever going to watch. Maybe if something interesting happens, I can keep the original for that one segment. But am I really going to watch all 50 hours it's going to take me to play Breath of the Wild 30 years from now? I'm doing this more "because I can" not really because there's a good reason. ;-)

    Re-reading the previous paragraph, I think I just talked myself into transcode-and-delete. ;-)

  2. Thanks, I'll try giving the bitrate a bump. Any tips on looking for quality issues? Are there any tools to help out? I cannot even tell a difference between an original 1080p60 at 30 Mbps and its 6 Mbps transcode. That's such a huge bitrate difference, I feel like there has to be a difference that I'm just not seeing. Or maybe it's just the magic of having more CPU time to encode offline vs. live. When using OBS to stream and record live it's only using about 20% CPU.

  3. Ah, whoops! I usually do check the FAQ and RTFM, but somehow skipped over this. Good to know I can ignore it.

  4. I have no idea what you are talking about, but it's great. ;-)

Also, a bit more on why I'm recording at all, rather than just stream and use Twitch as my definitive source. First, the upload to Twitch might glitch out, so it's nice to have a local copy. Second, the quality of the Twitch upload is pretty poor, at only 2,500 Kbps. If I ever want to upload a clip to YouTube, it's nice to have the higher quality recording available.

Thanks again,

-Dave

ddribin commented 7 years ago

So, being the consummate geek that I am, I tried to see if I could quantify the transcode quality, as described by this answer on Super User, by comparing the PSNR (Peak Signal-to-Noise Ratio) of various transcodes.

I started with a 3:11 (3min 11sec) clip that I captured at 1080p60. That captured bit rate is 31.32 Mbps. I then transcoded it at various target bit rates both with --quick and without. Here are the results:

Transcode: PSNR y:35.935412 u:44.487342 v:45.913438 average:37.443182 min:16.824555 max:50.267461
Quick:     PSNR y:35.917079 u:44.384920 v:45.785845 average:37.419434 min:16.825751 max:50.071217
7500 [Q]:  PSNR y:35.963479 u:44.523137 v:45.953226 average:37.471780 min:16.825667 max:50.797766
9000 [Q]:  PSNR y:35.993952 u:44.628198 v:46.084110 average:37.507033 min:16.824275 max:51.494783
15000 [Q]: PSNR y:36.061150 u:44.890310 v:46.431386 average:37.586687 min:16.822733 max:53.621123
20000 [Q]: PSNR y:36.090747 u:44.996408 v:46.579683 average:37.621184 min:16.822234 max:54.546419
25000 [Q]: PSNR y:36.110617 u:45.065164 v:46.672198 average:37.644064 min:16.821914 max:55.468788
30000 [Q]: PSNR y:36.110662 u:45.065329 v:46.672322 average:37.644114 min:16.822120 max:55.487360
30000:     PSNR y:36.128395 u:45.153057 v:46.789431 average:37.665993 min:16.822956 max:56.486342

I'm far from an expert here, but the way I understand it from this blog post is that the higher the PSNR the better, with 38 db being the minimum PSNR considered "acceptable".

So the results are somewhat surprising. The average PSNR varies from 37.42 (worst at 6000 Kbps "quick") to 37.67 (best at 30 Mbps "no quick"). That seems pretty minimal. I'm almost wondering if there's something odd with the transcode, or I'm calculating the PSNR incorrectly. Here's how I created the 25,000 Kbps transcode:

% time transcode-video --target 25000 --quick --limit-rate 60 --mp4 -o 25000-quick reference/2017-04-16_01-09-11.mp4

The only weird thing I see in the transcode log is this:

apply_h264_level [warning]: framerate (60.000) too high for level 4.0 at 1920x1080 (max. 30.118)
encx264: unparsed options: vbv-maxrate=25000:vbv-bufsize=31250:crf-max=25:level=4.0:ref=1:qpmax=34:analyse=none:rc-lookahead=30

I'm not sure if this is a problem, but I've attached the full log file as 2500-quick-2017-04-16_01-09-11.mp4.log.zip.

And here's how I calculated the PSNR with ffmpeg (as taken from this StackOverflow question):

% ffmpeg -i 25000-quick/2017-04-16_01-09-11.mp4  -i reference/2017-04-16_01-09-11.mp4 -filter_complex "psnr" -f null -

It's also quite possible that PSNR is a crap metric for this video clip. Maybe the clip is too short? I dunno. Also, PSNR does not necessarily indicate the visual quality of a transcode. Netflix has a perceptual video quality metric called Video Multi-Method Assessment Fusion (VMAF), described in this blog post. They've got an Open Source implementation, but I haven't taken the time to figure it out how to use it, yet.

lisamelton commented 7 years ago

@ddribin Sorry I took so long to reply this time. I've been grotesquely ill for several days, an activity that I do not recommend if you can avoid it. Today I'm finally back at my keyboard, so...

As you suspected, PSNR really is a crap metric for assessing video quality. Also, using ffmpeg that way is essentially re-transcoding to evaluate an existing transcoding -- not a good idea. And not only is PSNR a bad idea, so is using SSIM. To quote again from the FAQ section in the README regarding how I assess video quality:

I compare by visual inspection. Always with the video in motion, never frame by frame. It's tedious but after years of practice I know which portions of which videos are problematic and difficult to transcode. And I look at those first.

In addition, I use the query-handbrake-log tool to report on ratefactor, the average P-frame quantizer, to get a relative quality assessment from the x264 encoder.

What I don't use are peak signal-to-noise ratios or a structural similarity index in an attempt to objectively compare quality. Although both metrics are available to the x264 encoder, enabling either of them ironically disables key psychovisual optimizations that improve quality.

While VMAF from Netflix looks interesting, it's basically overkill for what you're trying to do here. I would not recommend it either. As I've said many times on podcasts, don't try to emulate Netflix. They have vast server farms to heat the planet and waste time with. You don't.

Just get familiar with a few short passages of your videos that are complex, busy, noisy, dark, and/or flat. And just A/B test the bejesus out of them with various transcoding options. Trust me when I say that you'll quickly learn when the bitrate is too low. And spending your time training your eyes is a much better investment of your time.

ddribin commented 7 years ago

You know, I did actually read that part of the README at one point, but it didn't make sense at the time, so I forgot about it. I agree that training my own eyes is the best investment, but that's always tricky. You don't know what you don't know! I can definitely see blockiness and other minor artifacts, but I'm sure there's other stuff I don't currently notice that I should. I'm not confident I can make a good decision right now, as to whether the transcode is good enough to throw away the original or not. I'll probably keep the originals, for now, until I start filling up on disk space.

In any case, do you think this is a problem?

apply_h264_level [warning]: framerate (60.000) too high for level 4.0 at 1920x1080 (max. 30.118)
encx264: unparsed options: vbv-maxrate=25000:vbv-bufsize=31250:crf-max=25:level=4.0:ref=1:qpmax=34:analyse=none:rc-lookahead=30

I did just check the README/FAQ again, and I didn't see it there, this time ;-) I can file a separate issue for this, if needed, so it doesn't get buried in this discussion.

-Dave

lisamelton commented 7 years ago

@ddribin Sorry, I somehow missed that warning message issue in my still feverish state yesterday.

I'm not sure I would call that a bug in transcode-video or an unhelpful feature. :) This is because transcode-video automatically forces the H.264 encoder level for each resolution to remain compatible with certain playback devices, particularly older Apple TVs and iPods. And it does this regardless of frame rate because it can't always know which frame rate HandBrake will pick.

I suppose I could make transcode-video "smarter" so that if the user specifies a frame rate, like you're doing, then it could use a higher H.264 encoder level. You can open a issue on that if you want.

In the meantime, you can work around it by adding --handbrake-option encoder-level=4.1 to your command line whenever you also use --limit-rate 60.

ddribin commented 7 years ago

@donmelton Thanks, will try that! And thanks again for all your help. I'm still learning a lot, here. Rest, and feel better!

lisamelton commented 7 years ago

@ddribin Thanks! I'll keep this open for awhile until you get a chance to try that. Besides, I'm sure you'll have another set of questions by this weekend. :) Plus, I'm enjoying the conversation.

lisamelton commented 7 years ago

@ddribin It turns out I'll be making a change to transcode-video soon in the same area of the source code as your suggested encoder level enhancement, so I'll likely implement your feature at the same time. Comedy is all about timing. :)

ddribin commented 7 years ago

BTW, I finally got around to trying the workaround, and it works great. But I did need to use level 4.2. Level 4.1 still ha a limit of 30fps for 1080p. I found this table very helpful, as it also explained what a "level" is.

lisamelton commented 7 years ago

@ddribin Yep, I was just looking at that table again yesterday. I think if you use --handbrake-option encoder-level=auto that should get you the same result. That way you can forget about the table. :)

And let me know if that works! :)

lisamelton commented 7 years ago

@ddribin Hard to believe, but I just noticed there's a bug in my --force-rate code when used with recent versions of HandBrakeCLI due to a change in its default behavior. Because my code is not setting HandBrake's --cfr option, my force-rate option behaves identically to my --limit-rate option. Which is not what it's supposed to do and probably not what most people want.

I'll fix that in the update I'm planning in a few days.

lisamelton commented 7 years ago

@ddribin All the changes are in version 0.17.3 which I just released. Thanks, again!

ddribin commented 7 years ago

@donmelton I will try out the new version. Thanks for everything! Sorry I have not been more responsive, but I haven't had a lot of time to play with this lately.

To close out my end, I'm currently not planning on transcoding my original videos, at this time. I will at some point, as disk space becomes more scarce, but I need to do more playing around and see what settings are "good enough" for me. I still don't have a good enough eye to see what I'm giving up by transcoding.

Also, I wanted to point out a couple of articles I found recently that help me understand your settings a bit more:

In particular, the second post recommends:

To summarize, here’s what you should do, depending on your use case:

  1. Archival — CRF that gives you the quality you want.
  2. Streaming — Two-pass CRF or ABR with VBV-constained bitrate.
  3. Live Streaming — One-pass CRF or ABR with VBV-constained bitrate, or CBR if you can waste bits.
  4. Encoding for Devices — Two-pass ABR, typically.

With this knowledge, I re-read the explanation of how your special ratecontrol system works, and it's starting to actually make sense. I think I just need to find the proper bitrate for my video sources.

Thanks again!

lisamelton commented 7 years ago

@ddribin Thanks for those links. Interesting articles. However, the recommendations are dubious. For example, no one uses "Two-pass CRF" (if there is such a thing) and "CBR" mode (also impractical) doesn't work like he thinks it does.

Also, keep in mind that there's no such thing as an "Archival" transcoding. The original is what you put in your archives. Anything else is just a lesser copy. And how much "lesser" is determined more by bitrate than any other factor.

But that's just me being a cranky transcoding curmudgeon. :)

Have fun and let me know what you decide!

ddribin commented 7 years ago

@donmelton Given Apple's embracing of HEVC (H.265) last week, I am now considering using this as my "archival" codec. It alone should save a bunch of space. I'm not sure if x265 and Handbrake's HEVC support is fully solid yet, though. Plus, I see H.265 in transcode-video is still considered experimental. If there's anything I can do to help test H.265, lemme know!

lisamelton commented 7 years ago

@ddribin I will let you know, sir. But, not to depress you, let me give you a preview of a blog post I'm drafting now:

HEVC/H.265 is clearly the future. It will eventually replace H.264 as our preferred video format. But that doesn't mean such a future is here yet for home transcoders. The open source x265 encoder is making rapid progress, but it's still not entirely practical for that domain. And it remains to be seen whether the HandBrake, FFmpeg or Libav teams will integrate Apple's HEVC implementation. My guess? Not anytime soon.

And keep in mind that the HandBrake, FFmpeg or Libav teams never integrated Apple's H.264 implementation either.

ddribin commented 7 years ago

Yeah, that makes sense. Not sure I need Apple's implementation. x264 seems pretty darned good, but as you say, still to early to know if x265 will be on par. But I am wondering if using Compressor, which will have HEVC support, is something I should be looking at. It's not nearly as tweakable, but might be good enough. Or maybe, again, I should just buy more disk. ;-) The lure of re-encoding this non-mission critical video just won't let go, though.

lisamelton commented 7 years ago

@ddribin Compressor works fine as long as you're OK with its limitations on input and output. For example, you'll never be able to transcode a DVD or Blu-ray Disc rip with Compressor. It's just not made for that. However, it can work well with input from video cameras and such.