zoukankan      html  css  js  c++  java
  • Python3 根据m3u8下载视频,批量下载ts文件并且合并

    Python3 根据m3u8下载视频,批量下载ts文件并且合并

    m3u8是苹果公司推出一种视频播放标准,是一种文件检索格式,将视频切割成一小段一小段的ts格式的视频文件,然后存在服务器中(现在为了减少I/o访问次数,一般存在服务器的内存中),通过m3u8解析出来路径,然后去请求,是现在比较流行的一种加载方式,诸如腾讯视频之类大多都是切割成ts流进行加载。

    示例代码:

    import os, shutil
    import urllib.request, urllib.error, requests
    
    # 打开并读取网页内容
    def getUrlData(url):
        try:
            urlData = urllib.request.urlopen(url, timeout=20)  # .read().decode('utf-8', 'ignore')
            return urlData
        except Exception as err:
            print(f'err getUrlData({url})
    ', err)
            return -1
    
    # 下载文件-urllib.request
    def getDown_urllib(url, file_path):
        try:
            urllib.request.urlretrieve(url, filename=file_path)
            return True
        except urllib.error.URLError as e:
            # hasttr(e, 'code'),判断e 是否有.code属性,因为不确定是不是HTTPError错误,URLError包含HTTPError,但是HTTPError以外的错误是不返回错误码(状态码)的
            if hasattr(e, 'code'):
                print(e.code)  # 打印服务器返回的错误码(状态码),如403,404,501之类的
            elif hasattr(e, 'reason'):
                print(e.reason)  # 打印错误原因
    
    
    def getVideo_urllib(url_m3u8, path, videoName):
        print('begin run ~~
    ')
         # urlData = getUrlData(url_m3u8).readlines()
        urlData = getUrlData(url_m3u8)
        num = 0
        tempName_video = os.path.join(path, f'{videoName}.ts')  # f'{}' 相当于'{}'.format() 或 '%s'%videoName
        # print(urlData)
        for line in urlData:
            # 解码,由于是直接使用了所抓取的链接内容,所以需要按行解码,如果提前解码则不能使用直接进行for循环,会报错
            # 改用上面的readlines()或readline()也可以,但更繁琐些,同样需要按行解码,效率更低
            url_ts = line.decode('utf-8')
            tempName_ts = os.path.join(path, f'{num}.ts')  # f'{}' 相当于'{}'.format()
            if not '.ts' in url_ts:
                continue
            else:
                if not url_ts.startswith('http'):  # 判断字符串是否以'http'开头,如果不是则说明url链接不完整,需要拼接
                    # 拼接ts流视频的url
                    url_ts = url_m3u8.replace(url_m3u8.split('/')[-1], url_ts)
            print(url_ts)
            getDown_urllib(url_ts, tempName_ts)  # 下载视频流
            if num == 0:
                # 重命名,已存在则自动覆盖
                shutil.move(tempName_ts, tempName_video)
                num += 1
                continue
            cmd = f'copy /b {tempName_video}+{tempName_ts} {tempName_video}'
            res = os.system(cmd)
            if res == 0:
                os.system(f'del {tempName_ts}')
                if num == 20:  # 限制下载的ts流个数,这个视频挺长有四百多个.ts文件,所以限制一下
                    break
                num += 1
                continue
            print(f'Wrong, copy {num}.ts-->{videoName}.ts failure')
            return False
        os.system(f'del {path}/*.ts')  # 调用windows命令行(即cmd)工具,运行命令
        filename = os.path.join(path, f'{videoName}.mp4')
        shutil.move(tempName_video, filename)
        print(f'{videoName}.mp4 finish down!')
    
    
    if __name__ == '__main__':
        url_m3u8 = 'http://wscdn.alhls.xiaoka.tv/201886/2f5/75a/HoHdTc1LjUaBjZbJ/index.m3u8'
        path = r'E:pydevworkspacesprojectproductepgwvideos'
        videoName = url_m3u8.split('/')[-2]
        getVideo_urllib(url_m3u8, path, videoName)

    注:(1)仅限windows下使用,如果要在Linux上使用需要修改合并命令;

            (2)修改文件名时,特意选择shutil模块(可以看作os的高级版)的move方法,虽然move主要是用来移动文件的,重命名算是附带的,不过强制覆盖的特点在这里很有用,避免中断后重新下载时重命名产生异常。

  • 相关阅读:
    串匹配(C/C++实现)
    稀疏数组-矩阵存储【C语言实现】
    mysql frm、MYD、MYI数据文件恢复,导入MySQL中
    我们为什么要分库分表?
    golang 使用goto进行多错误处理
    mongodb 查看、创建、修改、删除索引
    MyBatis中模糊搜索使用like匹配带%字符时失效问题
    MySQL 用 limit 为什么会影响性能?
    【java框架】SpringBoot(10) -- SpringBoot巧用 @Async提升API接口并发能力
    【Java代码之美】 -- Java17新特性初探
  • 原文地址:https://www.cnblogs.com/lizm166/p/10262394.html
Copyright © 2011-2022 走看看