MENU

使用python自动下载m3u8播放列表视频(采集m3u8文件并下载合并成MP4)

November 20, 2020 • 数据采集与数据分析(python)

先简单介绍下操作对象:

  • m3u8
  1. 文件实质是一个播放列表(playlist),其可能是一个媒体播放列表(Media Playlist),或者是一个主列表(Master Playlist)。但无论是哪种播放列表,其内部文字使用的都是 utf-8 编码。其格式如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:6
#EXTINF:5.080000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out0.ts
#EXTINF:5.000000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out1.ts
#EXTINF:5.000000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out2.ts
#EXTINF:5.000000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out3.ts
#EXTINF:5.000000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out4.ts
#EXTINF:5.000000,
https://z.weilekangnet.com:59666/data5/B1AF27ADA87782E7/6AE9D283C6B3F6B3/ts1/out5.ts
#EXTINF:5.000000,
#EXT-X-ENDLIST

上述格式中每个ts文件是一个片段,我们需要下载这些片段后再合并即可得到完整视频。对于普通播放,客户端只需要按顺序下载依次播放。但是对于直播的需要定时请求看是否有新的片段数据。

整体思路:首先是要从视频网站中找到m3u8文件,然后请求m3u8文件,得到ts文件地址列表,然后继续请求每个文件地址并得到ts文件数据,最后合并成MP4。

思路有了,下面开始实践:(直接上代码,具体看注释)

   import requests
    import re
    from urllib.parse import urlparse
    import os


    url = input('输入m3u8url')  #输入m3u8文件地址
    dir = urlparse(url)[4]      #解析m3u8地址,得到每个视频的‘变量’,设为文件夹名。根据自己的地址格式设置。不明白请参看urlparse库
    os.chdir('video')    #改变当前的工作目录,我这里是进入项目的video文件夹下。所有视频将在这个目录下创建自己的文件夹
    os.mkdir(dir)        #在video文件夹下创建目录,目录名为m3u8地址‘变量’
    req = requests.get(url,verify=False)   #请求m3u8地址
    print(req.text)      #输出m3u8文件内容
    text =req.text       #将m3u8文件内容赋给text变量
    result = re.findall('https.*?out\d*.ts',text,re.S)   #使用正则表达式找出所有ts文件的地址,返回地址列队
    print(result)        #输出ts文件地址列队
    i= 0                 #初始化ts文件名序号。*为方便后续合成,最好是将所有ts文件的按播放顺序命名。*
    for item in result:  #遍历列队
        url_i = item
        tsname = "{num:0>4}".format(num=i)     #文件名序号(i)转四位字数字子符串tsname,为每个ts文件名
        response = requests.get(url_i,verify=False) #请求ts文件
        print('正在下载当前页面为',item)         #向控制台输出当前瞎子啊ts地址
        with open(dir+ '\\'+tsname +'.ts','wb') as file: #将ts数据写入文件
            file.write(response.content)
        i = i+1                                           


    print('下载完毕!!!,准备合并')
    print('开始合并成MP4')
    for file in os.listdir(dir):                             #合并下载完的ts文件
        with open(dir+'\\'+file,'rb') as file_read:
            with open(dir + '.mp4','ab') as file_write:
                print('正在合并', file, '加入中。。。')
                file_write.write(file_read.read())

    print('合并完毕!!!')
    print('正在删除原始文件。。。')
    for file in os.listdir(dir):   #合并成功后,删除所有ts文件
        os.remove(dir + '\\' + file)                 
    os.rmdir(dir)                  #删除下载ts时创建的目录
    print('删除源文件完毕!~')

下面我们来看下运行结果:
ts下载与合并(m3u8).png
ts下载与合并(m3u8)文件目录.png

多线程版:使用 python 自动下载 m3u8 播放列表 ts 视频并合并(多线程版)

后续会更新异步的方法,来提升性能。还会完善异常机制。

*参考: m3u8 文件格式详解

Last Modified: November 24, 2020