python多线程下载网络视频ts,并合并(踩坑记录)

python多线程下载网络视频ts,并合并(踩坑记录)

由于是加密ts,使用的AES加密,首先需安装Crypto模块

出现这个 Microsoft Visual C++ 14.0 is required. Get it with “Microsoft Visual C++ Build Tools 错误
解决方法

//使用 conda install -c conda-forge 包名称 来安装相关包
conda install libpython m2w64-toolchain -c python_3.8

下载这个包可以解决C++依赖的问题,而不用向网上绝大数博客你抄我我抄你一样要下载个visual studio,那么大的空间真的是不值得。

//用到的解密代码
from Crypto.Cipher import AES
# 创建AES解密器
def AESDecrypt(cipher_text, key):
    aes = AES.new(key, AES.MODE_CBC)
    cipher_text = aes.decrypt(cipher_text)
    return cipher_text

解析m3u8文件内容获取秘钥以及ts的URI列表

//解析m3u8文件内容
def get_real_url(baseurl,url):
    # 解析M3U8文件内容
    r = requests.get(url, headers=headers)
    while r.status_code != 200:
        r = requests.get(url, headers=headers)
    key_uri = None
    datalist = []
    for line in r.text.splitlines():
        if line.startswith("#EXT-X-KEY"):
            print(line)
            if(len(line.split(","))>1):
                # 获取秘钥URI
                key_uri = line.split(",")[1].split("=")[1].strip('"')
            continue
        if not line.startswith("#"):
            if "http" not in line:
                # 将ts链接存储到字典中
                datalist.append(line)

    if not key_uri:
        key=""
    else:
        # 通过秘钥URL获取秘钥
        keydata = requests.get(baseurl+key_uri, headers=headers)
        while keydata.status_code != 200:
            keydata = requests.get(baseurl+key_uri, headers=headers)
        key=keydata.content
    return key,datalist

下载文件

# 下载ts文件
def DownloadVideo(savePath,videoUrl,key):
    req = requests.get(videoUrl, headers=headers)
    try:
        while req.status_code != 200:
            req = requests.get(videoUrl, headers=headers)
        data=req.content
        if not key=="":
            try:
                data = AESDecrypt(data, key=key)
            except ValueError:
                pass
        videoName = videoUrl[videoUrl.rfind("/") + 1:]
        with open(savePath + videoName, "wb") as f:
            f.write(data)
    finally:
        connectlock.release()

处理下载好的文件,这里使用了subprocess.Popen代替os.system,同时使用ffmpeg进行ts文件合并,使得视频不会特别掉帧,同时不会向控制台输出太多的东西

ffmpeg安装
参考这个链接: link
如果使用的是conda 虚拟环境则需要进行环境变量配置,否则会报错----不是内部或外部命令,也不是可运行的程序”
参考这个链接: link

# 合并ts文件,并删除ts文件
def merge_file(path,i):
    # 匹配非法字符
    illegal_chars = r'[\\/:*?"<>|]'
    # 将非法字符替换为空
    new_filename = re.sub(illegal_chars, '', i)
    new_filename = re.sub(' ', '', new_filename)
    name = new_filename+".mp4"
    # 如果文件名存在则增加时间戳后缀
    if os.path.exists("E:\学习资料MP4/"+name):
        name=new_filename+str(int(time.time()))+".mp4"

    for filename in os.listdir(path):
        if filename.find('ts') != -1:
            with open(path + "file_list.txt", 'a', encoding='utf-8') as f:
                f.write("file '"+filename+"'\n")

    os.chdir(path)
    cmd="ffmpeg -f concat -i file_list.txt -c copy "+name
    p=subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # p.wait()
    p.communicate()
    shutil.move('E:\学习资料/%s' % name, 'E:\学习资料MP4/')
    os.system('del /Q *.ts')
    os.system('del /Q *.txt')

多线程下载

# 多线程
from threading import *

nMaxThread = 8
connectlock = BoundedSemaphore(nMaxThread)

def chulishuju(baseurl,url, path, title):
    start1 = time.time()
    key,VideoList = get_real_url(baseurl,url)
    # for k in VideoList:
    i=0
    print(VideoList)
    for k in VideoList:
        k=baseurl+k
        # print(k)
        savePath= path +"%s."%str(i).rjust(5,'0')
        i+=1
        connectlock.acquire()
        t = Thread(target=DownloadVideo, args=(savePath, k,key))
        t.start()
    time.sleep(10)
    print("学习资料%s下载完成耗时%.5f秒" % (title, float(time.time() - start1)))
    merge_file(path,title);

全部程序放到csdn下载,需要的友友可以自行下载

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悦耳心意

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值