资讯动态

m4s-converter源码解析:.playurl解析与番剧30000规则,两步识别音视频m4s文件

发布时间:2026/9/24 20:15:39 来源:尧图企业网站定制
m4s-converter源码解析.playurl解析与番剧30000规则两步识别音视频m4s文件【免费下载链接】m4s-converter一个跨平台小工具将bilibili缓存的m4s格式音视频文件合并成mp4项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converterm4s-converter是一个跨平台小工具用于把 Bilibili 客户端缓存的 m4s 音视频文件合并成可播放的 MP4 视频。当你缓存的视频被下架后这些分开的 m4s 文件就成了哑巴文件——而本工具会扫描缓存目录依靠.playurl文件识别哪个 m4s 是视频、哪个是音频再用 MP4Box 无损合成。本文以源码为线索拆解.playurl解析与番剧30000 规则两大核心机制帮你快速看懂 m4s 转 MP4 的全过程。 项目结构总览识别逻辑在哪里项目结构非常精简Go 语言编写核心逻辑集中在common包文件 / 目录职责main.go程序入口初始化日志与配置、注册 CtrlC 退出信号common/synthesis.go合成主流程扫描目录 → 识别音视频 → 提取元数据 → 去重 → 合成common/util.go核心工具m4s 识别、.playurl解析、重复检测、弹幕下载conver/vars.go文件后缀常量 文件名识别规则的关键注释conver/xml2ass.go弹幕 XML 转 ASS 字幕internal/linux.go、internal/windows.go按操作系统定位内置 MP4Box 可执行文件入口 main.go 做的事很简单初始化日志和配置在一个 goroutine 中捕获 CtrlC 实现优雅退出最后调用c.Synthesis()进入合成主流程。命令行参数自定义缓存路径-c、MP4Box 路径-g、关闭弹幕-a等在 common/config.go 中解析。 两步识别 m4s 文件从改名到配对工具并不直接猜 m4s 文件的内容而是分两步完成识别第一步读取 .playurl把 m4s 改名为标准音视频FindM4sFiles 会遍历缓存目录对每个.m4s文件调用 GetVAId 取出客户端缓存时记录的视频 ID和音频 ID然后按一个简单规则改名videoId, audioId : GetVAId(src) if strings.Contains(info.Name(), audioId) { dst strings.ReplaceAll(src, conver.M4sSuffix, conver.AudioSuffix) // → -audio.mp3 } else { dst strings.ReplaceAll(src, conver.M4sSuffix, conver.VideoSuffix) // → -video.mp4 }文件名里包含音频 ID 的就是音频文件否则就是视频文件。改名后统一变为xxx-video.mp4与xxx-audio.mp3后缀常量见 conver/vars.go。第二步递归搜索音视频配对GetAudioAndVideo 递归扫描缓存子目录分别按-video.mp4和-audio.mp3两个后缀查找文件。两种文件都齐了的目录就是一个可合成视频同时这一步还会顺带触发弹幕下载与 ASS 转换。找不到时返回找不到音频或视频文件错误该目录跳过。 .playurl 解析原理客户端留下的钥匙.playurl是 Bilibili 客户端缓存视频时生成的 JSON 文件里面存有该视频的 DASH 流地址信息。GetVAId 用 gjson 库从中取出两个关键 ID不同缓存结构取的位置不同普通视频data.dash.video[0].id与data.dash.audio[0].id番剧result.dash.video[0].id与result.dash.audio[0].id源码里先尝试取data节点不存在时自动回退到result用一行判断兼容了两种缓存结构if p gjson.GetBytes(puByte, data); !p.Exists() { p gjson.GetBytes(puByte, result) }还有一个兜底分支如果.playurl不存在常见于Android 手机缓存则转而去解析上级的entry.json文件先检查page_data.download_title确认缓存已完成再直接返回固定文件名video.m4s/audio.m4s——因为安卓端的两个文件本来就长这样。 番剧 30000 规则视频文件为什么是 30080.m4s这是最容易让人困惑的点普通视频的 m4s 文件名与.playurl里的 ID 完全一致但番剧的视频文件名比.playurl中的id多 30000。conver/vars.go 中的注释把这条规则解释得很清楚1332097557-1-30280.m4s // 30280 均为音频文件 1332097557-1-100048.m4s // 值不固定的为视频文件 番剧 result.dash.video[0].id 80 需要加上30000实际30080.m4s result.dash.audio[0].id 30280也就是说番剧的视频 ID 在.playurl里可能只是80实际缓存文件却叫30080.m4s而音频 ID30280则原样使用。工具的处理方式是**反向检查**不拿视频 ID 去匹配文件名而是拿音频 ID 匹配——谁的 m4s 文件名里含30280谁就是音频剩下的自然就是视频。音频 ID 是五位数且以 30 开头如 30280、30216几乎不可能出现在视频文件名里这一招巧妙地绕开了加 30000带来的差异。✅ 从识别到合成MP4Box 与三重防重复识别出音视频后Composition 调用内置的 MP4Box 可执行文件按平台查找见 internal/darwin.go执行无损合成不转码、不损失画质-add xxx-video.mp4#video -add xxx-audio.mp3#audio -new output.mp4完成音视频合并-tags title...:artist...:album...把分组 ID、用户 ID、视频 ID 作为标签写入 MP4主流程 common/synthesis.go 在此基础上设计了三重防重复机制避免重复运行产生一堆相同文件同名检查输出目录已存在同名 mp4 时读取其元数据标签与当前任务比对一致则跳过哈希检查对音视频文件计算 MD5 组合哈希并存入.hash文件内容相同则跳过元数据校验通过MP4Box -info提取 title / artist / album 逐一比对另外缓存状态不是completed / 视频已缓存完成的目录会被直接跳过避免合成残缺文件。 弹幕彩蛋XML 转 ASS 一步到位合成视频之外downloadXml 还会用目录名即 cid下载弹幕 XML 文件自动处理 deflate 解压再由 conver/xml2ass.go 转成 ASS 字幕文件与输出的 mp4 同名同目录存放播放时即可自动显示弹幕。不想要弹幕可用命令行参数-a关闭。 源码走读一次运行的完整链路main.go启动程序注册退出信号config.go解析命令行参数定位 MP4Box确认缓存目录synthesis.goWalkDir遍历触发 FindM4sFiles完成第一步识别改名逐个视频目录调用 GetAudioAndVideo 完成第二步识别读取videoInfo.json/entry.json获取标题、UP 主等元数据通过防重复检查 →Composition合成 → 写入哈希 → 自动打开输出目录想本地跑起来执行git clone https://gitcode.com/gh_mirrors/m4/m4s-converter依赖清单见 go.modgjson、logrus、zenity 等。小结m4s 识别是两步走先按.playurl中的 ID 改名为标准音视频再按后缀递归配对.playurl解析的关键在data与result两个顶层节点分别对应普通视频和番剧番剧 30000 规则通过匹配音频 ID反向检查巧妙化解无需特殊处理 30000 差异合成走 MP4Box 无损路线配合三重防重复机制与弹幕 ASS 自动转换读懂这份源码你对 Bilibili 的缓存目录结构、DASH 流 ID 命名规则就会了然于胸也能举一反三地开发自己的缓存处理工具。【免费下载链接】m4s-converter一个跨平台小工具将bilibili缓存的m4s格式音视频文件合并成mp4项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价