ytdl-org / youtube-dl

Command-line program to download videos from YouTube.com and other video sites
http://ytdl-org.github.io/youtube-dl/
The Unlicense
132.36k stars 10.04k forks source link

wrong bitrate setting for opus postprocessing #28389

Open knarrff opened 3 years ago

knarrff commented 3 years ago

Checklist

Verbose log

[debug] System config: []
[debug] User config: [u'-o', u'%(title)s.%(ext)s']
[debug] Custom config: []
[debug] Command-line args: [u'-v', u'-ix', u'--audio-format=opus', u'https://www.youtube.com/watch?v=MU9oF-YmnyU']
[debug] Encodings: locale UTF-8, fs UTF-8, out None, pref UTF-8
[debug] youtube-dl version 2021.03.03
[debug] Python version 2.7.16 (CPython) - Linux-5.6.0-0.bpo.2-amd64-x86_64-with-debian-10.8
[debug] exe versions: ffmpeg 4.1.6, ffprobe 4.1.6, phantomjs 2.1.1, rtmpdump 2.4
[debug] Proxy map: {}
[youtube] MU9oF-YmnyU: Downloading webpage
[debug] Invoking downloader on u'https://r7---sn-uxax4vopj5qx-cxge.googlevideo.com/videoplayback?expire=1615301355&ei=izZHYLqUJ92ux_APyca-SA&ip=77.13.211.24&id=o-AFOJQoqh2GFpmeuN_v7jgQIJ0Zaho9BxYA_FcyILjqwx&itag=140&source=youtube&requiressl=yes&mh=hO&mm=31%2C29&mn=sn-uxax4vopj5qx-cxge%2Csn-4g5e6nez&ms=au%2Crdu&mv=m&mvi=7&pl=18&gcr=de&initcwndbps=935000&vprv=1&mime=audio%2Fmp4&ns=Sfcnv3ir99luxfd_eSGq7KIF&gir=yes&clen=4035697&dur=249.159&lmt=1600680540168690&mt=1615279473&fvip=1&keepalive=yes&fexp=24001374%2C24007246&c=WEB&txp=1311222&n=UeUjBTMcHkv2mY5n&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cgcr%2Cvprv%2Cmime%2Cns%2Cgir%2Cclen%2Cdur%2Clmt&lsparams=mh%2Cmm%2Cmn%2Cms%2Cmv%2Cmvi%2Cpl%2Cinitcwndbps&lsig=AG3C_xAwRQIgfAOZCi60Kem7_V4-Y3fQtvoI5Voscf2Dm28IU_fkz6QCIQCVwERNf05uFz70_woDviyq248KcM46nn0vzrkM-v3AEw%3D%3D&sig=AOq0QJ8wRQIgRX2sD14z8klAVFFtqxT20oYSuHiYydOAYDLywvYE1dECIQDqIBUvYHNuUZOXlxu9-V7YQ8_NEhWR3kP9YS0n3Jc4VA=='
[download] Destination: Alles Was Ich Habe.m4a
[ffmpeg] Correcting container in "Alles Was Ich Habe.m4a"
[debug] ffmpeg command line: ffmpeg -y -loglevel 'repeat+info' -i 'file:Alles Was Ich Habe.m4a' -c copy -f mp4 'file:Alles Was Ich Habe.temp.m4a'
[debug] ffmpeg command line: ffprobe -show_streams 'file:Alles Was Ich Habe.m4a'
[ffmpeg] Destination: Alles Was Ich Habe.opus
[debug] ffmpeg command line: ffmpeg -y -loglevel 'repeat+info' -i 'file:Alles Was Ich Habe.m4a' -vn -acodec libopus '-b:a' 5k 'file:Alles Was Ich Habe.opus'
Deleting original file Alles Was Ich Habe.m4a (pass -k to keep)

Description

When extracting audio, and the containing format isn't 'opus', but the requested format is, then youtube-dl will call ffmpg to do the convertion. Without specifying the preferred quality, youtube-dl defaults to '5'. This is fine. However, libopus does not support quality-based encoding, which is even mentioned in the youtube-dl source code: https://github.com/ytdl-org/youtube-dl/blob/c6a14755bb9629967fb12536ee8660ca67ff4345/youtube_dl/postprocessor/ffmpeg.py#L307

