加密后的ts文件不能直接合并或播放,需要使用key对每个ts文件进行解密。

分为两种情况:
(1).如果ts文件已经全部下载好,则可以直接在本地通过ffmpeg快速解密合并。
(2).如果ts文件没有下载好,则可以通过vlc直接下载整个视频,或者通过ffmpeg下载并转换。

无论是哪种情况,都要去视频源地址下载m3u8文件。如果可以下载key(有些网站加密方式比较严谨,不那么容易获取到key),把key文件也下载好。

下载m3u8文件的方式是去源地址网站,按F12找到m3u8文件,或者从右键–>网页源代码中找到地址。两种方式都试一试。

例如,从浏览器的F12中找:

这里能找到两个m3u8和一个key文件,都下载好。记事本打开两个m3u8,其中有一个包含了ts文件列表,这个m3u8文件是我们所需要的。例如我这里的是HdNz1kaz.m3u8文件,以下是一小部分内容。

1
2
3
4
5
6
7
8
9
10
11
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="/20180125/NfJJpxIH/1482kb/hls/key.key"
#EXTINF:12.5,
/20180125/NfJJpxIH/1482kb/hls/GBDYO3576000.ts
#EXTINF:12.5,
/20180125/NfJJpxIH/1482kb/hls/GBDYO3576001.ts
#EXTINF:12.5,
/20180125/NfJJpxIH/1482kb/hls/GBDYO3576002.ts

1.情形一:ts文件已经下载好

假如我的ts文件全部下载好,放在e:\20180125\目录下。

同时假设key文件已经下载好,也放在e:\20180125\目录下。

修改m3u8文件中key的uri路径和ts文件的路径为本地路径。下面是HdNz1kaz.m3u8文件修改后的一小部分内容

1
2
3
4
5
6
7
8
9
10
11
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="e:/20180125/key.key"
#EXTINF:12.5,
e:/20180125/GBDYO3576000.ts
#EXTINF:12.5,
e:/20180125/GBDYO3576001.ts
#EXTINF:12.5,
e:/20180125/GBDYO3576002.ts

然后用ffmpeg进行合并。

1
ffmpeg -allowed-extensions ALL -i HdNz1kaz.m3u8 -c copy new.mp4

我一般会把ts文件下载好,因为用下载工具(比如迅雷)下载比ffmpeg或者vlc下载速度要快的多,因为这两个工具都是串行下载的。

2.情形二:ts文件没有下载

同样,下载好m3u8文件(key可下载可不下载,因为可以直接在m3u8文件中指定key的网络uri路径)。

修改m3u8文件中key和ts的uri路径。下面是HdNz1kaz.m3u8文件修改后的一小部分内容。

1
2
3
4
5
6
7
8
9
10
11
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:13
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-KEY:METHOD=AES-128,URI="http://www.example.com/20180125/key.key"
#EXTINF:12.5,
http://www.example.com/20180125/GBDYO3576000.ts
#EXTINF:12.5,
http://www.example.com/20180125/GBDYO3576001.ts
#EXTINF:12.5,
http://www.example.com/20180125/GBDYO3576002.ts

然后,使用ffmpeg下载并合并。

1
ffmpeg -i HdNz1kaz.m3u8 -c copy new.mp4

3.使用vlc下载并保存ts文件

播放列表的下方有播放进度条,它表示下载的进度,不要去动,也不要去点击播放、暂停、停止等,放着别管就是了,直到播放进度条完成了,就表示文件合并完成。去文件保存位置的地方看看就知道了。

openssl解密加密的ts文件

如果m3u8文件头部,有类似于这样的内容:

1
2
3
4
5
#EXTM3U #EXT-X-VERSION:3
#EXT-X-TARGETDURATION:12
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="/inc/enc.key",IV=0x067209a194b6ab5482af9c937c264eaa

其中IV值可能不存在。

这说明ts文件是被AES-128加密的,需要解密才能正确播放。

解密可以使用openssl解密。

  • 如果不存在IV值,这IV值为每个ts文件的序列号对应的hex值。例如AES-128加密算法时其IV长度为16,那么序列号为1的ts文件对应的IV值为0x0000000000000001
  • 解密的key被保存在/inc/enc.key文件中,它可能是一个二进制文件,可能是一个明文密码(也有可能是被base64或其它方式编码过的)。

如果key是二进制文件,则将其转换为hex即可:

1
2
3
4
5
$ cat enc.key | hexdump -C
00000000 55 a7 6c ad 8e f1 88 34 94 ed 68 cf e3 ac 3a 44 |U.l....4..h...:D|
00000010

$ cat enc.key | hexdump -C | head -1 | sed "s/00000000//;s/|.*//;s/ //g"

总之,现在得到了key和iv值,那么就可以尝试使用Openssl来解密ts文件:

1
2
3
key=55a76cad8ef1883494ed68cfe3ac3a44
iv=067209a194b6ab5482af9c937c264eaa
openssl aes-128-cbc -d -in 720_000.ts -out out_0.ts -nosalt -K $key -iv $iv

所有ts文件已经解密,那么可以将所有的解密后的ts列表单独写入文件ts.list

1
2
3
4
# 每行一个,加上前缀file
file out_0.ts
file out_1.ts
...

然后通过ffmpeg合并:

1
ffmpeg -y -f concat -i ts.list -bsf:a aac_adtstoasc -c copy output.mp4

ffmpeg从m3u8文件转mp4

1
2
3
4
5
6
7
8
# 如果已经下载好m3u8,且m3u8文件里的路径都是绝对路径而不是相对路径
# 例如:https://cnd.abc.com/video/70a/video000.ts
# 或者:E:/20180125/GBDYO3576000.ts
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -bsf:a aac_adtstoasc -i "./us.m3u8" -c copy filename.mp4

# 如果是相对路径,可以将m3u8文件修改,加上路径前缀,或者直接传递m3u8的URL
# 例如:/20180125/NfJJpxIH/1482kb/hls/GBDYO3576000.ts
ffmpeg -protocol_whitelist file,http,https,tcp,tls,crypto -bsf:a aac_adtstoasc -i "https://abc.def.com/us.m3u8" -c copy filename.mp4

ffmpeg报错

错误:

Malformed AAC bitstream detected: use the audio bitstream filter ‘aac_adtstoasc’ to fix it (‘-bsf:a aac_adtstoasc’ option with ffmpeg)

需要在合并视频的时候,加上-bsf:a aac_adtstoasc

1
ffmpeg -i index.m3u8 -c:a copy -bsf:a aac_adtstoasc new.mp4

错误:

Codec for stream 0 does not use global headers but container format requires global headers
Codec for stream 1 does not use global headers but container format requires global headers

需要加上global header

1
ffmpeg -i index.m3u8 -c:a copy -flags +global_header new.mp4