python下载m3u8视频_Python 下载m3u8格式的视频

日常中我们在一些网站上看到有意思的电影或者视频,想保存下来,点击下载却发现这是一个以 .m3u8结尾的视频链接。就算我们用手机下载下来,却发现下载后得到的不是一个完整的视频文件,而是一大堆ts结尾的视频文件,整个视频被切割为一个个的几秒的视频文件。这里就使用python实现将视频链接下载为一个完整的mp4视频文件。

1.了解 m3u8 视频链接

m3u8文件其实是 HTTP Live Streaming(缩写为 HLS)协议的部分内容,而 HLS 是一个由苹果公司提出的基于 HTTP 的 流媒体 网络传输协议。

简而言之,HLS 是新一代流媒体传输协议,其基本实现原理为将一个大的媒体文件进行分片,将该分片文件资源路径记录于 m3u8 文件(即 playlist)内,其中附带一些额外描述用于提供给客户端。客户端依据该 m3u8 文件即可获取对应的媒体资源,进行播放。

因此,客户端获取 HLS 流文件,主要就是对 m3u8 文件进行解析操作。

2.解析 m3u8 文件

我们将获取的视频链接在浏览器上打开,会得到一个以 .m3u8 为结尾的文件,使用记事本打开

#EXTM3U

#EXT-X-TARGETDURATION:12

#EXT-X-MEDIA-SEQUENCE:0

#EXTINF:2,

http://play1.cp21.ott.cibntv.net/play.videocache.lecloud.com/ver_00_22_0_0_1_81028_0_0.ts

#EXTINF:3,

http://play1.cp21.ott.cibntv.net/play.videocache.lecloud.com/ver_00_22_1_1_1_113176_81028_0.ts

#EXTINF:5,

http://play1.cp21.ott.cibntv.net/play.videocache.lecloud.com/ver_00_22_2_2_1_248724_194204_0.ts

......

#EXT-X-ENDLIST

第一行 “#EXTM3U” 表明这个一个 m3u8 格式的视频文件,“#EXTINF”后面的一行链接便是每一个视频流的文件地址。如果将链接输入到浏览器中访问,你将得到一个以 .ts 结尾的几秒钟视频文件。这个文件中所有的链接全部请求得到的就是一个完整的视频。

有时候得到的 m3u8 文件不一样,会有一行 “#EXT-X-KEY” ,说明这个视频是经过加密的,需要我们去解密才能得到视频,否则得到的视频文件打开就会报错。

#EXTM3U

#EXT-X-VERSION:3

#EXT-X-TARGETDURATION:2

#EXT-X-MEDIA-SEQUENCE:0

#EXT-X-KEY:METHOD=AES-128,URI="key.key"

#EXTINF:1.668333,

ir7QcW6705000.ts

#EXTINF:0.834167,

ir7QcW6705001.ts

#EXTINF:0.834167,

ir7QcW6705002.ts

这个文件中多了一行 “#EXT-X-KEY” 这个是向客户端表明这个一个加密的视频,加密方式为 AES-128 ,而加密文件是 key.key ,由于这个加密文件和视频链接地址都无前缀,所以他们的链接前缀应该是得到这个m3u8文件的链接,将末尾修改为key文件和视频流名称就可得到完整的链接。

有时候我们得到的 m3u8 文件是这样的

#EXTM3U

#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=732000,RESOLUTION=720x480

hls/index.m3u8

我们将第一个链接后改为 http://www.play1.com/hls/index.m3u8 再次访问才能得到像上面格式的文件。这个只是将文件设置为二次访问获取真实地址。

整个文件解析基本完成,现在进行脚本编写,实现下载。

3.Python实现下载流程

这里实现加密视频的下载

首先获取 m3u8 文件并解析

import requests

import re

from Crypto.Cipher import AES

def m3u8(url):

header = {

'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'

}

# requests得到m3u8文件内容

content = requests.get(url,headers=header).text

if "#EXTM3U" not in content:

print("这不是一个m3u8的视频链接!")

return False

if "EXT-X-KEY" not in content:

print("没有加密")

return False

# 使用re正则得到key和视频地址

jiami=re.findall('#EXT-X-KEY:(.*)\n',content)

key=re.findall('URI="(.*)"',jiami[0])

#得到每一个ts视频链接

tslist=re.findall('EXTINF:(.*),\n(.*)\n#',content)

newlist=[]

for i in tslist:

newlist.append(i[1])

# 先获取URL/后的后缀,再替换为空

urlkey=url.split('/')[-1]

url2 = url.replace(urlkey, '') #这里为得到url地址的前面部分,为后面key的链接和视频链接拼接使用

#得到key的链接并请求得到加密的key值

keyurl=url2+key[0]

keycontent= requests.get(keyurl,headers=header).text

#得到每一个完整视频的链接地址

tslisturl=[]

for i in newlist:

tsurl=url2+i

tslisturl.append(tsurl)

#得到解密方法,这里要导入第三方库 pycrypto

#这里有一个问题,安装pycrypto成功后,导入from Crypto.Cipher import AES报错

#找到使用python环境的文件夹,在Lib文件夹下有一个 site-packages 文件夹,里面是我们环境安装的包。

#找到一个crypto文件夹,打开可以看到 Cipher文件夹,此时我们将 crypto文件夹改为 Crypto 即可使用了

cryptor = AES.new(keycontent, AES.MODE_CBC, keycontent)

#for循环获取视频文件

for i in tslisturl:

res = requests.get(i, header)

#使用解密方法解密得到的视频文件

cont=cryptor.decrypt(res.content)

#以追加的形式保存为mp4文件

with open('xx.mp4', 'ab+') as f:

f.write(cont)

return True

if __name__ == '__main__':

url = "https://xxxxxxx/hls/index.m3u8"

pd = m3u8(url)

if pd:

print('视频下载完成!')

至此整个视频文件下载脚本结束。启动脚本等待视频下载完成,即可得到一个完整的 mp4 格式视频文件。

后记

整个脚本实现过程比较粗糙。只是完成视频的分析下载。小伙伴们可以根据自己自行修改优化。这里也是参考不少大佬的博客技术文档,站在大佬的肩上学习实现了这个脚本。感谢大佬们的技术博客分享,向大佬们致敬!

你可能感兴趣的:(python下载m3u8视频)