使用Python下载m3u8流媒体并嵌入到AMP网页中
在短视频和直播场景里,很多视频不是直接给你一个 mp4 文件,而是以 m3u8 播放列表加一组 .ts 分片的形式提供。如果你想做本地下载、静态归档,或者把视频转换后嵌入自己的页面,就需要自己处理这条链路。
这篇文章聚焦两件实际会遇到的事:
- 用 Python 下载 m3u8 对应的 TS 分片
- 把分片合并成 MP4,再嵌入 AMP 页面播放
如果你需要的是“浏览器里直接下载并转成 MP4”的方案,文末我也放了更新版本的延伸阅读。
0. 环境准备
先安装示例里用到的依赖:
pip install m3u8 requests
如果你后面要把 TS 分片合并成 MP4,还需要准备 ffmpeg。
1. 什么是m3u8?
M3U8格式基于HTTP Live Streaming (HLS)技术,可以对整个视频进行分割,形成一系列小的文件,然后创建一个索引文件(.m3u8),通过该索引文件可以加载流媒体。这意味着视频播放时,客户端只需要加载索引文件,之后根据索引文件逐个下载小的视频文件进行播放,从而支持了视频边下边播的功能。
2. 根据m3u8文件下载所有视频文件
我们首先需要获取到m3u8文件,并解析出文件中视频片段(.TS文件)的URL。为了处理网络请求,我们需要使用Python的requests库。以下是一段代码:
import m3u8
import requests
import os
def check_path(path):
if not os.path.exists(path):
os.makedirs(path)
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0"
}
domain = 'www.bobobk.com'
def download_m3u8(m3u8url):
print(m3u8url)
playlist_filename = os.path.join(*m3u8url.split('/')[3:])
if os.path.exists(playlist_filename):
pass
check_path(os.path.dirname(playlist_filename))
host = m3u8url.split("://")[1].split('/')[0]
baseurl, m3u8url = m3u8url.split("://")
if not os.path.exists(playlist_filename):
text = requests.get(m3u8url, headers=headers).text
open(playlist_filename, 'w').write(text.replace(host, domain))
m3u8_obj = m3u8.load(playlist_filename)
print(f"playlist:{playlist_filename}")
baseurl += "://" + m3u8url.split("/")[0]
print("start check playlist")
if len(m3u8_obj.playlists) != 0:
m3u8url = m3u8_obj.playlists[0].uri
if '://' not in m3u8url:
if m3u8url[0] == '/':
m3u8url = baseurl + m3u8_obj.playlists[0].uri
else:
m3u8url = baseurl + '/' + os.path.dirname(playlist_filename)+ '/' + m3u8_obj.playlists[0].uri
print(m3u8url)
text = requests.get(m3u8url, headers=headers).text
playlist_filename = os.path.join(*m3u8url.split('/')[3:])
check_path(os.path.dirname(playlist_filename))
open(playlist_filename, 'w').write(text.replace(host, domain))
m3u8_obj = m3u8.load(playlist_filename)
baseurl, m3u8url = m3u8url.split("://")
host = m3u8url.split('/')[0]
print(f"playlist:{playlist_filename}")
output = os.path.join(*m3u8_obj.segments[0].absolute_uri.split('/')[3:])
check_path(os.path.dirname(output))
print("check subdir")
for segment in m3u8_obj.segments:
segment_url = segment.absolute_uri
segment_file_name = os.path.join(*segment_url.split('/')[3:])
r = requests.get(segment_url, headers=headers, stream=True)
print(f"{segment_url}\t{segment_file_name}")
if os.path.exists(segment_file_name):
continue
with open(segment_file_name, 'wb') as f:
for chunk in r.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
m3u8url = "https://pptv.sd-play.com/202308/01/PfdfHWiJa43/video/index.m3u8"
download_m3u8(m3u8url)
这段脚本处理了一个比较实用的细节:如果遇到 master playlist,会继续向下解析到具体的 media playlist,再逐个下载 .ts 分片。
3. 将m3u8视频嵌入到amp网页
AMP(Accelerated Mobile Pages)网页是一种专为移动设备优化的开源框架,利用该框架,可以创建出快速,美观的网页应用。它用标准化但是灵活的方式,规定了HTML的使用,使得开发响应式网页变得更加简单。
直接将m3u8视频嵌入到AMP中,存在一个问题:目前,AMP并不支持直接播放m3u8文件。因此,我们需要将其转换为MP4格式,再将其嵌入到AMP网页中。
我们可以使用ffmpeg工具来合并.ts文件,并转换为.mp4文件。以下是代码:
for tsfile in "202308/01/PfdfHWiJa43/video/900k_0X480_64k_25/hls/"*.ts;do
echo "file '${tsfile}'" >> tsfile.txt
done
ffmpeg -f concat -safe 0 -i tsfile.txt -c copy 202308/01/PfdfHWiJa43/video/900k_0X480_64k_25/hls/202308.mp4
然后,我们可以在AMP网页中使用amp-video组件来播放这个mp4视频: https://www.bobobk.com/m3u8.html
<!doctype html>
<html amp>
<head>
<meta charset="utf-8">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<title>使用Python下载m3u8流媒体并嵌入到AMP网页中(amp video page)</title>
<link rel="canonical" href="self.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style>
<noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<script async custom-element="amp-video" src="https://cdn.ampproject.org/v0/amp-video-0.1.js"></script>
</head>
<body>
<amp-video controls width="640" height="360" layout="responsive" > <source src="/202308/01/PfdfHWiJa43/video/900k_0X480_64k_25/hls/202308.mp4" type="video/mp4"> </amp-video>
</body>
</html>
4. 如何验证下载和嵌入是否成功
建议至少检查下面 3 件事:
- 目标目录下是否已经完整生成
.ts分片文件 ffmpeg合并后的 MP4 是否可以正常播放- AMP 页面里的视频是否能在移动端正常加载
最直接的方式是先检查分片数量,再检查最终输出:
find 202308/01/PfdfHWiJa43/video/ -name '*.ts' | wc -l
ffmpeg -i 202308/01/PfdfHWiJa43/video/900k_0X480_64k_25/hls/202308.mp4
5. 常见问题与修复
1. 下载到一半失败
通常是源站限流、链接失效,或者部分分片不可访问。
修复:
- 补充更稳定的请求头
- 重新拉取最新 m3u8 地址
- 跳过已存在分片后继续下载
2. ffmpeg 合并失败
通常是 tsfile.txt 列表不完整,或分片顺序不对。
修复:
- 确认每个
.ts文件都存在 - 重新生成
tsfile.txt - 再执行一次
ffmpeg -f concat
3. AMP 页面里无法直接播放 m3u8
这不是脚本问题,而是 AMP 本身不直接支持 m3u8 播放。
修复:
- 先转换成 MP4
- 再通过
amp-video嵌入
6. 延伸阅读
7. 总结
本文详细介绍了使用Python下载m3u8流媒体并嵌入到amp网页中的整个过程,希望对你有所帮助。在实际应用中,请确保你完全遵循了使用流媒体服务的协议,并尊重相关的版权法律。
- 原文作者:春江暮客
- 原文链接:https://www.bobobk.com/892.html
- 版权声明:本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。