数据结构+算法=程序
程序+设计模式=软件

0%

如何从B站下载大电影

首先你要确保视频是能播的,能播的都可以下载,不过得采用一些技术手段,所以有些会员才能看的电影,你得先充个会员。

方法一:手机缓存

  1. 直接在手机APP上缓存要看的电影,以安卓手机为例,缓存的视频在Android -> data -> tv.danmaku.bili -> download目录下。
  2. 缓存完毕后,你会在这个目录下找到audio.m4svideo.m4s这2个文件,分别代表音频文件和视频文件,将这2个文件导入到电脑。
  3. audio.m4s的后缀改为mp3,将video.m4s的后缀改为mp4,然后启动格式工厂这个软件,选择混流模式,将音频和视频文件合并成一个完整的mp4。

不过对于有些资源来说,即使是会员也不能缓存,有只能在线观看的限制,这个时候可参考方法二。

方法二:网络抓包

用Chrome浏览器打开某个电影的播放界面,用f12抓包会找到很多m4s格式的数据包,这些就是视频流和音频流,通过分析可以发现30080.m4s代表着视频流,30280.m4s是音频流,怎么知道的,通过实验一些视频,判断流大小得出的结果。

找到文件流的大小

随便打开一个30080.m4s请求,可以找到这个视频的最终大小,音频文件30280.m4s也类似。

模拟请求

打开为所欲为的fiddle软件,同样抓包,可以拿到很多30080.m4s的请求,接下来,使用fiddle的replay功能,将拆分的字节数改为0到文件流的最大值,然后模拟提交。

由于fiddle能缓存的文件大小最多只有2G,而一部1080P的电影至少都超过2G,所以没办法,只能将视频拆分为2部分,从0到1000000000,然后从1000000001到视频末尾,即按1G大小来划分。

同样的方式下载音频文件,音频文件大概在200MB左右,就不用拆分了,直接改为完整大小,然后提交。
用fiddle的save功能将文件流保存下来。

合并视频文件

2个视频文件就是一堆二进制数据流,只要将其按顺序存储成一个文件就可以了,提供一段合并二进制文件的代码:
参数inputFiles是多个输入文件的路径,outputFile是输出文件路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static void MergeFiles(string[] inputFiles, string outputFile)
{
FileStream outStream = new FileStream(outputFile, FileMode.Create);
BinaryWriter bw = new BinaryWriter(outStream);
long total = 0L;
long current = 0L;
foreach (var path in inputFiles)
{
total += new FileInfo(path).Length;
}
foreach (var path in inputFiles)
{
using (var fs = new FileStream(path, FileMode.Open))
{
using (var br = new BinaryReader(fs))
{
while (true)
{
var buffer = br.ReadBytes(8192);
if (buffer.Length > 0)
{
bw.Write(buffer);
current += buffer.Length;
Console.Write("Process: {0}/{1}\r", current, total);
}
else
break;
}
}
}
}
bw.Flush();
bw.Close();
Console.WriteLine();
}

生成

这个时候你已经拿到视频文件和音频文件了,还是格式工厂这个软件,用混流模式合并即可。
整个过程中,最慢的环节就是这个步骤了,下载的过程是非常快的,基本上可以占满全部的带宽,而合并音频视频却非常慢,如果你用其他软件合并也是可以的,欢迎推荐。