mirror of
https://github.com/ZHANGTIANYAO1/teamspeak-music-bot.git
synced 2026-10-01 20:42:50 +08:00
本地上传此前只接受音频。想放一段本地 mp4/mov/avi 里的音乐,四道关卡 挡着(前两道在服务端,后两道在浏览器端): 1. src/music/local.ts 的 AUDIO_EXTENSIONS 只列了 12 种音频后缀; 2. src/web/api/music.ts 里 express.raw 的 type 只匹配 audio/*、 video/webm、application/octet-stream —— 浏览器给 .mp4 打的 Content-Type 是 video/mp4,请求体压根不会被解析,处理函数看到 req.body === undefined,回 400「raw audio body is required」; 3. Search.vue 的 accept 属性让文件选择框把视频文件置灰; 4. isAudioFile() 把拖进来的视频文件静默丢掉。 ffmpeg 层不是瓶颈:s16le 输出格式不接受视频,ffmpeg 的自动选流本来 就只挑音轨。实测 mp4/mov/avi/mkv/flv/wmv/ts/m4v/mpg 九种容器用现有 参数全部正常出声,多音轨、带字幕、带 timecode 的也一样,所以 buildFfmpegArgs 一个字没动。 ## 改动 - **打通四道关卡**:新增 VIDEO_EXTENSIONS(mp4/mov/avi/mkv/flv/wmv/ m4v/mpg/mpeg/3gp/ts/m2ts/ogv),express.raw 收 video/*,前端 accept 与过滤函数同步放宽。 - **上传时抽取音轨**(extractAudioTrack):视频落盘后用 `-vn -sn -dn -map 0:a:0 -c:a copy` 把音轨原样搬进 Matroska 音频容器 (.mka)再删掉原视频。`-c:a copy` 不重编码,无损、快,且 Matroska 几乎收所有音频编码,不用维护「编码→后缀」对照表。实测 720p 素材 落盘体积降到原文件的 14%,这对 5 GiB 的上传目录配额很关键——否则 十来个视频就把配额占满了。抽取失败(冷门编码、超时)则保留原容器 继续播,只是占地方,绝不会因此上传失败。 - **拒绝没有音轨的视频**:上传时探测,直接回「这个视频里没有音轨, 无法播放」,而不是等到播放时静默跳过。只在 ffmpeg 确实打开了容器 (打印了 `Input #0,`)时才拒绝——认不出的字节一律放行,截断的 mp3 一直是这个行为,不能因为这次改动开始被拒。 - **上限从 200mb 提到 500mb**,并把超限响应从 Express 默认的 HTML 错误页(带堆栈和服务器绝对路径)换成和本路由一致的 JSON;前端也加 了同样的预检,不再传完几百兆才被拒。 - **上传进度**:视频比音频大得多,原来那句静止的「正在上传 N 个文件」 看着像卡死,现在按文件显示百分比,传完切到「服务端处理中」。 ## 验证 - 全量 `npx vitest run`:136 个文件 / 2070 项,新增 24 项。 - 新增测试用 ffmpeg 现造真实容器跑端到端:mp4 上传后时长正确、原 容器已删、剩下的 .mka 能被播放链路解码出 PCM;avi/mkv/flv 同样; 无音轨视频被拒且不留残留文件;纯音频上传字节数不变、不被重封装。 - 变异测试(逐个改回旧实现,确认新测试真的会红):后缀白名单 4 项失败、 express.raw 的 type 5 项失败、抽取音轨 2 项失败、无音轨拒绝 2 项失败。 - `npx tsc --noEmit` 与 `npx vue-tsc --noEmit` 均 exit 0。 Reported-by: @LadenceE Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>