将m3u8下载为MP4文件,Python 实现

将m3u8下载为MP4文件,Python 实现

在线看都某个不错的视频,便想把它下载下来。

看下开发者工具,发现是m3u8格式视频,该视频是不能像其他视频那样一键另存了。

m3u8是HTTP Live Streaming (HLS)的播放列表格式,通常用于视频分段传输。

该文件格式通常为如图所示,具体格式不做说明了,其中视频片段文件为这些 *ts。

要下载视频数据,只需先解析m3u8文件,获取所有的ts片段链接,然后下载这些片段,最后合并成mp4文件即可了。

使用m3u8_To_MP4实现

如果使用第三方依赖:m3u8_To_MP4,可以非常快捷实现:

import m3u8_To_MP4
if __name__ == '__main__':
    # 1. Download videos from uri.
    m3u8_To_MP4.multithread_download('http://videoserver.com/playlist.m3u8')
    # 2. Download videos from existing m3u8 files.
    m3u8_To_MP4.multithread_file_download('http://videoserver.com/playlist.m3u8',m3u8_file_path)
    # For compatibility, i reserve this api, but i do not recommend to you again.
    # m3u8_To_MP4.download('http://videoserver.com/playlist.m3u8')

来自:https://pypi.org/project/m3u8-To-MP4/

使用前提需要安装:python -m pip install m3u8_To_MP4

纯 Python 实现

有时候不想搞太多的第三方依赖,纯 Python 实现实现也没有几行代码,手闲也搞一个。

import argparse
import requests

# 解决Python3 控制台输出InsecureRequestWarning的问题
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

def print_used():
    print("python3 m3u8_to_mp4.py -i m3u8_file -o save_mp4_file")
    print(' example 1:python3 m3u8_to_mp4.py -i http://127.0.0.1:8001/index.m3u8 -o ./1.mp4')

def parse_param():
    parser = argparse.ArgumentParser(description="")
    parser.add_argument("-i")
    parser.add_argument("-o")
    args = parser.parse_args()

    return args.i, args.o

def main():
    _input, _output = parse_param()

    if not _input or not _output:
        print_used()
        exit()

    # 获取m3u8文件数据
    html = requests.get(_input, verify=False)
    m3u8_content = html.content.decode()
    src = _input[:_input.rfind("/")+1]

    if m3u8_content.find("#EXTM3U") == -1:
        print("not a m3u8 file")
        exit()

    # 解析出ts文件
    m3u8_content = m3u8_content.replace("\r\n", "\n").replace("\r", "\n")
    lines = list(filter(lambda line: line.endswith(".ts"), m3u8_content.split("\n")))

    # 下载ts合并到目标文件去
    out_file = open(_output, "wb")
    for i in range(len(lines)):
        line = lines[i] if lines[i].startswith("http") else src+lines[i]

        print("(%d/%d)loading:%s, " % (i+1, len(lines), line))
        ts = requests.get(line, verify=False)
        out_file.write(ts.content)

if __name__ == "__main__":
    main()

有些网站,其ts 数据是加密的。这类型的视频,会在m3u8文件内注明解密密钥地址数据,需要额外处理一下,但这种较少,就不考虑了。

使用方法:

python3 m3u8_to_mp4.py -i https://网站地址/xxx.m3u8 -o ./视频名字.mp4

(全文完)

(欢迎转载本站文章,但请注明作者和出处 编程想法 – Yuccn

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注