However, the following check does this:

                if int(self._preferredquality) < 10 and extension != 'opus':
                    more_opts += ['-q:a', self._preferredquality]
                else:
                    more_opts += ['-b:a', self._preferredquality + 'k']

So, in case no quality is set on the command line and opus is requested, self._preferredquality is 5, resulting in execution of the 'else'-branch and an encoding with a bitrate of 5k, also visible in the log above, second to last line. The encoding does not fail, but you can imagine it's quality ...

It is not immediately clear how to resolve this. Assuming we treat values < 10 as quality (like the rest of the code also does), then we could at least set the bitrate to a typical value for music. According to https://wiki.hydrogenaud.io/index.php?title=Opus, this could be 192k. If you want to be really nice, it could be set to (self._preferredquality * 38.4) This would result in 192k for the default of 5, but would make other quality settings at least mean something.

zulc22 commented 3 years ago

^^^^^^^

Was about to make an issue about some videos having unacceptable quality when downloaded as opus. Have reproduced many times -- seems to happen more on older videos?

d3fault commented 2 years ago

Confirming this bug. It's intermittent though, different URLs give different results.

youtube-dl --extract-audio --audio-format opus "https://www.youtube.com/watch?v=azOiTtlN-6E" ^gives good quality output

youtube-dl --extract-audio --audio-format opus "https://www.youtube.com/watch?v=t1C83sIxUyg" ^gives 5k quality output

d3fault commented 2 years ago

I figured out what triggers the different results.

Confirming this bug. It's intermittent though, different URLs give different results.

youtube-dl --extract-audio --audio-format opus "https://www.youtube.com/watch?v=azOiTtlN-6E" ^gives good quality output

This is downloaded as a webm, so a lossless conversion is performed (the ffmpeg command doesn't specify -b:a because it's -vcodec copy)

youtube-dl --extract-audio --audio-format opus "https://www.youtube.com/watch?v=t1C83sIxUyg" ^gives 5k quality output

This is downloaded as an m4a, so a lossy conversion is performed (and the ffmpeg command does specify -b:a)

pukkandan commented 2 years ago

The --audio-quality 0-10 syntax was originally designed for mp3. Due to this, similar issues exist for other conversions as well. For example, while 0 is "best" for mp3, it refers to the worst quality for vorbis.

yt-dlp deals with these issues by re-scaling the user input according to format. Same can be done here. I opted to not convert the 0-10 scale to bitrate for formats that do not support -qa, but I can see the appeal of doing that (might be difficult to agree on the factor to use).

https://github.com/yt-dlp/yt-dlp/blob/5792c950bfd9f8b6730659b3046b41c1aea64c98/yt_dlp/postprocessor/ffmpeg.py#L403-L423

d3fault commented 2 years ago

0 being best is what --help describes, so vorbis should change accordingly. Different codecs will warrant different scales, as 128 kb/s MP3 is vastly different from 128 kb/s Opus. Opus is just a much better codec that can do more with less.

knarrff commented 2 years ago

With this issue I did not necessarily want to create the best possible solution, but to get to a workable solution fast. The current state of a default of 5 and this being interpreted as 5 kb/s for opus is not really usable. I agree that using an codec-provided quality scale would be ideal. However, as this does not seem to exist, we are left with the question what to choose as default. Assuming we stick with a default of 5 and assuming we stick with the interpretation of values in the range of 0<x<10 as quality rating and not bit rate, we have to come up with some mapping of that to bit rates on our own, thus my original suggestion in the ticket description.

d3fault commented 2 years ago

@knarrff in case it wasn't obvious, I filed pull request #30957 fixing this issue, and used your scaling idea (but ended up using 24 instead of 38.4 giving a range of 6 kb/s to 210 kb/s)

knarrff commented 2 years ago

Indeed I was not aware of the request. Thanks!