测试环境:python 3.7
部分m3u8文件样本:
#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-TARGETDURATION:60
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-START-TIME:1080
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:15+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=0&end=185555&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:16+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=185556&end=372051&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:17+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=372052&end=557795&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:18+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=557796&end=747299&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:19+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=747300&end=937743&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:20+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=937744&end=1124803&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:21+08:00
#EXTINF:1,
612048020_1773822331_1.ts?start=1124804&end=1308667&type=mpegts&resolution=1280x720&sign=c5bf5843178951ada765c8e5d62865e2&t=6089b22d&us=12975f1b-50fc-4a55-b825-f4a429987355
#EXT-X-PROGRAM-DATE-TIME:2021-04-27T14:01:22+08:00
#EXTINF:1,
想要下载m3u8视频,第一件事就是找到m3u8的文件地址。可以浏览器F12抓包找,然后下载到本地,用下面的脚本来解析m3u8下载分流。
以下脚本包含有:m3u8分流下载、ts视频合并。
# _*_encoding:UTF-8_*_
import urllib.request
import urllib.parse
import re
import time
import sys
import os
#根据m3u8文件下载ts子文件
#strM3U8: m3u8文件,该文件中存放了分流信息。
#urlHead: 因为分流信息是没有前面的地址的,所以需要提供url的前半部分。可以通过浏览器F12抓包找到。
# 浏览器在播放时会下载分流,可以抓到很多的包,把链接复制下来对比一下提取前半部分。
#strSaveDir: 下载保存的目录,会自动创建。
def downloadM3U8(strM3U8, urlHead, strSaveDir):
print("开始下载:" + strM3U8)
if not os.path.exists(strSaveDir):
os.mkdir(strSaveDir);
f = open(strM3U8, 'r', encoding='utf-8')
if f==None:
print('open failed:'+strM3U8)
return
strContext = f.read()
nIndex = 0
listFile = re.findall(r'.*start=.*', strContext)
for file in listFile:
#if(nIndex > 154):
# break
print("[%08d] %s" % (nIndex, file))
strUrl = urlHead + file
strPath = "%s\\%08d.ts" % (strSaveDir, nIndex)
try:
#这里在下载时可能会出现超时问题,所以加入异常重试机制,这也是一些下载器没有的功能
#下载器通常会傻傻的等到死。这也是这个脚本诞生的原因[狗头]。
urllib.request.urlretrieve(strUrl, strPath)
except BaseException:
print("文件下载失败,10秒后重试:" + strPath)
time.sleep(10)
continue
nIndex += 1
f.close()
print("下载完毕")
#合并ts类型文件
#strTsDir: 下载好的ts分流目录
#nRecursion: 递归计数,用来命名合并文件的,默认0.
#bDelSrc: 合并完了要不要删除源文件。建议调用时不删,防止合并出错。合并没问题了手动删。
# 这个参数主要是用来删除递归临时文件的。
def MergeTsFile(strTsDir, nRecursion, bDelSrc):
nMergeNum = 0 #合并次数
strTotalPath = ""
print("合并ts文件,递归次数:%d" % (nRecursion))
for nIndex in range(99999):
if nRecursion == 0:
strTsPath = "%s\\%08d.ts" % (strTsDir, nIndex)
else:
strTsPath = "%s\\%08d_%08d.ts" % (strTsDir, nRecursion-1, nIndex)
if not os.path.exists(strTsPath):
break
if nIndex % 10 == 0:
strTotalPath = "%s\\%08d_%08d.ts" % (strTsDir, nRecursion, nMergeNum)
if os.path.exists(strTotalPath):
os.remove(strTotalPath)
fTmp = open(strTotalPath, "w")
fTmp.close()
nMergeNum += 1
sysCmd = 'copy /b "%s"+"%s" "%s">>log.txt' % (strTotalPath, strTsPath, strTotalPath)
print(sysCmd)
os.system(sysCmd)
if bDelSrc:
os.remove(strTsPath)
if nMergeNum <= 1:
return
nRecursion += 1
MergeTsFile(strTsDir, nRecursion, True)
def main():
print("开始:")
strSaveDir = "X:\\Desktop\\tempVideo"
strUrl = "https://www.xxxxxx.com/d7beb5c4vodcq13013243"
strSaveDir = "X:\\Desktop\\tempVideo\\"
downloadM3U8("X:\\Desktop\\playlist_eof.m3u8", strUrl, strSaveDir)
#合并ts视频流
nRecursion = 0 #递归次数,如果存在上万的分流,是分批次每10个1组进行递归合并的。
MergeTsFile("X:\\Desktop\\tempVideo", nRecursion, False)
print('退出')
#下载完成后关机,如果视频太大可以设置自动关机
#os.system("shutdown -s -t 60")
if __name__ == "__main__":
main()
最终合并完的格式是ts格式的,也可以播放,如果要转mp4可以下载格式工厂。这个工具挺好用的。
上面的脚本仅供测试使用,如果实际使用,需要根据自己的需求进行手动修改。上面的脚本不支持m3u8加密流的下载。如果遇到加密,需要使用AES对其进行解密。并在m3u8文件中下载对应的加密key文件。