三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

央视HLS视频流处理实战:m3u8解析、ts分片合并与mp4封装全流程

央视HLS视频流处理实战:m3u8解析、ts分片合并与mp4封装全流程

前几篇文章分析了央视视频接口和签名机制,这篇聚焦拿到视频地址之后的环节——如何把HLS分片流处理成完整的mp4文件。

一、HLS协议基础

HLS(HTTP Live Streaming)是苹果提出的流媒体协议,核心思想是将完整视频切片传输:

m3u8 索引文件
├── seg-001.ts (5-10秒)
├── seg-002.ts (5-10秒)
├── seg-003.ts (5-10秒)
└── … (几百个分片)
m3u8是索引文件,记录所有分片的顺序和地址。播放器按顺序拉取分片,边下边播。

二、m3u8文件解析

用Python的 m3u8 库解析索引文件:

python

import m3u8

def parse_m3u8(url: str) -> list:
“”“解析m3u8索引,返回分片URL列表”“”
playlist = m3u8.load(url)
segments = [seg.uri for seg in playlist.segments]
return segments

使用示例

segments = parse_m3u8(“https://example.com/index.m3u8”)
print(f"共 {len(segments)} 个分片")
解析后拿到的是每个ts分片的下载地址列表。

三、ts分片批量下载

python

import requests
from concurrent.futures import ThreadPoolExecutor

def download_segment(url: str, index: int, output_dir: str) -> str:
“”“下载单个ts分片”“”
resp = requests.get(url, timeout=30)
path = f"{output_dir}/seg_{index:04d}.ts"
with open(path, ‘wb’) as f:
f.write(resp.content)
return path

def download_all_segments(segments: list, output_dir: str, max_workers: int = 4):
“”“多线程批量下载所有分片”“”
os.makedirs(output_dir, exist_ok=True)
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = []
for i, url in enumerate(segments):
futures.append(executor.submit(download_segment, url, i, output_dir))
results = [f.result() for f in futures]
# 按序号排序
results.sort()
return results
注意控制并发数,央视对IP请求频率有限制,建议4线程以内。

四、ts分片合并

分片下载完成后,有两种合并方式:

方式一:FFmpeg直接从m3u8合并(最简单)

bash

ffmpeg -i “https://example.com/index.m3u8” -c copy -bsf:a aac_adtstoasc output.mp4
-c copy 不重新编码,速度极快。-bsf:a aac_adtstoasc 把ts容器的AAC音频转成mp4容器格式。

方式二:本地分片文件合并(适合断点续传场景)

先创建一个本地m3u8文件指向已下载的分片:

python

def create_local_m3u8(segment_files: list, output: str):
“”“生成本地m3u8索引文件”“”
with open(output, ‘w’) as f:
f.write(“#EXTM3U\n”)
f.write(“#EXT-X-VERSION:3\n”)
for seg in segment_files:
f.write(f"#EXTINF:10.0,\n")
f.write(f"{seg}\n")
f.write(“#EXT-X-ENDLIST\n”)
然后用FFmpeg合并:

bash

ffmpeg -protocol_whitelist file -i local.m3u8 -c copy -bsf:a aac_adtstoasc output.mp4
五、mp4封装优化

合并后的mp4可以进一步优化:

  1. 快速启动(faststart)

bash

ffmpeg -i input.mp4 -c copy -movflags +faststart output.mp4
把moov atom移到文件头部,网页播放时不用等整个文件下载完就能开始播放。

  1. 元信息写入

python

from mutagen.mp4 import MP4, MP4Tags

def write_metadata(filepath: str, title: str, artist: str = “CCTV”):
“”“写入视频元信息”“”
video = MP4(filepath)
video[“\xa9nam”] = title # 标题
video[“\xa9ART”] = artist # 作者
video[“\xa9alb”] = “央视纪录片” # 专辑
video.save()
六、性能对比

合并方式 速度 适用场景 备注
FFmpeg直接从URL合并 中 网络稳定时 最简单
多线程下载+本地合并 快 需要断点续传 适合批量
FFmpeg从本地m3u8合并 极快 已下载全部分片 无网络依赖
七、常见问题

Q:合并后播放没声音?

加上 -bsf:a aac_adtstoasc 参数,把AAC音频流从ADTS格式转到ASC格式。

Q:合并后画面花屏?

检查分片是否完整下载,缺失分片会导致合并异常。建议下载后校验文件大小。

Q:FFmpeg报错 “Invalid data”?

m3u8中的分片地址可能是相对路径,需要用 -protocol_whitelist file,http,https,tcp,tls,crypto 参数。

八、总结

HLS流处理的核心流程是:解析m3u8索引→批量下载ts分片→FFmpeg合并封装为mp4。如果不想手动处理这些步骤,CCTV视频下载器v18已经内置了完整的流处理逻辑,粘贴链接即可一键完成。相关技术资料在盘资源基地(cc.ewp.cc)有整理讨论。
https://pan.baidu.com/s/1ynh0u6YsLXXVP4GKKMC6RA?pwd=aa28 提取码: aa28

← 返回列表