某教育平台视频下载完整指南

某教育平台视频下载完整指南
余逢某教育平台视频下载完整指南
目标页面信息
| 项目 | 内容 |
|---|---|
| 页面 | 坐位体前屈(小学体育与健康 · 一至二年级 · 水平一 · 人教版) |
| 页面URL | https://basic.smartedu.cn/syncClassroom/classActivity?activityId=d1a5243d-9b85-11ec-92ef-246e9675e50c&chapterId=b44e3dad-30a0-3b26-8856-4db325da2a89&teachingmaterialId=96297c58-094b-45c8-b4da-4034ee696824&fromPrepare=1&classHourId=lesson_1 |
| ActivityId | d1a5243d-9b85-11ec-92ef-246e9675e50c |
| 视频ID | 5520fef9-9ba6-11ec-9c6b-fa20200f090a |
| 视频封面 | https://r1-ndr.ykt.cbern.com.cn/edu_product/esp/micro_lesson_video/5520fef9-9ba6-11ec-9c6b-fa20200f090a.t/zh-CN/1769440331675/transcode/thumbnail.jpg |
| 视频格式 | HLS(m3u8 流媒体) |
| CDN | r1-ndr.ykt.cbern.com.cn / r3-ndr.ykt.cbern.com.cn |
一、平台架构分析
1.1 前端技术栈
该平台是一个 SPA(单页应用),使用 React + Webpack 构建,打包名为 webpackChunkbase_template。
核心 JS 文件:
| 文件 | 用途 |
|---|---|
chunk-fish-382dd43b.js |
富文本编辑器、视频播放器封装 |
chunk-uc-4d4ca6ab.js |
UC(用户中心)SDK,负责认证 |
chunk-react-3842c9f4.js |
React 框架 |
chunk-vendors-7c5b0ad5.js |
第三方库(video.js 6.13.0、HLS.js 等) |
app-2c2376a1.js |
主应用代码(1.3MB) |
classActivity 页面加载的 Webpack Chunks:
1 | 7937, 4308, 7167, 112, 8937, 1562, 1463, 9743, 2620, 2269, 1644, 8844, 8444, 5735, |
关键模块:
- Module 922846(chunk 2846): classActivity 页面主组件
- Module 760753(chunk 2846): courseInfo Hook,负责获取课程数据
- Module 210436(chunk 436): API 服务层,包含所有数据请求函数
- Chunk 1644: 视频播放器组件(VideoPlayer、QuestionVideoPlayer 等)
1.2 视频播放器
- 基于 video.js 6.13.0 + HLS.js
- 播放器 JS/CSS 托管在
gcdncs.101.com/v0.1/static/fish/videoplayer/0.2.15/ - 通过
beforeRequest钩子为 HLS 请求添加 Authorization 头 - 支持画质切换:默认、高清(720p)、标清(480p)、流畅(360p)
1.3 CDN 与资源存储
| 主机 | 用途 |
|---|---|
basic.smartedu.cn |
主站 |
bdcs-file-2.ykt.cbern.com.cn |
NDR 静态资源(公开) |
r{1,2,3}-ndr-private.ykt.cbern.com.cn |
NDR 私有资源(需认证) |
r{1,2,3}-ndr.ykt.cbern.com.cn |
NDR 公开资源 |
ndvideo-key.ykt.eduyun.cn |
AES-128 密钥服务器 |
gcdncs.101.com |
静态资源配置文件 |
二、视频数据获取流程
2.1 API 端点
课程详情(此接口无需认证,返回完整的课程结构数据):
1 | GET https://s-file-1.ykt.cbern.com.cn/zxx/ndrv2/national_lesson/resources/details/{activityId}.json |
2.2 数据结构
以「坐位体前屈 · 第一课时」为例,JSON 结构如下:
1 | { |
2.3 视频资源 ti_items
视频资源包含 6 个 ti_item:
| # | ti_file_flag | 格式 | 分辨率 | 加密 | 需认证 |
|---|---|---|---|---|---|
| 0 | href |
m3u8 | 1920×1080 | DRM | ✅ |
| 1 | href-360p-m3u8 |
m3u8 | 640×360 | DRM | ✅ |
| 2 | href-480p-m3u8 |
m3u8 | 852×480 | DRM | ✅ |
| 3 | href-720p-m3u8 |
m3u8 | 1280×720 | DRM | ✅ |
| 4 | href-m3u8 |
m3u8 | 1920×1080 | DRM | ✅ |
| 5 | thumbnail_1 |
jpg | - | 无 | ✅ |
每个 ti_item 的关键字段:
1 | { |
关键发现:ti_storage 字段的路径前缀 cs_path:${ref-path} 会被替换为 NDR 私有主机地址。
三、视频保护机制
3.1 第一层:访问认证(401 Unauthorized)
m3u8 文件托管在 NDR 私有 CDN(r*-ndr-private.ykt.cbern.com.cn),必须在 URL 中附带有效的 accessToken 参数。
1 | https://r2-ndr-private.ykt.cbern.com.cn/.../xxx.m3u8?accessToken=XXXXX |
accessToken 获取方式:
- 通过 UC(用户中心)SDK 的
uc.getToken()获取 - token 存储在 localStorage,key 为
ND_UC_AUTH-e5649925-441d-4a53-b525-51a2f1c4e0a8&ncet-xedu&token - token 结构包含
access_token、mac_key、diff等字段
token 生成代码(来自 app-2c2376a1.js):
1 | var C = function() { |
3.2 第二层:HLS AES-128 加密
m3u8 播放列表使用标准 HLS AES-128 加密:
1 | #EXT-X-KEY:METHOD=AES-128,URI="https://ndvideo-key.ykt.eduyun.cn/v1/resource_keys/0a14015988184e288b16feffb73b805a",IV=0x00000000000000000000000000000000 |
- 加密方式: AES-128(标准 HLS 加密,非 Widevine/FairPlay)
- 密钥服务器:
ndvideo-key.ykt.eduyun.cn - 密钥 ID:
0a14015988184e288b16feffb73b805a - IV: 全零(
0x00000000000000000000000000000000) - 分片数量: 124 个 .ts 文件
- 每个分片时长: 10秒(最后一个 5.92秒)
- 分片总大小: 约 232MB
3.3 密钥服务器认证(P.Key 计算)
密钥服务器 ndvideo-key.ykt.eduyun.cn 使用基于签名的认证机制。播放器在请求密钥时,需要携带正确的 nonce、sign 和 accessToken 参数。
与传统 MAC 签名方案的区别:原方案需要手动计算 HMAC-SHA256 签名并构造 Authorization 头,而本方案通过拦截密钥服务器的交互流程,自动计算出最终的 P.Key(即 AES 解密密钥),无需手动构造签名。
密钥请求流程:
第一步:获取签名参数(signs)
播放器首先向密钥服务器的 /signs 端点请求签名参数:
1 | GET https://ndvideo-key.ykt.eduyun.cn/v1/resource_keys/{keyId}/signs?accessToken={accessToken} |
返回 JSON 包含 nonce 字段,例如:
1 | { |
第二步:计算 sign 值
使用 MD5 对 nonce + keyId 进行哈希,取前 16 个字符作为 sign:
1 | // 需要 CryptoJS 库 |
示例:
- nonce =
"1780806943750:enc88ohj" - keyId =
"0a14015988184e288b16feffb73b805a" - sign =
MD5("1780806943750:enc88ohj0a14015988184e288b16feffb73b805a").substring(0, 16)
第三步:获取加密密钥
使用计算出的 sign 请求密钥服务器,获取 AES 加密的密钥:
1 | GET https://ndvideo-key.ykt.eduyun.cn/v1/resource_keys/{keyId}?nonce={nonce}&sign={sign}&accessToken={accessToken} |
返回的响应体是一个经过 AES-ECB 加密的密钥字符串。
第四步:AES-ECB 解密得到 P.Key
使用 sign 作为密钥,对响应体进行 AES-ECB 解密:
1 | var encrypted = response.key; // 服务器返回的加密密钥 |
P.Key 特征:
- 长度:16 字节(32 个十六进制字符)例如: “1ca2e7da4f3843e3”
- 格式:纯十六进制字符串
- 用途:作为 HLS AES-128-CBC 解密的密钥,对每个 .ts 分片进行解密
3.4 认证流程总结
1 | 浏览器 ──GET /signs?accessToken=XXX──▶ 密钥服务器 |
四、m3u8 播放列表详情
4.1 已获取的有效 m3u8 URL
1 | https://r1-ndr-private.ykt.cbern.com.cn/edu_product/esp/assets/5520fef9-9ba6-11ec-9c6b-fa20200f090a.t/zh-CN/1703758568544/videos/1f943ea8-82ee-4e8d-9693-7cd44e458221-1920x1080-true-e2fc96b320803614c423c7fa5d2e1565-a52ec2956b434eadb0ddc7883044afe5.m3u8 |
4.2 分片 URL 格式
1 | https://r1-ndr-private.ykt.cbern.com.cn/.../video{001..124}.ts?accessToken=XXX |
分片编号从 001 到 124,共 124 个分片。
4.3 分片可访问性验证
| 资源 | 状态 | 说明 |
|---|---|---|
| 播放列表 | ✅ 可访问 | 可通过 accessToken 访问 |
| 分片 | ✅ 可访问 | 可通过 accessToken 访问,单个约 1.8MB |
| 密钥 | ⚠️ 需认证 | 需要通过 P.Key 计算流程获取 |
| 缩略图 | ⚠️ 需认证 | 需要 accessToken |
五、一种可实现的下载方式
基于对平台架构的深入分析,以下是经过验证的完整下载方案。
注意:如果你觉得手动操作麻烦,可以安装脚本实现(几乎)全自动方案。详见「常见问题 → Q: 有没有更简单的自动化方案?」。
前提条件
你需要以下工具:
| 工具 | 用途 | 安装方式 |
|---|---|---|
| 浏览器 + 篡改猴(自行搜索安装方式) | 获取 P.Key、m3u8 和 token | 自行安装即可 |
| N_m3u8DL-RE | 下载、解密 m3u8 | 见下方 |
安装下载器:点此下载 N_m3u8DL-RE
第一步:获取 P.Key (不想动手可以翻到下面看第二个QA)
- 打开目标课程页面,在浏览器中确保视频可以正常播放
- 按 F12 打开浏览器控制台
- 切换到「源代码」(Sources) 标签
- 搜索
P.key,定位到videoplayer.min.js文件 - 找到如下代码段:
1 | O = P.key, |
在
n(i(j));这一行设置断点回到控制台,输入
j并回车,即可显示 P.Key 值P.Key 示例:
1ca2e7da4f3843e3以下图示(图片加载较慢,稍等)
这一串就是P.key
第二步:获取 M3U8 地址和 Token
2.1 获取M3U8地址。
在刚才获取P.key的基础上,在控制台切换到网络页面,按图操作。
2.2获取Token
另一种取 Token的方式
手动在控制台执行:
1 | localStorage.getItem("ND_UC_AUTH-e5649925-441d-4a53-b525-51a2f1c4e0a8&ncet-xedu&token") |
从返回的 JSON 中提取 access_token 字段的值。
第三步:拼接数据
先来回顾我们找到的三条数据:
P.key :1ca2e7da4f3843e3
Token:access_token:”7F938B205F876FC39BD5FD64A3C821679F8BC3B1766BEEDAF8D5DEDE5F005641C913C19A3083B606241F6C5E5D9F0DF42571E59BC6ED4B77”
将 m3u8 地址和 accessToken 拼接成最终地址:
1 | {m3u8地址}?accessToken={accessToken} |
示例:
1 | https://r1-ndr-private.ykt.cbern.com.cn/edu_product/esp/assets/5520fef9-9ba6-11ec-9c6b-fa20200f090a.t/zh-CN/1703758568544/videos/1f943ea8-82ee-4e8d-9693-7cd44e458221-1920x1080-true-e2fc96b320803614c423c7fa5d2e1565-a52ec2956b434eadb0ddc7883044afe5.m3u8?accessToken=7F938B205F876FC39BD5FD64A3C821679F8BC3B1766BEEDAF8D5DEDE5F005641C913C19A3083B606241F6C5E5D9F0DF42571E59BC6ED4B77 |
第四步:下载视频
使用 N_m3u8DL-RE 下载并解密:
1 | N_m3u8DL-RE "拼接好的m3u8地址" \ |
示例:
1 | N_m3u8DL-RE "https://r1-ndr-private.ykt.cbern.com.cn/...xxx.m3u8?accessToken=XXX" \ |
下载完成后,得到可播放的 .mp4 文件。
完整流程一览
1 | ┌─────────────────────────────────────────────────┐ |
常见问题
Q: accessToken 会过期吗?
会。 accessToken 有效期通常为 2-4 小时。如果下载过程中提示 401,需要重新获取 token。
Q: 下载的视频无法播放?
检查以下几点:
- 是否使用了
--key-hex提供正确的 P.Key - P.Key 是否是 16 字节(32 个十六进制字符)
- N_m3u8DL-RE 输出日志中是否有解密错误
Q: 有没有更简单的自动化方案?
可以安装篡改猴(Tampermonkey)脚本,实现(几乎)全自动下载:
- 自动获取 m3u8、accessToken,并进行拼接
- 自动拦截密钥服务器交互,计算 P.Key
- 内置一键下载功能(2GB 以内视频直接下载,超过 2GB 使用外部下载器)
脚本安装步骤:
- 安装篡改猴浏览器扩展(自行搜索安装方法)
- 下载脚本:下载地址(已打包好篡改猴插件)
- 安装脚本后,进入课程视频页面,脚本会自动捕获所有参数
- 点击面板上的「一键下载 MP4」即可
注意:脚本内置下载仅支持 2GB 以内的视频,超过此大小请使用 N_m3u8DL-RE 下载器。
附录
智慧教育平台教材下载
链接格式:
普通教材:
1 | https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId=(教材contentId)&catalogType=tchMaterial&subCatalog=tchMaterial |
资源包教材:
1 | https://basic.smartedu.cn/tchMaterial/detail?contentType=thematic_course&contentId=(教材contentId)&catalogType=tchMaterial&subCatalog=tchMaterial |
解析接口:
普通教材:
1 | https://s-file-2.ykt.cbern.com.cn/zxx/ndrv2/resources/tch_material/details/(教材contentId).json |
资源包教材:
1 | https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/special_edu/thematic_course/(教材contentId)/resources/list.json |
英语听力:
1 | https://s-file-1.ykt.cbern.com.cn/zxx/ndrs/resources/(教材contentId)/relation_audios.json |
示例网页链接:
普通教材:
1 | https://basic.smartedu.cn/tchMaterial/detail?contentType=assets_document&contentId=bdc00134-465d-454b-a541-dcd0cec4d86e&catalogType=tchMaterial&subCatalog=tchMaterial |
资源包教材:
1 | https://basic.smartedu.cn/tchMaterial/detail?contentType=thematic_course&contentId=2afcdb56-6fce-8c99-0bc9-e9dd33b5c51c&catalogType=tchMaterial&subCatalog=tchMaterial |
智慧教育平台课程资源下载
链接格式:
教育部资源:
1 | https://basic.smartedu.cn/syncClassroom/classActivity?activityId=(资源包activityId)&chapterId=&teachingmaterialId=&fromPrepare=0 |
学校提供网课:
1 | https://basic.smartedu.cn/qualityCourse?courseId=(资源包teachingmaterialId)&chapterId=&teachingmaterialId=&fromPrepare=0&classHourId=lesson_1 |
备课:
1 | https://basic.smartedu.cn/syncClassroom/prepare/detail?lessonId=(资源包lessonId)&chapterId=&teachingmaterialId=&fromPrepare=1&classHourId=lesson_1 |
解析接口:
需要带上 X-Nd-Auth 标头
教育部资源:
1 | https://s-file-1.ykt.cbern.com.cn/zxx/ndrv2/national_lesson/resources/details/(资源包activityId).json |
学校提供网课:
1 | https://s-file-2.ykt.cbern.com.cn/zxx/ndrv2/resources/(资源包teachingmaterialId).json |
备课:
1 | https://s-file-2.ykt.cbern.com.cn/zxx/ndrv2/prepare_lesson/resources/details/(资源包lessonId).json |
示例网页链接:
教育部资源:
1 | https://basic.smartedu.cn/syncClassroom/classActivity?activityId=f15feef1-b908-44f5-a765-500b9395c313&chapterId=8d6cc118-a169-3ea1-9a45-31cc841ad239&teachingmaterialId=4a4aa279-8dc6-4098-b45f-dd3f7d5a61b2&fromPrepare=0 |
学校提供网课:
1 | https://basic.smartedu.cn/qualityCourse?courseId=8ae7e48f-842c-12fc-0184-35dacdee016f&chapterId=8ae5c0d4-cfd4-34d1-9757-0295bd0c55ed&teachingmaterialId=4a4aa279-8dc6-4098-b45f-dd3f7d5a61b2&fromPrepare=0&classHourId=lesson_1 |
备课:
1 | https://basic.smartedu.cn/syncClassroom/prepare/detail?lessonId=8aee80a5-6b86-5bc9-016b-87465e6e0290&chapterId=5bb731e1-cdac-3984-a977-3d44c5d2d809&teachingmaterialId=4a4aa279-8dc6-4098-b45f-dd3f7d5a61b2&fromPrepare=1&classHourId=lesson_1 |











