我想使用 youtube-dl 获取 URL,以及-g
不下载视频的“模拟”选项。
因此我给出了以下命令:
youtube-dl -g https://www.youtube.com/watch?v=k4JGSAmu4lg
7 到 8 秒后输出以下结果
https://r20---sn-cvh7zn7d.googlevideo.com/videoplayback?initcwndbps=1113000&mt=1408702970&requiressl=yes&ipbits=0&sver=3&fexp=901454%2C902408%2C919145%2C924626%2C927622%2C927904%2C931330%2C931983%2C934024%2C934030%2C934804%2C945118%2C945308%2C946023%2C951914&ratebypass=yes&signature=38F111D46D72FFC50B47D50B3C9A631099BF5F83.FA134C91F407989B95ACADC1F1F6946B8F18C158&upn=tU0u5t7A2Uw&sparams=id%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Cmm%2Cms%2Cmv%2Cratebypass%2Crequiressl%2Csource%2Cupn%2Cexpire&mm=31&expire=1408724634&id=o-AJNPuDp9TKMKiwzUwvSk76W7JdA0cx0bRSum9mPJJ7Vo&mv=u&source=youtube&ms=au&key=yt5&ip=115.113.1.50&itag=18
但问题是查询 URL 大约需要 7 到 8 秒。
有什么方法可以让它更快吗?
答案1
时间都用来做工作
该命令不会挂起或等待浪费时间的事情,
它实际上会执行需要时间的工作;它很可能通过累积多个小的网络延迟来花费时间。但也可能是 YouTube 端存在延迟,这些延迟会累积起来。
这只是下载所需 HTML 所需的时间;
该命令需要依次发出至少两个 HTTP 请求,甚至可能更多。
所以如果有什么事情发生缓慢,那么它的数量就会乘以请求数。
对于我来说,在非常快的线路上花费 1.5 秒 - 这与 8 秒相差不远。
如何找出答案
我将显示我用来查找的命令:
为了使示例更整洁,我们对 URL 使用了变量:
$ u="https://www.youtube.com/watch?v=k4JGSAmu4lg"
我们想要测量命令的持续时间;使用命令时time
需要注意不要混淆命令和 shell 内置命令。我们使用一个小函数来缩短行数:
$ t(){/usr/bin/time -f 'Time: %es' "$@";}
您的命令写出视频文件的 URL(截断为 80 列):
$ youtube-dl -g "$u"
https://r20---sn-cxg7en7d.googlevideo.com/videoplayback?signature=091F68E823
让我们测量一下它在我的电脑上运行所需的时间:
$ t youtube-dl -g "$u"
https://r20---sn-cxg7en7d.googlevideo.com/videoplayback?signature=091F68E823
Time: 1.44s
好的,一秒半。比问题中快,但也没有快多少。但它是如何花费时间的?也许它确实以某种隐藏的方式下载了视频并将其丢弃?该视频为 360p,时长 11 分钟。不带任何选项下载大约需要 13 秒 - 时间长十倍。
需要仔细查看,使用详细选项-v
:
$ t youtube-dl -v -g "$u"
[debug] System config: []
[debug] User config: []
[debug] Command-line args: ['-v', '-g', 'https://www.youtube.com/watch?v=k4J
[debug] Encodings: locale 'UTF-8', fs 'UTF-8', out 'UTF-8', pref: 'UTF-8'
[debug] youtube-dl version 2014.02.06
[debug] Python version 2.7.6 - Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14
[debug] Proxy map: {}
https://r20---sn-cxg7en7d.googlevideo.com/videoplayback?sparams=id%2Cinitcwn
Time: 1.40s
哦,在打印“[debug]”行之前有一些延迟。看起来它youtube-dl
花费了一些时间进行自己的配置设置。大约四分之一秒,不是我们想要的延迟。但我们可以从中了解到,实现youtube-dl
本身可能很慢。
在消息之后,直到打印结果 URL 之前什么都没有发生。所以我们仍然没有看到有趣的部分。
该选项-g
是“模拟”视频下载,即它执行复杂的部分,找出那个半秘密的 URL,打印它,但最后跳过实际下载。有一个类似的选项-s
不输出 URL,其他方面似乎相似。我们假设它足够相似,如果它花费的时间大约相同;我们需要检查一下。
$ t youtube-dl -v -s "$u"
[debug] System config: []
[debug] User config: []
[debug] Command-line args: ['-v', '-s', 'https://www.youtube.com/watch?v=k4J
[debug] Encodings: locale 'UTF-8', fs 'UTF-8', out 'UTF-8', pref: 'UTF-8'
[debug] youtube-dl version 2014.02.06
[debug] Python version 2.7.6 - Linux-3.13.0-24-generic-x86_64-with-Ubuntu-14
[debug] Proxy map: {}
[youtube] Setting language
[youtube] k4JGSAmu4lg: Downloading webpage
[youtube] k4JGSAmu4lg: Downloading video info webpage
[youtube] k4JGSAmu4lg: Extracting video information
Time: 1.45s
好的,-s
花费的时间与 相同-g
,因此可以替换它们进行测试。
更有趣的是,我们现在获得了更多输出。并且它以有趣的时间打印出来:这些行以相似的延迟打印出来,因此看起来它们与实际花费我们寻找的时间的操作有关。
从消息来看,至少下载了两个网页。但我们可以假设“页面”一词不是指单个 HTTP 请求和单个 HTML 文档。
我们学到了什么?
重点是,程序的工作确实需要时间,它不是在等待什么,也不是在挂起。
此外,我们看到多个步骤花费的时间相似。没有太多需要计算的内容,所以这在某种程度上是网络往返,累加起来。
这意味着,我们的连接延迟仅在这里很重要。连接的吞吐量无关紧要。
如果您要加快互联网连接速度,使其能够以双倍速度传输数据,那根本无济于事。但如果您可以获得更好的ping
速度,那将使其更快。
不过,这与互联网服务提供商的“ping”时间无关;重要的是整个 YouTube 的 ping 时间 - 而且可能无法更改。
有趣的是,对于下一步,即下载视频,对快速线路的要求恰恰相反:延迟根本不重要,吞吐量才真正重要。
还不累吗?
是否想要更多细节来了解时间真正花在了什么地方?
下一步是跟踪 HTTP 连接;我怀疑它可能会显示远不止两次的往返,例如重定向。您可以使用wireshark
,或日志记录 HTTP 代理,或者strace
仅计算连接或写入的系统调用。
今天,我们已经对网络这个“兔子洞”进行了深入的探究。
答案2
只需执行以下操作:
youtube-dl -j --flat-playlist 'https://www.youtube.com/watch?v=k4JGSAmu4lg' | jq -r '.id' | sed 's_^_https://youtube.com/v/_'
答案3
可能还有其他原因。youtube-dl
以压缩的 Python 应用程序形式分发。每次运行它时,它都会将其提取出来然后运行。
您可以使用unzip
命令手动提取它。然后__main__.py
像运行一样运行youtube-dl
。在像 Pi 这样的低功耗计算机上,这将显著提高您的性能。