Files
music-visualizer/README.md
T
blumia a237a7c604 Add one-line score visualizer with 3D orb and MP4 export
- Verovio single-system engraving, MuseScore audio/MIDI from the same source
- React + Remotion player with live camera, colour and orb controls
- Express pipeline, render queue and local H.264/AAC export
- MIT license plus third-party notices for the reference skill
2026-11-05 11:38:25 +08:00

134 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Music Visualizer
把一份 MusicXML / MXL / MIDI 谱面变成横向滚动、单行不换页的音乐视频:谱面始终只有一行,发光小球沿真实符头跳跃,支持实时调参并用 Remotion 在本地导出 MP4。
视觉与运动参数参考了 [Dancing Notes](https://github.com/SyanChen7/dancing-notes)(MIT),本项目重写了排版、音频、对齐、滚动和 Web 端流水线。
## 功能
- **单行谱面**:Verovio `breaks: none` 生成一条超宽 system,按播放进度横向滚动到结尾,不换行、不翻页。
- **音画同源**:默认调用本机 MuseScore 4,从同一份 MusicXML 生成 WAV 和 MIDI;动画时间来自 MIDI,谱面符头坐标来自 Verovio SVG。
- **发光小球**:每个声部一颗球,沿符头连续跳跃;包含起跳、抛物线、落点光环、拖尾和纸面光晕。
- **反复段**:按演奏顺序回到前面的谱面位置,滚动也会短暂回退。
- **实时预览**:生成一次后,画面高度、滚动提前量、3D 视角、颜色、光晕、小球大小、标题显示等参数会立即反映在 Remotion Player 中,不需要重新跑流水线。
- **3D 倾斜视角**:可调俯仰、滚转、偏航、透视距离和缩放,内置平视 / 轻斜 / 电影 / 强透视预设。
- **导出**:使用 `@remotion/renderer` 在本地渲染 1080p H.264 + AAC MP4。导出前会把当前实时参数写回任务,保证视频与预览一致。
- **输入**:MusicXML、MXL(压缩包)、MIDI。MIDI 会先由 MuseScore 识别成 MusicXML。
- **可选音频**:可以上传自己的 WAV / MP3 / M4A / OGG / FLAC 替代自动合成音频;动画仍使用 MIDI/谱面时间轴。
## 环境要求
- Node.js 22+(推荐 24)
- MuseScore 4(自动合成音频、MIDI 转谱需要)
- Chrome 或 Edge(Remotion 渲染会优先使用本机浏览器,避免下载 Headless Shell)
- Windows PowerShell 下开发即可;其他平台同样适用
MuseScore 默认从常见安装路径查找,也可以显式指定:
```powershell
$env:MUSESCORE_PATH = "C:\Program Files\MuseScore 4\bin\MuseScore4.exe"
```
## 开发
```powershell
npm install
npm run dev
```
- 前端:<http://127.0.0.1:5173>
- API:<http://127.0.0.1:3001>
- Vite 会把 `/api`、`/jobs`、`/demo` 代理到服务端。
## 生产运行
```powershell
npm run build
npm start
```
生产模式由 Express 同时提供 API 和 `dist/client` 静态文件,默认端口 `3001`。
可配置环境变量:
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `PORT` | `3001` | 服务端口 |
| `PUBLIC_BASE_URL` | `http://127.0.0.1:${PORT}` | Remotion 渲染时访问 SVG / 音频的公开地址 |
| `DATA_DIR` | `data` | 任务与产物目录 |
| `MUSESCORE_PATH` | 自动查找 | MuseScore 4 可执行文件 |
| `REMOTION_BROWSER_EXECUTABLE` / `BROWSER_EXECUTABLE` | 自动查找 | 指定 Chrome / Edge 可执行文件 |
## 使用流程
1. 拖入 MusicXML / MXL / MIDI;或者点“加载示例曲”。
2. 可选填写标题、副标题、作曲者;留空时读取谱面信息。
3. 选择画幅、帧率、谱面高度、3D 视角和颜色。
4. 点“生成预览”,等待解析、MuseScore 合成、Verovio 排版和 MIDI 对齐完成。
5. 在右侧 Remotion Player 中播放、拖动时间轴、实时调整左侧画面参数。
6. 点“导出 MP4”,服务端会先保存当前参数,再在本地渲染视频并给出下载链接。
> 首次生成需要先跑完一次流水线;之后调整视觉参数都是即时预览。修改谱面/音频/标题文字本身需要重新生成,标题、副标题、作曲者的非空修改也会在导出前写入。
### 开发时改渲染代码
服务端第一次导出时会把 Remotion 项目打包一次,并缓存在内存里。缓存带源码指纹:改动 `src/remotion/`、`src/shared/` 或 `public/` 后再次导出会自动重新打包(日志会打印 `[render] sources changed, rebuilding the Remotion bundle`),不需要重启服务,也不会出现“预览是新的、导出还是旧画面”。
## 3D 视角
“3D 视角”把纸面、谱面、纸面光和 Canvas 小球放进同一个 CSS 3D 变换平面,因此小球和符头会一起倾斜、透视,不会错位。
- **俯仰角**:数值越大,谱面上方越向后倒。
- **滚转角**:负值让谱面右侧抬高,形成参考视频里的斜线。
- **偏航角**:左右转向;过大时透视会明显压缩。
- **透视距离**:越小透视越强,越大越接近正交投影。
- **视角缩放**:倾斜后用于补足画面;谱面被裁切或留白时优先调它。
## API
| 方法 | 路径 | 说明 |
| --- | --- | --- |
| `GET` | `/api/health` | MuseScore / 浏览器 / FFmpeg 状态 |
| `GET` | `/api/jobs` | 最近任务 |
| `POST` | `/api/jobs` | 创建任务,`multipart/form-data`:`score`、可选 `audio`、`settings`(JSON)、`title`、`subtitle`、`composer` |
| `GET` | `/api/jobs/:id` | 任务状态与预览数据 |
| `PATCH` | `/api/jobs/:id/settings` | 保存实时预览参数,并重新计算滚动关键帧 |
| `POST` | `/api/jobs/:id/render` | 加入渲染队列 |
| `GET` | `/api/jobs/:id/video` | 下载 MP4 |
## 验证脚本
```powershell
npx tsx scripts/check-demo.ts
```
会对内置示例跑解析、Verovio 单行排版、MuseScore 导出、MIDI 映射,并输出 `data/check/score.json`。也可以直接用 Remotion CLI 验证单帧:
```powershell
# 用某个已完成任务的完整设置生成单帧 props(含按当前画幅重算的滚动关键帧)
npx tsx scripts/props-from-job.ts <jobId> data/check/p-job.json
npx remotion still src/remotion/index.ts MusicScroll data/check/frame.png `
--frame=300 --props=data/check/p-job.json `
--browser-executable="C:\Program Files\Google\Chrome\Application\chrome.exe"
```
`<jobId>` 是 `data/jobs/` 下的目录名,`props-from-job.ts` 会读取该任务的 `score.json` 与 `job.json`,因此导出的单帧和网页里看到的一致。
## 已知限制
- 反复、ending、D.C./D.S. 等跳转按谱面结构做近似展开;复杂跳转建议先在 MuseScore 中展开后导出 MusicXML。
- 多声部/多谱表会渲染成同一条 system 上的多组五线谱,不是多行总谱。
- 歌词、和弦符号、指法、tab 等会随 Verovio SVG 显示,但不参与小球坐标。
- 上传音频时,动画时间仍来自 MIDI/谱面;录音速度与谱面差异过大时会渐进漂移,可用“音频偏移”做整体校准。
- 视频最长 20 分钟,上传文件最大 30MB。
- 渲染是 CPU 本地渲染,长曲会比较慢;可降低 fps 或谱面分辨率来加速。
## 许可与归属
本项目代码以 MIT 许可发布。
视觉与运动设计参考 **Dancing Notes**,Copyright (c) 2026 言说新事 (SyanChen7),MIT License。原版权声明与许可全文见 [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md)。
使用的第三方组件包括 Remotion、Verovio、MuseScore、React、Vite、zod 等,请分别遵守其许可证。Remotion 的商用许可要求请以官方说明为准。