在家想下载视频到本地,发现很多视频网站的video
标签的src
指向了
Blob: http(s)://xxx.xxx.xxx/xxx
,直接进这个链接的话会显示链接已禁用。
想法:既然能播放视频,就证明视频到最后一定是被 video 拿到了的.
谷歌一圈后发现了:
1.window.URL.createObjectURL(object)
方法会返回该链接
A File, Blob, or MediaSource object to create an object URL for.( https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL )
2.window.URL.revokeObjectURL(objectURL)
,禁用上面返回的链接
A string representing a object URL that was previously created by calling createObjectURL().( https://developer.mozilla.org/en-US/docs/Web/API/URL/revokeObjectURL)
1.hook 了window.URL.revokeObjectURL(objectURL)
来忽略禁用请求,结果没用,依旧被禁用。
2.换个方法,直接 hook 二进制流,你缓存多少,我给你复制多少。查了下MediaSource, 他结合上面的createObjectURL(object)
可以分片的方式加载视频,大概就是看多少,就加多少。
其中的音频和视频分别放在两个 sourceBuffer 中,直接 hook 住SourceBuffer.appendBuffer()
就能实现视频流的截取了。再将每个分片以数组的方式保存下来,最后等视频缓存完后
new Blob(video/audio bufferArray)
这样就实现了视频和音频的保存。
3.由于播放的时候,视频和音频分在两个 SourceBuffer 中,所以最后会得到两个文件。又是一番谷歌,有如下命令:
ffmpeg -i video.mp4 -i audio.mp4 -c:v copy -c:a aac -strict experimental output.mp4
可以将其合并为一个视频。
4.想过用 ffmpeg 的 wasm 库来在线合并,最后输出的,发现 ffmpeg-core 初始化时所需要的文件在国内下载不下来导致报错,从而导致适用的用户可能有点少,所以就没加,可能是我使用方法不对,以后有时间可以改改。
5.发现有些网站的视频是在iframe
标签下的,并且加了sandbox
属性,而有该属性的话就会导致最后的下载被拦截,于是,我使用了如下代码来将页面中的所有frame
替换成无sandbox
属性的:
(function (that) {
let removeSandboxInterval = setInterval(() => {
if (that.document.querySelectorAll('iframe')[0] !== undefined) {
that.document.querySelectorAll('iframe').forEach((v, i, a) => {
let ifr = v;
ifr.removeAttribute('sandbox');
const parentElem = that.document.querySelectorAll('iframe')[i].parentElement;
a[i].remove();
parentElem.appendChild(ifr);
});
clearInterval(removeSandboxInterval);
}
}, 1000);
})(window);
于是有了如下油猴脚本:
英文名:Unlimited_downloader
https://greasyfork.org/en/scripts/445751-unlimited-downloader
Ps: 都是谷歌翻译成英文的,因为英文是个通用语言,所以不同地方的人看起来可能要方便点。
原理:直接 hook 媒体二进制流,换句话说就是你能看到,你就能下载,你能缓存多快,你就能下载多快。
使用方法:安装后,打开任意有视频或音频的网站,等视频缓存条加载完后会自动下载下来。
也可以自己手动开 16 倍速加速缓存,控制台输入:document.querySelector('video').playbackRate = x
感谢分享功能类似插件,大家可以自己挑个来用,互为补充:
@linglin0924 最近有一些不能下载的视频,我都是用这个插件,看他的运行方式,应该也是读流合并的 https://chrome.google.com/webstore/detail/video-downloader-cococut/gddbgllpilhpnjpkdbopahnpealaklle
@hbtech 很有意思,功能跟这个扩展也有点像: https://chrome.google.com/webstore/detail/stream-recorder-download/iogidnfllpdhagebkblkgbfijkbkjdmm
@tammy 我都是调用 you-get 下载的(Firefox 添加“鼠标中键点击下载按钮条用 you-get.exe 下载视频” 的功能 - Ryan 快快跑),对于支持的网站不用说,一流,默认最高画质,在配合你这个搞不支持的网站,那就更舒服了
1
Louis423Lee 2022-05-31 17:41:26 +08:00
感谢 op ,请问能选择视频的清晰度下载吗?
|
2
dabaisuv OP @Louis423Lee 可以的,原理就是 hook 播放的视频的二进制流,你只要能把视频的画质调到对应的清晰度即可。
|
3
goodhellonice 2022-05-31 17:50:25 +08:00
试了下哔哩哔哩。。。。结果只下载了音频
|
4
dabaisuv OP @goodhellonice 我测试的时候,各大网站都行的,你看看是不是有下载被拦截了,我的谷歌浏览器在一次性弹两个下载时会自动拦截一个,这个需要你同意多个文件下载权限
|
5
linglin0924 2022-05-31 17:57:15 +08:00
刚试了油管,看完视频自动下载了视频和一个音频。感觉自动下载有点那啥。
可以的话让用户给选择是否下载 |
6
linglin0924 2022-05-31 17:58:28 +08:00
最近有一些不能下载的视频,我都是用这个插件,看他的运行方式,应该也是读流合并的
https://chrome.google.com/webstore/detail/video-downloader-cococut/gddbgllpilhpnjpkdbopahnpealaklle |
7
creanme 2022-05-31 17:58:41 +08:00
IDM 可以自动识别
|
8
HeyWeGo 2022-05-31 17:58:45 +08:00
试了下油管:
如果一个视频有 4 分钟,开头我看了 10s ,然后手动跳过一部分未缓存的,继续播 3 分之后的内容,是不是就没法完整缓存整个了,分两段下载? |
9
hbtech 2022-05-31 18:00:21 +08:00
|
10
libook 2022-05-31 18:02:37 +08:00
这个东西很厉害,基本能突破很多 HLS 加密方案了。
|
11
dabaisuv OP @HeyWeGo 也是一段,但是最终通过 ffmpeg 合成后,播放到你跳过的那段好像会空白还是跳过,这个不太记得了
|
12
goodhellonice 2022-05-31 18:07:34 +08:00
@dabaisuv 好的 我再看看 是不是我开着其他脚本或扩展的问题 谢谢
|
13
dabaisuv OP @linglin0924 这个可以选择,在源代码里面把 window.autoDownload 设置为 0 就行,然后想下载的话在控制台输入 window.downloadAll = 1 。我设置成自动下载,主要是因为有些视频网站是 iframe 里面播放的,这样在控制台输入 window.downloadAll = 1 的话,下载的会是空白的,因为视频的缓存是在 iframe 里面,两者的 window 指向不同 document 。以后可能会更新就算视频在 iframe 里面也能下载到的功能。现在的最佳解决办法就是自动下载,配合油猴的开关插件,在需要的时候再载入插件
|
14
dabaisuv OP @linglin0924
@hbtech 看了下说明,没安装,他这个可能是获取 m3u8 格式的 ts 文件后合并下载的,如果是这样的话,适用范围可能不是太广。你有用它试过下载 xilixili 视频吗,如果能下载的话,可能就是直接获取二进制流的,那跟我原理差不多 |
15
linglin0924 2022-05-31 18:37:21 +08:00
@dabaisuv 这个插件,下载 b 站的视频得用录制模式,也是得等加载完才算下载完
|
16
teasick 2022-05-31 18:39:15 +08:00
以为无下限视频
|
17
dabaisuv OP @linglin0924
感谢回复,那应该是一样的。我写脚本之前搜到有人推荐类似的,不过说的是下载 m3u8 。我这才写了这个脚本,不过好像白折腾了。 |
18
crab 2022-05-31 18:50:08 +08:00
91 上音频没问题,视频文件大小 OK ,时间不对。
|
19
libook 2022-05-31 18:51:00 +08:00
目前测试了主流的 HLS 加密,以及小鹅通那种比较强一些的加密也都是可以下载下来的。
不过小鹅通下载下来的音频有问题,声音非常低沉,不知道是不是开了 16 倍速的原因。 |
21
LiuJiang 2022-05-31 18:52:43 +08:00
哈哈哈,最近自己也写了个,给朋友用的
|
22
Buges 2022-05-31 18:54:28 +08:00 via Android
你想岔了,不是每个网站都使用同一种方式播放还没有检测的。
真正通用的方式是 patch chromium 的源码,直接截取播放的编码流,除了 DRM 和使用非浏览器自带播放器的网站外都能获取到。 当然具体操作最大的成本是构建 chromium 需要的大量资源。 |
23
dabaisuv OP @libook 感谢回复,我对音频编码不太了解,倍速讲道理不会影响声音。是合并后的问题还是下载下来就有的问题,如果是下载下来就有问题......这个是截取的视频流音频流,会不会是他的网页播放器是定制的自动提高音频,然后服务器存的就是降频的音频。亦或者是本地播放器的问题,这个我不太能回答。如果是合并后出的问题,可能是 ffmpeg 编码的问题?
|
24
dabaisuv OP @Buges 感谢回复,改源码这个复杂性就太高了。在写脚本前,我查了下,目前几乎所有前端视频都是 video.src=window.URL.createObjectURL(MediaSource),而放入 MediaSource 的 SourceBuffer 之前的视频和音频流都应该是加密的,以此来防止网络嗅探。而我只需要在网站的 js 代码自己解密视频和音频流并放入 SourceBuffer 的时候截取就行,免去了伤脑细胞的加密算法分析,更加符合了 Ulimited_Downloader 的名称。
另外,我目前查到的资料是,视频加密的话,最终基本都会到 SourceBuffer 这一步,而不用 SourceBuffer 的视频播放,一般可以使用手动使用 document.querySelector('video').src (如果网站使用了 iframe:document.querySelectorAll(iframe).forEach(v=>{console.log(v.contentDocument.querySelector('video').src)})直接获得视频直接链接,那这个脚本自然也没用处了。 |
25
israinbow 2022-05-31 19:15:45 +08:00
有 FF 的支持么, 楼上出现的插件都不支持 FF.
|
26
dabaisuv OP @dabaisuv 如果是防检测的话,可以修改 toString()方法返回 hook 之前的函数的字符串,后续可以考虑加上
|
28
dabaisuv OP @dabaisuv 这又涉及到矛与盾的问题了,网站也可以不管 hook 没 hook ,而直接替换关键函数为信任的对应函数。这我也可以 hook 住它需要替换函数所需要的函数。总的来说就跟内核一样,谁更底层,谁更先,谁赢。
|
30
dabaisuv OP @israinbow 没测试,不过我觉得应该支持,火狐能安装油猴插件把,能的话就应该能支持的,我这脚本没用浏览器特性,油猴的特性也没使用,甚至你可以直接用 fidder 插入代码。但不排除火狐有什么权限相关的问题。
|
31
Buges 2022-05-31 19:33:22 +08:00 via Android 2
@dabaisuv 不管怎么样这种方式终归是在 js 端和网站斗智斗勇,patch chromium 的方式论复杂到也不是多复杂,几年前某安全论坛就看到过相关的资料,媒体模块加几行代码打 log 就能把内容提取出来,具体写的很清楚,只是没有成品。对程序员来说实施起来不难,只是构建 chromium 的成本太高了。
|
32
tammy 2022-05-31 19:36:56 +08:00
我都是调用 you-get 下载的([Firefox 添加“鼠标中键点击下载按钮条用 you-get.exe 下载视频” 的功能 - Ryan 快快跑]( https://kkp.disk.st/firefox-adds-the-function-of-middle-click-the-download-button-bar-and-download-video-with-yougetexe.html)),对于支持的网站不用说,一流,默认最高画质,在配合你这个搞不支持的网站,那就更舒服了
|
33
johnnyNg 2022-05-31 19:37:23 +08:00
思路挺可以的
|
34
dabaisuv OP @Buges 再次感谢回复,之前没接触过 chromium 源码,看了你的回复后,我觉得可以抽时间来读一读,也可以提升一下自己对浏览器的理解。
|
36
Buges 2022-05-31 19:47:32 +08:00 via Android
@dabaisuv 其实 chromium 的源码并不难,基本上就纯 OO ,没啥高级特性和黑魔法,而且很规范、注释丰富。不过规模太庞大了,代码量太多。之前给某 chromium 下游项目提 pr 看过 chromium 源码,体验就是定位两小时 patch 5 分钟,还有就是编译吃的资源太多,你得有高速的国际宽带+流量+大量的 SSD 硬盘空间+大内存+多核 CPU 再加上大量时间才能尝试构建。
|
37
kkocdko 2022-05-31 19:58:02 +08:00 via Android
(题主做了我一直想做的事
我感觉 hook 是现在页面增强很好的一个思路,之前有见过 hook 定时器来加速跳过视频站广告。 前端的不透明度是越来越高了。 |
38
ijrou 2022-05-31 19:58:05 +08:00
|
40
libook 2022-05-31 19:59:46 +08:00 via Android
@dabaisuv 合并前有问题,可能是你说的那样。
小鹅通对 video 定制得挺变态的,但 drm 效果好,工信部在用。 |
41
darer 2022-05-31 20:18:00 +08:00
提个小建议 文件名可以改成 title_format
|
43
HFX3389 2022-05-31 20:30:04 +08:00
@Buges #22 知道了在哪改的话,弄个按量付费的云服务器,24G 内存的 80~100 左右一天(因为我没试过编译 chromium 需要多久所以就按一天算),而且浏览器这类应用编译完一次可以用很久的
|
45
Buges 2022-05-31 20:39:07 +08:00 via Android
@HFX3389 没试过这种方式,但我盲猜国内服务器第一步代码都拉不下来。而且修改了以后还是要调试的,增量编译+链接一次也要几分钟。
|
46
HFX3389 2022-05-31 20:46:33 +08:00
@Buges #45 那就弄香港、日本、韩国、新加坡的服务器呗,这样代码拉下来就容易多了;至于后面的修改调试就得看前期代码熟练度了,不能啥都没看就直接上服务器吧,这样太烧钱了,一天一百。应该是先在本地上看完大致有个思路、模板什么的,到时候一击必中或者只要经过很小的调试就可以用
|
47
siknet 2022-05-31 20:49:55 +08:00
@libook 正在下小鹅通。分享链接到傲游 PC 端,然后扫码或者短信登录,自带的资源管理器能嗅探到文件链接,下载就行了。如果播放不了就在点播放后切换线路就行了。
|
48
dabaisuv OP @ijrou 感谢回复,看了下它的 js 源码,定位到这一行是检测代码
//(t || 1 == i || n && "auto" !== n || r && -1 === r.indexOf("360") || o) && (s.remove(), s.setStorage(), s.destroy()) 是循环检测的。注释掉就行了。但是我不打算加入到脚本,这个太有针对性了,有法律风险; |
49
dabaisuv OP @darer 感谢建议,插件更新了,目前可以简单的防止 hook 检测,并且下载的文件名会是:网站标题+audio/video.mp4
|
50
lizhenda 2022-05-31 21:51:08 +08:00
思路不错哦
|
52
zhw2590582 2022-05-31 21:59:34 +08:00
和我之前写得一个 chrome 扩展差不多原理,用来转码获取 B 站直播间的 Flv 流,后面发现直播地址会因为网络波动而变化,获取到的流不能合并在一起,后面换了个思路,直接用 MediaRecorder ,随他地址怎么切换都能录制
https://chrome.google.com/webstore/detail/bilibili-%E5%BD%95%E6%92%AD%E5%A7%AC/nagmkdppcmenlcgelpgkjoknakghllml |
53
xx3122 2022-05-31 23:13:29 +08:00
马了,期待支持所有网站
|
54
dabaisuv OP @zhw2590582 感谢回复,MediaRecorder ,涨知识了,之前我还没查到这个函数
|
56
ufan0 2022-05-31 23:33:17 +08:00
很久之前捯饬过,没用到啥技术,只是扒 ie 浏览器的缓存,直接提取缓存文件拼接。
希望楼主工具越做越好,mark ~ |
59
byte10 2022-06-01 08:14:43 +08:00
这个样的插件是不是很多?我以前好像用到过这样的脚本,也是用谷歌的插件去下载视频。可以下载腾讯课堂的视频
|
60
hahahahahahahah 2022-06-01 09:38:38 +08:00 via iPhone
a 站下载音频有问题,没有倍速
|
61
heiyutian 2022-06-01 09:43:07 +08:00
建议可以只保存观看或缓冲的部分,有很多视频真的只需要一部分就够了,有时候并不需要整个视频,如果视频很长就比较费流量和时间了。
|
62
Rrrrrr 2022-06-01 10:10:11 +08:00
b 站确实不行,只有音频。我之前都是自己去分析代码,拿到真实地址,不过比较费时间。
|
63
zhaozhao 2022-06-01 10:37:42 +08:00 1
|
64
tianyou666shen 2022-06-01 10:55:50 +08:00
用这个下了个视频 还不错 就是免费版两小时只能下一次文件
Video DownloadHelper (chrome) |
65
root01 2022-06-01 10:58:48 +08:00
OP 很给力,但是视频和音频下载下来是分开的,美中不足
非常感谢 OP |
66
root01 2022-06-01 11:07:17 +08:00
抱歉,没看完整,原来是分开的
|
67
OMGZui 2022-06-01 11:15:41 +08:00
感谢,很牛逼
|
68
FaiChou 2022-06-01 11:50:37 +08:00
这个原理不错, 前几天刚好遇到这个问题 : [Instagram 网页版视频是如何限制在 devtools 中找到视频链接进行直接下载的]( https://v2ex.com/t/852210#reply6)
|
69
shaojz2005 2022-06-01 12:16:38 +08:00
这些是针对什么视频网站的。我试了这几个,好像 B 站都下不回来
|
70
dabaisuv OP @shaojz2005 测试的时候国内外的都行的。
|
74
hxz0803 2022-06-01 20:46:48 +08:00
试了一下,DMM 那种视频也可以下载
|
75
xifangczy 2022-06-02 03:13:52 +08:00
之前我也有类似的想法,甚至经历都跟你差不多一步步试验过来,想装到 chrome 扩展里...因为扩展 manifest 升级到了 V3 然后又因为 V3 的脚本注入 API scripting 又巨难用,它甚至不能在 document-start 运行(刚刚去看了 102 版终于加上了)... 我就搁置了。。还是油猴脚本好使啊
|
76
shaojz2005 2022-06-02 09:26:34 +08:00
@dabaisuv 我装了你这个插件,然后打开哔哩哔哩视频时,在视频页没有右上角的捕获片段的提示,但是哔哩哔哩首页或者搜索页(即进入详情页的上一页)会有提示捕获,但最后都没下载到什么完整的视频,都是一些小片段。不知道我是不是操作流程有什么问题。。。
|
77
shaojz2005 2022-06-02 09:38:24 +08:00
咦,再试了下又可以了
|
78
dabaisuv OP @shaojz2005 这代码没有加右上角的捕获片段提示啊,捕获到了片段会在控制台打印出来
|
79
Rrrrrr 2022-06-02 10:56:11 +08:00
应该要加个按钮,点开始才下,我昨晚看 youtube 怎么突然就给我下了一个视频
|
81
shaojz2005 2022-06-02 14:32:32 +08:00
@dabaisuv 我用了这个帖子里另外一个
|
82
dabaisuv OP |
83
MiketsuSmasher 2022-06-13 10:45:54 +08:00
楼主的这个脚本无法下载学习通课程视频,即便在脚本文件里设置 window.autoDownload = 1 也没有用,在控制台设置 window.downloadAll = 1 下载到的是空白文件
|
84
dabaisuv OP @MiketsuSmasher 它视频就没加密,直链就能下载。。。。,记得把 refer 标头改成视频页面网址就行的
|
86
dsyrock 2023-02-04 09:57:43 +08:00
你好,感谢做了这个插件。有个问题是,有些视频有不同的清晰度选择。我则腾讯上测试,选择了 720P 的,然后刷新一次,保证从头播放的时候就是这个清晰度,但是脚本下载下来也是 480P 的,请问这个清晰度可以选择吗?
|
87
Memorainer 2023-02-05 21:19:12 +08:00
@libook 同样遇到了这个问题。下载下来的音频本来就是低沉的带有很重的机械音,根本听不清楚。可以结合上面提到的插件 cococut 配合爬取。
|
88
Memorainer 2023-02-05 21:22:02 +08:00
@xff236 配合 CoCocut 插件。CoCocut 本来也可以爬小鹅通,但文件体积不知道为什么比脚本爬取的小很多。如果担心文件质量有问题的话,可以用 ffmpeg 把插件下下来的视频里的音频流提出来再混到脚本下载的视频流里去。
|
89
Memorainer 2023-02-11 10:32:36 +08:00
关于合并两条流,OP 的命令似乎有不可预知的问题。chatGPT 给出了方案,流直接复制,无需再编码:ffmpeg -i videoA.mp4 -i videoB.mp4 -map 0:v -map 1:a -c:v copy -c:a copy videoC.mp4
-i videoA.mp4 和 -i videoB.mp4 表示读取视频 A 和视频 B 的源文件。 -map 0:v 和 -map 1:a 分别表示选择视频 A 的画面和视频 B 的声音。 -c:v copy 和 -c:a copy 表示复制视频 A 的画面和视频 B 的声音。 最后,videoC.mp4 表示合并后的新视频的输出文件。 |
91
BetterSci 2023-02-26 18:06:35 +08:00
小鹅通、知网视频都无法下载,求解决方案
|
92
xxxxLyq 2023-06-28 11:25:04 +08:00
@Memorainer 这个命令解决了我的问题。我遇到的情况是:下载下来的音频视频两个文件,用 quicktimeplayer 打开看长度都是原视频的两倍,前面一半正常,后面一半是空的。用你的命令处理出来一切都正常。
|
93
recall704 2023-08-13 13:53:07 +08:00
ffmpeg 合并的小工具 https://github.com/rxaa/MediaMux
|
94
fang5566 5 天前
这个脚本咋在 greasyfork 上面删除了呢?
|