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})\n', 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 ~~\n')
     # 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:\pydevworkspaces\project\product\epgw\videos'
    videoName = url_m3u8.split('/')[-2]
    getVideo_urllib(url_m3u8, path, videoName)

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

        (2)修改文件名時,特意選擇shutil模塊(可以看作os的高級版)的move方法,雖然move主要是用來移動文件的,重命名算是附帶的,不過強制覆蓋的特點在這里很有用,避免中斷后重新下載時重命名產生異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM