新闻详情

新闻详情

首页 / 资讯中心 / 详情

Python实战:M3U8分片下载与FFmpeg合并,一键保存智慧教育平台课程

发布时间:2026/9/26 5:51:47来源:尧图网络
Python实战:M3U8分片下载与FFmpeg合并,一键保存智慧教育平台课程
1. 这个工具到底解决了什么问题国家中小学智慧教育平台上的课程资源质量确实不错覆盖了从小学到高中的主要学科而且都是官方录制的完整课程。但用过的人都知道它有一个非常让人头疼的限制没有提供批量下载功能。你想把一节40分钟的课保存到本地只能在线看或者用一些不太靠谱的录屏方式画质和音质都打折扣。更麻烦的是这个平台的视频采用了M3U8 分片传输的方式。简单来说一个完整的视频被切成了几百上千个小的.ts文件通过一个.m3u8索引文件来组织播放顺序。你打开浏览器开发者工具看到的是密密麻麻的请求列表手动一个个下载再合并几乎是不可能完成的任务。所以smartedu-download这个项目的核心价值就一句话把国家中小学智慧教育平台上的课程视频一键下载到本地自动合并成完整的 MP4 文件。它用 Python 写成封装了从解析 M3U8 索引、批量下载 TS 分片、到调用 FFmpeg 合并输出的完整流程。对于家里网络不稳定、想给孩子反复看课、或者想把优质课程存档的家长和老师来说这个工具非常实用。这篇文章我会从零开始把整个项目的设计思路、核心代码、实操步骤、以及我踩过的坑全部拆开讲清楚。即使你之前没写过 Python跟着走也能跑起来。2. 整体设计思路与方案选型2.1 为什么选择 Python 而不是其他语言这个项目本质上是一个网络请求 文件处理 媒体合并的自动化脚本。Python 在这个场景下有天然优势requests 库处理 HTTP 请求极其简洁几行代码就能完成带 Cookie、Referer 的请求多线程/多进程支持成熟下载几百个 TS 分片时能显著提速FFmpeg 的 Python 封装或者直接subprocess调用都很方便跨平台Windows、macOS、Linux 都能跑如果用 Go 或 Rust 写性能会更好但开发效率和代码可读性对普通用户不够友好。这个工具的目标用户是家长和老师不是专业程序员所以 Python 是最平衡的选择。2.2 M3U8 下载的核心逻辑M3U8 是 HLSHTTP Live Streaming协议使用的索引格式。一个典型的 M3U8 文件长这样#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.000000, segment_000.ts #EXTINF:10.000000, segment_001.ts #EXTINF:10.000000, segment_002.ts ... #EXT-X-ENDLIST每一行#EXTINF后面跟着的是这个分片的时长下一行是分片文件名。下载工具要做的就是请求 M3U8 文件解析出所有 TS 分片的 URL并发下载所有 TS 分片到本地临时目录按顺序拼接所有 TS 分片用 FFmpeg 把 TS 流转换为 MP4 格式注意有些 M3U8 文件是加密的会有#EXT-X-KEY标签需要先获取密钥才能解密。国家中小学智慧教育平台的资源目前大部分没有加密但如果你遇到加密的源需要额外处理密钥请求。2.3 为什么需要 FFmpegTS 分片直接拼接得到的文件虽然能用某些播放器打开但兼容性很差。FFmpeg 的作用是重新封装把 TS 流封装成 MP4 容器兼容所有播放器修复时间戳分片拼接后时间戳可能不连续FFmpeg 会自动处理转码可选如果源视频编码格式特殊可以转成 H.264 AAC 的通用格式FFmpeg 的调用命令很简单ffmpeg -i input.ts -c copy -bsf:a aac_adtstoasc output.mp4-c copy表示不重新编码直接复制流速度极快。-bsf:a aac_adtstoasc是处理 AAC 音频流的比特流过滤器避免音频播放异常。2.4 打包成 EXE 的考量很多用户没有 Python 环境所以项目提供了打包成 EXE 的方案。常用的工具有PyInstaller和Nuitka。PyInstaller 更简单一行命令就能打包pyinstaller -F -w smartedu_download.py-F表示打包成单个文件-w表示不显示控制台窗口。但 PyInstaller 打包出来的 EXE 体积较大通常 10-30MB启动也稍慢。Nuitka 会把 Python 代码编译成 C性能和体积都更优但配置复杂一些。3. 核心细节解析与实操要点3.1 如何获取真实的 M3U8 地址这是整个流程中最关键的一步。国家中小学智慧教育平台的视频播放页面并不是直接把 M3U8 地址写在 HTML 里的而是通过 JavaScript 动态加载。你需要打开课程播放页面按 F12 打开开发者工具切换到Network网络面板筛选m3u8关键字刷新页面找到返回 M3U8 内容的请求复制这个请求的 URL实操心得平台的 M3U8 地址通常带有时效性 Token过期后需要重新获取。所以下载要尽快开始不要拖太久。3.2 请求头的伪装直接请求 M3U8 地址可能会被拒绝因为服务器会检查Referer和User-Agent。你需要带上headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://basic.smartedu.cn/, }Referer告诉服务器你是从平台页面跳转过来的User-Agent模拟浏览器。这两个字段缺一不可否则大概率返回 403。3.3 多线程下载的线程数选择TS 分片数量可能从几十到上千不等。单线程下载太慢但线程数也不是越多越好。我的经验是分片数量推荐线程数理由 1008-16分片少线程太多反而增加调度开销100-50016-32平衡速度和服务器压力 50032-64分片多需要更高并发线程数过高会导致服务器限流甚至封 IP。建议从 16 开始测试如果下载速度稳定再逐步增加。3.4 分片顺序的保证多线程下载时分片完成的顺序是随机的。但合并时必须按原始顺序拼接否则视频会乱序。解决方案有两种方案一下载时用分片索引作为文件名如0001.ts、0002.ts合并时按文件名排序方案二用一个列表记录分片顺序下载完成后按列表顺序拼接我推荐方案一简单可靠而且方便断点续传。3.5 FFmpeg 的路径问题FFmpeg 不是 Python 标准库需要单独安装。Windows 用户下载ffmpeg.exe后要么放到系统 PATH 里要么在代码里指定绝对路径FFMPEG_PATH rC:\ffmpeg\bin\ffmpeg.exe常见坑如果路径中有空格subprocess调用时需要用引号包裹或者用列表形式传参。我建议用列表形式避免转义问题。4. 完整实操流程与核心代码4.1 环境准备首先确保你的电脑上有 Python 3.8 以上版本。Windows 用户去 Python 官网下载安装包安装时勾选Add Python to PATH。安装完成后打开命令行验证python --version pip --version然后安装依赖库pip install requests pip install tqdmrequests用于网络请求tqdm用于显示下载进度条。FFmpeg 需要单独下载解压后把bin目录添加到系统 PATH。4.2 解析 M3U8 文件import requests import re def parse_m3u8(m3u8_url, headers): resp requests.get(m3u8_url, headersheaders, timeout30) resp.raise_for_status() content resp.text # 提取所有 TS 分片文件名 ts_list re.findall(r^[^#].*\.ts.*$, content, re.MULTILINE) # 处理相对路径 base_url m3u8_url.rsplit(/, 1)[0] ts_urls [] for ts in ts_list: ts ts.strip() if ts.startswith(http): ts_urls.append(ts) else: ts_urls.append(f{base_url}/{ts}) return ts_urls这段代码的核心是正则表达式^[^#].*\.ts.*$它会匹配所有不以#开头且包含.ts的行。re.MULTILINE让^和$匹配每一行的开头和结尾。4.3 多线程下载分片import os from concurrent.futures import ThreadPoolExecutor, as_completed from tqdm import tqdm def download_segment(args): url, index, save_dir, headers args filename os.path.join(save_dir, f{index:05d}.ts) # 断点续传如果文件已存在且大小合理跳过 if os.path.exists(filename) and os.path.getsize(filename) 0: return filename for retry in range(3): try: resp requests.get(url, headersheaders, timeout60) resp.raise_for_status() with open(filename, wb) as f: f.write(resp.content) return filename except Exception as e: if retry 2: raise e return filename def download_all(ts_urls, save_dir, headers, max_workers16): os.makedirs(save_dir, exist_okTrue) tasks [(url, i, save_dir, headers) for i, url in enumerate(ts_urls)] with ThreadPoolExecutor(max_workersmax_workers) as executor: futures [executor.submit(download_segment, task) for task in tasks] for future in tqdm(as_completed(futures), totallen(futures), desc下载分片): future.result()这里有几个关键点断点续传如果文件已存在且大小大于 0直接跳过。这样中断后重新运行不会重复下载重试机制每个分片最多重试 3 次避免网络抖动导致失败进度条tqdm让用户看到下载进度体验更好4.4 合并分片并转 MP4import subprocess def merge_segments(save_dir, output_file, ffmpeg_pathffmpeg): # 获取所有 TS 文件并按名称排序 ts_files sorted([f for f in os.listdir(save_dir) if f.endswith(.ts)]) # 生成合并列表文件 list_file os.path.join(save_dir, filelist.txt) with open(list_file, w, encodingutf-8) as f: for ts in ts_files: f.write(ffile {ts}\n) # 调用 FFmpeg 合并 cmd [ ffmpeg_path, -f, concat, -safe, 0, -i, list_file, -c, copy, -bsf:a, aac_adtstoasc, output_file ] subprocess.run(cmd, cwdsave_dir, checkTrue) print(f合并完成{output_file})-f concat告诉 FFmpeg 使用拼接模式-safe 0允许使用绝对路径-c copy不重新编码。整个过程通常只需要几秒钟。4.5 打包成 EXE如果你想把脚本分享给没有 Python 环境的朋友可以用 PyInstaller 打包pip install pyinstaller pyinstaller -F -w -i icon.ico smartedu_download.py打包完成后dist目录下会生成一个.exe文件。但要注意FFmpeg 不会被自动打包进去需要单独放在同目录下如果代码里用了相对路径打包后路径会变化建议用os.path.dirname(sys.executable)获取 EXE 所在目录实操心得PyInstaller 打包的 EXE 启动时会解压到临时目录杀毒软件可能会误报。建议给 EXE 添加数字签名或者提前告知用户添加信任。5. 常见问题与排查技巧实录5.1 下载速度慢怎么办问题现象分片下载速度只有几十 KB/s一个视频要下几个小时。排查思路检查网络本身是否正常尝试访问其他网站降低线程数可能是服务器限流检查是否走了代理某些代理会限制大文件下载尝试更换 DNS有些 CDN 节点解析慢解决方案我实测下来线程数从 16 降到 8速度反而更稳定。另外把下载任务安排在非高峰时段比如深夜速度会明显提升。5.2 FFmpeg 合并报错问题现象ffmpeg报错Invalid data found when processing input。原因分析通常是某个 TS 分片下载不完整或损坏。解决方案检查分片文件大小异常小的文件如 0 字节就是损坏的删除损坏的分片重新下载如果多个分片损坏可能是网络问题建议降低线程数重试5.3 视频播放没有声音问题现象合并后的 MP4 能播放但没有声音。原因分析AAC 音频流的 ADTS 头没有正确处理。解决方案确保 FFmpeg 命令中加了-bsf:a aac_adtstoasc。如果还是不行尝试去掉-c copy让 FFmpeg 重新编码音频ffmpeg -i input.ts -c:v copy -c:a aac -b:a 128k output.mp45.4 EXE 在别人电脑上打不开问题现象自己电脑上能运行的 EXE发给别人后报错。排查清单问题检查项解决方法缺少 DLL是否在纯净系统测试用--add-data打包依赖路径错误是否用了绝对路径改用sys.executable获取路径杀毒拦截是否被 Windows Defender 拦截添加信任或签名权限不足是否在 Program Files 目录改用用户目录5.5 M3U8 地址失效问题现象昨天还能下载的地址今天报 403。原因分析平台的 Token 有时效性通常几小时到一天。解决方案重新从浏览器获取新的 M3U8 地址。建议获取后立即开始下载不要拖延。5.6 常见问题速查表问题可能原因快速解决403 Forbidden缺少 Referer补全请求头分片下载失败网络抖动增加重试次数合并后花屏分片顺序错乱检查文件名排序音频不同步时间戳问题用 FFmpeg 重新封装EXE 体积过大PyInstaller 打包改用 Nuitka 或 UPX 压缩下载中断网络断开利用断点续传重新运行6. 进阶优化与扩展思路6.1 支持批量下载整个课程单个视频下载只是基础实际使用中更常见的是下载整个课程几十个视频。思路是解析课程页面的 HTML提取所有视频的 ID对每个视频 ID调用平台的 API 获取 M3U8 地址循环调用下载函数这里的关键是找到平台的 API 接口。通过浏览器开发者工具观察播放页面加载时的 XHR 请求通常能找到返回视频信息的接口。6.2 添加图形界面命令行工具对普通用户不够友好。可以用tkinter或PyQt做一个简单的 GUI输入框粘贴 M3U8 地址选择目录选择保存位置开始按钮触发下载进度条显示下载进度tkinter是 Python 自带的不需要额外安装适合快速开发。6.3 自动识别并下载更进一步可以做一个浏览器插件或者油猴脚本在播放页面自动提取 M3U8 地址然后调用本地工具下载。这样用户只需要点一下按钮完全不需要手动复制地址。6.4 处理加密的 M3U8如果遇到加密的 M3U8需要解析#EXT-X-KEY标签获取密钥 URL请求密钥 URL得到解密密钥用 AES-128 解密每个 TS 分片Python 的pycryptodome库可以处理 AES 解密。这部分代码稍复杂但原理不复杂。7. 我踩过的坑和实操建议第一个坑是Referer 缺失。我一开始只带了 User-Agent结果一直返回 403。后来抓包对比浏览器请求才发现少了 Referer。这个字段在平台的反盗链机制中很关键。第二个坑是线程数过高导致 IP 被限。我一开始设了 64 线程下载了大概 200 个分片后所有请求都超时了。等了几分钟才恢复。后来改成 16 线程稳定跑完整个视频。第三个坑是FFmpeg 路径问题。我在代码里写的是ffmpeg但 Windows 上如果 PATH 没配好会报FileNotFoundError。后来改成配置文件读取让用户可以自己指定路径。第四个坑是打包后的路径问题。PyInstaller 打包后__file__指向的是临时解压目录不是 EXE 所在目录。用sys.executable才能拿到正确路径。最后分享一个小技巧下载前先请求第一个分片确认能正常返回再启动多线程下载。这样可以避免因为地址失效导致所有线程都失败。这个工具后续还可以扩展成支持其他教育平台的下载核心逻辑是一样的只需要适配不同的 API 和请求头。如果你对 Python 爬虫和媒体处理感兴趣这个项目是一个很好的练手素材。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Wallhaven最新入口获取与高效筛选壁纸完整指南 2026/9/26 6:30:06

Wallhaven最新入口获取与高效筛选壁纸完整指南

1. 壁纸资源站的核心价值与选型逻辑1.1 为什么高质量壁纸站点依然是刚需做桌面美化这些年,我试过的壁纸来源少说也有几十个。从早期各大门户的壁纸频道,到后来各种聚合类应用,兜兜转转一圈下来,真正能长期留在浏览器书签里的其实就…

阅读更多 →
发布检查单自动化全流程串联:实现从 PR 提交到上线前的一键巡检 2026/9/26 6:30:06

发布检查单自动化全流程串联:实现从 PR 提交到上线前的一键巡检

发布检查单自动化全流程串联:实现从 PR 提交到上线前的一键巡检在现代持续交付(Continuous Delivery)体系中,如何兼顾“极速发布”与“极致稳定性”一直是研发团队面临的核心矛盾。 过去,团队为了保证发布质量&#xf…

阅读更多 →
利用运营技能地图基于Python解析用户指标及订单跟踪 2026/9/26 6:29:59

利用运营技能地图基于Python解析用户指标及订单跟踪

在当前的数据驱动时代,企业和组织越来越依赖于数据分析来指导决策和优化运营。Python作为一种强大的编程语言,提供了广泛的库和工具,使得从复杂数据集中提取有用信息变得可行和高效。企业运营的核心在于增加客户、订单、收入、注册量及提高效率。这些目标可通过《运营技能地…

阅读更多 →
使用机器学习进行客户终身价值和RFM模型分析 2026/9/26 6:29:59

使用机器学习进行客户终身价值和RFM模型分析

在探讨如何提升产品的市场竞争力时,理解用户价值是关键。这不仅关系到产品设计,更涉及到如何精准地满足用户需求。随着技术的不断进步,客户行为和市场研究方法也在持续变化。因此,公司需要不断地调整市场策略,尤其是在营销上。面对这样的情况,客户细分成了一个重要的策略…

阅读更多 →
Python机器学习零基础理解回归模型的准确性指标和评估 2026/9/26 6:29:59

Python机器学习零基础理解回归模型的准确性指标和评估

在日常生活中,预测和评估无处不在。无论是预测明天的天气,还是估算家庭预算,都在不断地做出判断和评估。在机器学习和数据科学的世界里,这些预测和评估被高度数学化和系统化,形成了一套复杂但高效的模型和算法。其中回归模型是最常见和最基础的一种。 然而一个自然而然的…

阅读更多 →
xgplayer Monorepo 仓库地图:从目录导航、开发命令到发布协作的完整指南 2026/9/26 6:29:53

xgplayer Monorepo 仓库地图:从目录导航、开发命令到发布协作的完整指南

音视频前端 【免费下载链接】xgplayer A HTML5 video player with a parser that saves traffic 项目地址: https://gitcode.com/gh_mirrors/xg/xgplayer 点击查看 免费下载 本文基于仓库根目录的 CLAUDE.md(AGENTS.md 仓库导航图)展开&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