Clarify the real data contract before scaling external datasets
Constraint: Must document code-true behavior for training crops, retrieval windows, GPU support, and FMA reuse before more dataset automation lands Rejected: Leave docs at high-level abstractions only | Would hide 5s-vs-8s and CPU-vs-GPU operational realities Confidence: high Scope-risk: narrow Directive: Keep future dataset docs aligned with actual code paths and artifact timestamps, not intended architecture alone Tested: Source review of dataset.py manifest_tools.py external_adapters.py utils/audio.py ecapa_embedder.py train.py; live FMA smoke progress observed through epoch completion Not-tested: Markdown renderer-specific Mermaid rendering and every relative link target in external viewers
Showing
3 changed files
with
326 additions
and
500 deletions
| ... | @@ -2,6 +2,34 @@ | ... | @@ -2,6 +2,34 @@ |
| 2 | 2 | ||
| 3 | ## 2026-06-02 | 3 | ## 2026-06-02 |
| 4 | 4 | ||
| 5 | |||
| 6 | ### Stage: 补齐训练数据、重叠窗口、GPU 与 FMA 数据处理文档 | ||
| 7 | |||
| 8 | 完成项: | ||
| 9 | - 重写并压缩 `dataset-spec.md`,补齐训练切片、检索重叠滑窗、manifest 生成差异 | ||
| 10 | - 扩展 `training-data-and-pgvector-guide.md`,补齐 FMA / MTG / 自有数据接入、目录规范、脚本职责、GPU 加速说明 | ||
| 11 | - 明确记录当前真实代码事实:训练端 5s 随机裁剪、检索端 5s/2.5s 重叠滑窗、外部 manifest 默认 8s query | ||
| 12 | - 记录当前 smoke 现状:`smoke-local` 仍固定 CPU,真实 FMA smoke 正在运行 | ||
| 13 | - 记录当前实验产物一致性风险:旧的 `fma_reports_smoke/config.json` 与最新 manifests 时间戳不一致,需后续统一配置治理 | ||
| 14 | |||
| 15 | 验证结果: | ||
| 16 | - 源码复核: | ||
| 17 | - `src/data/dataset.py`:训练端随机 5s crop | ||
| 18 | - `src/utils/audio.py` / `src/engines/ecapa_embedder.py`:5s window + 2.5s stride | ||
| 19 | - `src/data/manifest_tools.py`:每首歌 1 个随机 query,默认 `8.0s` | ||
| 20 | - `src/data/external_adapters.py`:`smoke-local` 当前硬编码 `--device cpu` | ||
| 21 | - `train.py`:支持 `--device auto`,CUDA 路径支持 mixed precision | ||
| 22 | - 真实运行状态: | ||
| 23 | - FMA smoke 进程仍在运行 | ||
| 24 | - 最新可见进度约 `82%` epoch 1 | ||
| 25 | - 文档链接验证:主文档仍使用相对路径链接到仓库文件与同组文档 | ||
| 26 | |||
| 27 | 结论: | ||
| 28 | - 当前项目关于训练数据格式、3 分钟 mp3 切片、是否重叠窗口、GPU 是否可显著加速、FMA 与开放数据如何复用流程,已形成可交接文档 | ||
| 29 | - 后续可继续沿两条线推进: | ||
| 30 | 1. 让 `smoke-local` 支持 GPU | ||
| 31 | 2. 增加 overlap query manifest 生成能力 | ||
| 32 | |||
| 5 | ### Stage: 真实 FMA 本地数据门槛打开并进入 smoke 训练 | 33 | ### Stage: 真实 FMA 本地数据门槛打开并进入 smoke 训练 |
| 6 | 34 | ||
| 7 | 完成项: | 35 | 完成项: | ... | ... |
| 1 | # ACR Dataset / 输入输出规范 | 1 | # ACR Dataset / 输入输出规范 |
| 2 | 2 | ||
| 3 | > 更新:2026-06-02 | 3 | > 更新:2026-06-02 |
| 4 | > 关联文档:[训练数据与 pgvector 指南](./training-data-and-pgvector-guide.md) · [开放数据工作流](./open-dataset-workflow.md) · [数据来源与接入](./dataset-sources-and-licensing.md) | ||
| 4 | 5 | ||
| 5 | ## 一页结论 | 6 | ## 一页结论 |
| 6 | 7 | ||
| 7 | - 数据规范的核心不是文件格式,而是**分离 catalog 与 query** | 8 | 当前项目的数据规范,最重要的是 4 件事: |
| 8 | - 外部数据集进入系统前必须先转换成统一 manifest | 9 | |
| 9 | - 当前系统的标准输入是: | 10 | 1. **训练输入不是“整首 mp3 文件”本身,而是 manifest 驱动的 reference + query 样本体系**。 |
| 10 | - **16k mono audio** | 11 | 2. **训练和检索的切窗策略不同**:训练端当前是**随机裁剪 5s**,检索/建索引端当前是**5s 窗口 + 2.5s stride 的 50% 重叠滑窗**。 |
| 11 | - **128 Mel** | 12 | 3. **外部开源数据集进入项目时,必须先转换成统一 manifest**,再做训练、评测、索引和 pgvector 入库。 |
| 12 | - **window-level retrieval** | 13 | 4. **当前音乐任务输入层已切换到 128 维 Mel 频谱**,并开启 band-split 方向;FMA 这类真实数据建议优先使用 GPU。 |
| 13 | - 当前系统的标准输出是: | ||
| 14 | - top-k candidates | ||
| 15 | - confidence | ||
| 16 | - reject/accept | ||
| 17 | - metadata | ||
| 18 | 14 | ||
| 19 | --- | 15 | --- |
| 20 | 16 | ||
| ... | @@ -22,13 +18,14 @@ | ... | @@ -22,13 +18,14 @@ |
| 22 | 18 | ||
| 23 | ```mermaid | 19 | ```mermaid |
| 24 | flowchart LR | 20 | flowchart LR |
| 25 | A[External / Synthetic Audio] --> B[Manifest Conversion] | 21 | A[Raw Audio\nFMA / MTG / 自有 BGM / 录音] --> B[Manifest Conversion] |
| 26 | B --> C[Catalog Manifest] | 22 | B --> C[Catalog Manifest\nreference] |
| 27 | B --> D[Query Manifest] | 23 | B --> D[Train/Test Manifest\nquery] |
| 28 | C --> E[Reference Index Build] | 24 | C --> E[Reference Index Build\nsliding windows] |
| 29 | D --> F[Training / Evaluation Queries] | 25 | D --> F[Training / Evaluation] |
| 30 | E --> G[Hybrid Retrieval] | 26 | E --> G[Hybrid Retrieval] |
| 31 | F --> G | 27 | F --> G |
| 28 | G --> H[pgvector / report / service] | ||
| 32 | ``` | 29 | ``` |
| 33 | 30 | ||
| 34 | --- | 31 | --- |
| ... | @@ -58,6 +55,7 @@ flowchart TD | ... | @@ -58,6 +55,7 @@ flowchart TD |
| 58 | Q --> Q2[audio_path] | 55 | Q --> Q2[audio_path] |
| 59 | Q --> Q3[duration] | 56 | Q --> Q3[duration] |
| 60 | Q --> Q4[type=clean/augmented/confused/humming_like] | 57 | Q --> Q4[type=clean/augmented/confused/humming_like] |
| 58 | Q --> Q5[offset] | ||
| 61 | ``` | 59 | ``` |
| 62 | 60 | ||
| 63 | --- | 61 | --- |
| ... | @@ -66,14 +64,60 @@ flowchart TD | ... | @@ -66,14 +64,60 @@ flowchart TD |
| 66 | 64 | ||
| 67 | | 环节 | 输入 | 输出 | | 65 | | 环节 | 输入 | 输出 | |
| 68 | |---|---|---| | 66 | |---|---|---| |
| 69 | | 训练 | query segments | embeddings + logits | | 67 | | 训练 | query segments + references | embeddings + logits | |
| 70 | | 索引 | catalog references | chromaprint index + embedding index | | 68 | | 索引 | catalog references | chromaprint index + embedding index | |
| 71 | | 识别 | query audio | ranked candidates | | 69 | | 识别 | query audio | ranked candidates | |
| 72 | | 评测 | query manifest + catalog | top1/top5/hard-case report | | 70 | | 评测 | query manifest + catalog | top1/top5/hard-case report | |
| 71 | | 入库 | manifest + embedding | pgvector-ready JSON / SQL rows | | ||
| 73 | 72 | ||
| 74 | --- | 73 | --- |
| 75 | 74 | ||
| 76 | ## 4.1 Hard-case 训练信号图 | 75 | ## 5. 3 分钟 mp3 到 5–8 秒片段:当前到底怎么切 |
| 76 | |||
| 77 | ## 5.1 当前代码里有 **3 种不同切法** | ||
| 78 | |||
| 79 | ```mermaid | ||
| 80 | flowchart TD | ||
| 81 | A[3min mp3] --> B[训练 Dataset] | ||
| 82 | A --> C[检索 / 建索引] | ||
| 83 | A --> D[外部数据集 manifest 生成] | ||
| 84 | |||
| 85 | B --> B1[随机裁 1 个 5s clip] | ||
| 86 | C --> C1[5s 窗 + 2.5s stride]\n50% overlap | ||
| 87 | D --> D1[每首歌随机采 1 个 query]\n默认 8s | ||
| 88 | ``` | ||
| 89 | |||
| 90 | | 场景 | 当前实现 | 是否重叠 | 代码位置 | | ||
| 91 | |---|---|---:|---| | ||
| 92 | | 训练 `SongPairDataset` | 每次采样随机取一个 5s clip | 否,**不是固定滑窗** | [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py) | | ||
| 93 | | 检索 / embedding / 建索引 | `window_sec=5.0`, `stride_sec=2.5` | 是,**50% overlap** | [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py), [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py) | | ||
| 94 | | `audio-dir-to-splits` | 每首歌只生成 1 个随机 query | 否 | [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py) | | ||
| 95 | |||
| 96 | ### 直接回答你的问题 | ||
| 97 | |||
| 98 | - **有重叠窗口,但只在检索/索引链路里有。** | ||
| 99 | - **当前训练主链路没有对 3 分钟 mp3 预展开成“全量重叠切片集”**,而是每次 batch 动态随机裁一个 5s 片段。 | ||
| 100 | - **当前外部数据集 manifest 生成器也没有自动为每首歌生成多个重叠 query。** | ||
| 101 | |||
| 102 | --- | ||
| 103 | |||
| 104 | ## 5.2 为什么这样设计 | ||
| 105 | |||
| 106 | | 设计点 | 当前好处 | 当前限制 | | ||
| 107 | |---|---|---| | ||
| 108 | | 训练随机裁剪 | 节省存储,不必预生成几万切片 | 同一 epoch 暴露到的时间区域有限 | | ||
| 109 | | 检索重叠滑窗 | 更接近真实 ACR reference coverage | 索引体积更大 | | ||
| 110 | | 外部数据一首歌一个 query | smoke 更轻、更快验证 | 训练/评测覆盖不充分 | | ||
| 111 | |||
| 112 | 推荐理解方式: | ||
| 113 | - **训练端**更像“随机数据增强采样器” | ||
| 114 | - **检索端**更像“为了召回覆盖做滑窗索引” | ||
| 115 | |||
| 116 | --- | ||
| 117 | |||
| 118 | ## 6. 当前训练信号与 hard-case 规则 | ||
| 119 | |||
| 120 | ## 6.1 Hard-case 训练信号图 | ||
| 77 | 121 | ||
| 78 | ```mermaid | 122 | ```mermaid |
| 79 | flowchart LR | 123 | flowchart LR |
| ... | @@ -97,7 +141,7 @@ flowchart LR | ... | @@ -97,7 +141,7 @@ flowchart LR |
| 97 | 141 | ||
| 98 | --- | 142 | --- |
| 99 | 143 | ||
| 100 | ## 4.2 检索融合参数图 | 144 | ## 6.2 检索融合参数图 |
| 101 | 145 | ||
| 102 | ```mermaid | 146 | ```mermaid |
| 103 | flowchart LR | 147 | flowchart LR |
| ... | @@ -112,14 +156,9 @@ flowchart LR | ... | @@ -112,14 +156,9 @@ flowchart LR |
| 112 | | `ecapa_weight` | 0.50 | 0.55 | 提高 embedding 检索主导 | | 156 | | `ecapa_weight` | 0.50 | 0.55 | 提高 embedding 检索主导 | |
| 113 | | `melody_weight` | 0.25 | 0.25 | 暂时保持不变 | | 157 | | `melody_weight` | 0.25 | 0.25 | 暂时保持不变 | |
| 114 | 158 | ||
| 115 | 说明: | ||
| 116 | - 当前仓库已经支持在 `evaluate.py` 中直接传入融合参数 | ||
| 117 | - 对个人使用场景,推荐把一部分开源数据集固定成 **fusion tuning eval set** | ||
| 118 | - 这样训练、检索、调参可以分离,而不是每次都重训 | ||
| 119 | |||
| 120 | --- | 159 | --- |
| 121 | 160 | ||
| 122 | ## 4.3 开源数据集 train/eval 切分图 | 161 | ## 7. 开源数据集 train/eval 切分图 |
| 123 | 162 | ||
| 124 | ```mermaid | 163 | ```mermaid |
| 125 | flowchart LR | 164 | flowchart LR |
| ... | @@ -137,7 +176,7 @@ flowchart LR | ... | @@ -137,7 +176,7 @@ flowchart LR |
| 137 | | [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json) | 评估查询 | query + references | | 176 | | [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json) | 评估查询 | query + references | |
| 138 | | [val.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/val.json) | 预留验证集 | 当前可为空 | | 177 | | [val.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/val.json) | 预留验证集 | 当前可为空 | |
| 139 | 178 | ||
| 140 | 推荐法则(个人使用): | 179 | 推荐法则: |
| 141 | - FMA / MTG-Jamendo 可优先用于真实 train/eval baseline | 180 | - FMA / MTG-Jamendo 可优先用于真实 train/eval baseline |
| 142 | - 至少固定一部分曲目只进 [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json),不要同时参与训练 | 181 | - 至少固定一部分曲目只进 [test.json](../acr-engine/data/external_ingested/demo_via_adapter/fma/manifests/test.json),不要同时参与训练 |
| 143 | - 小数据集也要保证至少 1 个 train query + 1 个 test query | 182 | - 小数据集也要保证至少 1 个 train query + 1 个 test query |
| ... | @@ -148,38 +187,48 @@ CLI 入口: | ... | @@ -148,38 +187,48 @@ CLI 入口: |
| 148 | - 导入前预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-local <dataset> <input_dir>` | 187 | - 导入前预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-local <dataset> <input_dir>` |
| 149 | - 多目录批量预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-batch fma=<dir> mtg_jamendo=<dir> ...` | 188 | - 多目录批量预检查:[acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-batch fma=<dir> mtg_jamendo=<dir> ...` |
| 150 | 189 | ||
| 151 | ## 5. 文字说明 | 190 | --- |
| 191 | |||
| 192 | ## 8. 当前项目输入层规范 | ||
| 193 | |||
| 194 | | 项目 | 当前值/建议 | 说明 | | ||
| 195 | |---|---|---| | ||
| 196 | | 采样率 | `16kHz` | 统一音频读取口径 | | ||
| 197 | | 声道 | `mono` | 当前链路按单声道处理 | | ||
| 198 | | 频谱 | `128 Mel` | 音乐任务输入层 | | ||
| 199 | | 训练 clip | `5s` | 当前训练代码事实 | | ||
| 200 | | 外部 query manifest 默认 | `8s` | 当前 `prepare-local/smoke-local` 默认 | | ||
| 201 | | Band split | `enabled` | 已纳入当前模型配置 | | ||
| 152 | 202 | ||
| 153 | ### 5.1 为什么必须分离 catalog 和 query | 203 | --- |
| 154 | 早期原型容易把 train split 直接当搜索库,这会让评测和真实服务语义混乱。工业化系统必须把: | ||
| 155 | - “可搜索曲库” | ||
| 156 | - “训练/评测 query” | ||
| 157 | 204 | ||
| 158 | 明确分离。 | 205 | ## 9. 文字说明 |
| 159 | 206 | ||
| 160 | ### 5.2 为什么输入层是 128 Mel | 207 | ### 9.1 为什么必须分离 catalog 和 query |
| 161 | 音乐任务需要更丰富的频带表达,128 Mel 更适合 band-split 和音乐 timbre/harmony 建模。 | 208 | 工业化系统里,“可搜索曲库”和“训练/评测 query”必须分离,否则评测会和真实服务语义混在一起。 |
| 162 | 209 | ||
| 163 | ### 5.3 query 类型为什么要显式标注 | 210 | ### 9.2 为什么输入层是 128 Mel |
| 164 | `clean / augmented / confused / humming_like` 是评测与训练策略的重要条件,不应只放在隐式文件名里。 | 211 | 音乐任务需要更丰富的频带表达;128 Mel 比 40 维 MFCC 更适合 timbre/harmony/band-split 建模。 |
| 165 | 212 | ||
| 166 | ### 5.4 为什么 hard-case 权重必须做到 sample-level | 213 | ### 9.3 为什么 query 类型必须显式标注 |
| 167 | 如果只在 batch 级取平均权重,`confused` 这种少量但高风险样本会被正常样本稀释。当前版本已经改成 **sample-level weighted SupCon + sample-level weighted CE**,从而让单个困难片段在损失中真实“被看见”。 | 214 | `clean / augmented / confused / humming_like` 不只是标签名,而是训练权重、评测 bucket、难例治理的入口。 |
| 168 | 215 | ||
| 169 | ### 5.5 当前经验结论 | 216 | ### 9.4 关于 5s vs 8s 的一个当前注意点 |
| 217 | 当前仓库有两组时长: | ||
| 218 | - **训练 Dataset 与默认模型训练:5s** | ||
| 219 | - **开放数据 manifest/query 默认:8s** | ||
| 220 | |||
| 221 | 这不是同一层配置,因此当前文档和实验报告里必须明确区分;不要把它们误认为一套统一参数。 | ||
| 222 | |||
| 223 | ### 9.5 当前经验结论 | ||
| 170 | - 简单过采样会导致整体退化 | 224 | - 简单过采样会导致整体退化 |
| 171 | - type-aware weighting 能提升一部分 hard case | 225 | - type-aware weighting 能提升一部分 hard case |
| 172 | - confused 类需要更高权重,但过强偏置会回伤 `humming_like` | 226 | - confused 类需要更高权重,但过强偏置会回伤 `humming_like` |
| 173 | - residual confused failure 往往集中在 `intro` 片段,因此 `segment_type` 不只是元数据,还应参与后续难负例设计 | 227 | - residual confused failure 往往集中在 `intro` 片段,因此 `segment_type` 不只是元数据,还应参与后续难负例设计 |
| 174 | - 因此 dataset 规范中必须保留 `type` 字段,后续才能继续做: | ||
| 175 | - confusion-aware negative mining | ||
| 176 | - melody-aware reranking | ||
| 177 | - 双支路 hard-case curriculum | ||
| 178 | - segment-type-aware hard negatives | ||
| 179 | 228 | ||
| 180 | --- | 229 | --- |
| 181 | 230 | ||
| 182 | ## 6. 细节附录 | 231 | ## 10. 细节附录 |
| 183 | 232 | ||
| 184 | ### Reference 示例 | 233 | ### Reference 示例 |
| 185 | ```json | 234 | ```json |
| ... | @@ -203,6 +252,5 @@ CLI 入口: | ... | @@ -203,6 +252,5 @@ CLI 入口: |
| 203 | } | 252 | } |
| 204 | ``` | 253 | ``` |
| 205 | 254 | ||
| 206 | |||
| 207 | ## Sources | 255 | ## Sources |
| 208 | - See [references-and-sources.md](./references-and-sources.md) for the current source map. | 256 | - 当前代码事实来自 [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py), [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py), [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py), [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py), [acr-engine/train.py](../acr-engine/train.py) | ... | ... |
| ... | @@ -5,10 +5,13 @@ | ... | @@ -5,10 +5,13 @@ |
| 5 | 5 | ||
| 6 | ## 一页结论 | 6 | ## 一页结论 |
| 7 | 7 | ||
| 8 | 你这次问的两个核心问题,可以先压缩成一句话: | 8 | 围绕你最新问的几个问题,可以压缩成 5 句话: |
| 9 | 9 | ||
| 10 | 1. **当前训练输入的最小单位是“带 `song_id` 标签的音频片段 + reference 全曲/长片段 + manifest”**,不是只扔一堆音频文件进去。 | 10 | 1. **当前训练输入的最小单位是“带 `song_id` 的 query 样本 + reference 资产 + manifest”**,不是直接把 3 分钟 mp3 整批扔进模型。 |
| 11 | 2. **如果后面要接入 `pgvector`,应先把音频转成标准资产和 manifest,再从 manifest 生成 embedding 与结构化元数据,不要直接把原始音频塞进数据库。** | 11 | 2. **3 分钟 mp3 当前在训练端通常不是预切全量重叠窗口,而是运行时随机裁 5s;检索端才是重叠滑窗。** |
| 12 | 3. **如果有 GPU,FMA 这类真实数据训练会明显加速,当前 `train.py` 已支持 `auto/cuda`,但 `smoke-local` 现在仍硬编码为 CPU。** | ||
| 13 | 4. **FMA、MTG-Jamendo、自有 BGM/录音都应先变成统一 manifest,再做训练、评测和 pgvector 入库。** | ||
| 14 | 5. **后续你们要扩自己的数据集时,最重要的不是文件后缀,而是 `song_id / type / offset / source_dataset / split` 这些结构化字段。** | ||
| 12 | 15 | ||
| 13 | --- | 16 | --- |
| 14 | 17 | ||
| ... | @@ -16,7 +19,7 @@ | ... | @@ -16,7 +19,7 @@ |
| 16 | 19 | ||
| 17 | ```mermaid | 20 | ```mermaid |
| 18 | flowchart LR | 21 | flowchart LR |
| 19 | A[原始素材\nBGM / 歌曲 / 录音] --> B[标准化音频资产\n16k / mono / wav优先] | 22 | A[原始素材\nBGM / 歌曲 / 录音 / FMA] --> B[标准化音频资产\n16k / mono] |
| 20 | B --> C[Reference 全曲/长片段] | 23 | B --> C[Reference 全曲/长片段] |
| 21 | B --> D[Query 短片段\n5s / 8s] | 24 | B --> D[Query 短片段\n5s / 8s] |
| 22 | C --> E[Manifest\ncatalog/train/val/test] | 25 | C --> E[Manifest\ncatalog/train/val/test] |
| ... | @@ -28,563 +31,310 @@ flowchart LR | ... | @@ -28,563 +31,310 @@ flowchart LR |
| 28 | 31 | ||
| 29 | --- | 32 | --- |
| 30 | 33 | ||
| 31 | ## 2. 先回答你的问题 1:当前训练数据和输入数据应该是什么格式 | 34 | ## 2. 当前训练数据到底是什么格式 |
| 32 | 35 | ||
| 33 | ## 2.1 当前项目真正需要的输入,不只是音频文件 | 36 | ## 2.1 不是“一个 mp3 文件”,而是三层对象 |
| 34 | |||
| 35 | 当前项目训练/评测链路需要 3 类输入: | ||
| 36 | 37 | ||
| 37 | | 层 | 现在需要什么 | 作用 | | 38 | | 层 | 现在需要什么 | 作用 | |
| 38 | |---|---|---| | 39 | |---|---|---| |
| 39 | | 音频资产层 | `.wav/.mp3/.flac/.ogg` | 真正被读取和切片的内容 | | 40 | | 音频资产层 | `.wav/.mp3/.flac/.ogg` | 真正被读取的内容 | |
| 40 | | 标注层 | `song_id`、`type`、`offset` 等 | 告诉系统“这是谁、是什么角色” | | 41 | | 标注层 | `song_id`、`type`、`offset`、`source_dataset` | 告诉系统“是谁、是哪种样本” | |
| 41 | | manifest 层 | `catalog.json` / `train.json` / `test.json` / `val.json` | 驱动训练、建库、评测 | | 42 | | manifest 层 | `catalog.json` / `train.json` / `test.json` / `val.json` | 驱动训练、建库、评测 | |
| 42 | 43 | ||
| 43 | 也就是说,**最小可训练单元**不是“一个文件”,而是: | 44 | 也就是说,**最小可训练单元**不是“一个文件”,而是: |
| 44 | 45 | - 一个 `audio_path` | |
| 45 | - 一个音频文件路径 `audio_path` | 46 | - 一个 `song_id` |
| 46 | - 一个主标签 `song_id` | 47 | - 一个 `type` |
| 47 | - 一个角色标签 `type` | 48 | - 一个 `duration` |
| 48 | - 一个时长 `duration` | ||
| 49 | - 如为 query,通常还应有 `offset` | 49 | - 如为 query,通常还应有 `offset` |
| 50 | 50 | ||
| 51 | --- | 51 | --- |
| 52 | 52 | ||
| 53 | ## 2.2 当前代码侧的默认音频读取约束 | 53 | ## 2.2 当前推荐音频约束 |
| 54 | |||
| 55 | 从当前仓库实现看,数据读取是按以下原则处理的: | ||
| 56 | 54 | ||
| 57 | | 项目 | 当前推荐值 | 说明 | | 55 | | 项目 | 当前推荐值 | 说明 | |
| 58 | |---|---|---| | 56 | |---|---|---| |
| 59 | | 采样率 | `16000 Hz` | 读取时会统一到 16k | | 57 | | 采样率 | `16000 Hz` | 读取时统一到 16k | |
| 60 | | 声道 | `mono` | 当前管线按单声道处理 | | 58 | | 声道 | `mono` | 当前管线按单声道 | |
| 61 | | query 长度 | `5s` 或 `8s` | 训练常用 5s,开放数据 smoke 常用 8s | | 59 | | 训练片段长度 | `5s` | 训练数据集代码事实 | |
| 62 | | reference 长度 | 尽量完整曲目 | 用于建 reference 索引 | | 60 | | 外部 query 默认长度 | `8s` | `prepare-local/smoke-local` 默认 | |
| 63 | | 频谱输入 | `128 维 Mel 频谱` | 你要求从 40 维 MFCC 切到音乐任务更合适的 128 Mel | | 61 | | 频谱输入 | `128 维 Mel` | 当前音乐任务输入层 | |
| 64 | 62 | | 模型配置 | `use_band_split=true` | 已集成频带分割模块 | | |
| 65 | ### 推荐的标准化目标 | ||
| 66 | |||
| 67 | ```text | ||
| 68 | 容器格式:WAV 优先(也可 MP3/FLAC/Ogg) | ||
| 69 | 采样率:16k | ||
| 70 | 声道:mono | ||
| 71 | 响度:建议归一化到稳定区间 | ||
| 72 | 切片长度:5s / 8s | ||
| 73 | ``` | ||
| 74 | |||
| 75 | --- | ||
| 76 | |||
| 77 | ## 2.3 训练数据中的两种核心角色 | ||
| 78 | |||
| 79 | ### A. Reference | ||
| 80 | |||
| 81 | Reference 是“曲库真身”,用于建索引、被检索、被匹配。 | ||
| 82 | |||
| 83 | 示例: | ||
| 84 | |||
| 85 | ```json | ||
| 86 | { | ||
| 87 | "song_id": "song_0001", | ||
| 88 | "audio_path": "audio/song_0001.wav", | ||
| 89 | "duration": 183.4, | ||
| 90 | "type": "reference", | ||
| 91 | "source_dataset": "internal_bgm" | ||
| 92 | } | ||
| 93 | ``` | ||
| 94 | |||
| 95 | 要求: | ||
| 96 | |||
| 97 | - 一首歌至少 1 条 reference | ||
| 98 | - 最好是完整曲目或较长主版本 | ||
| 99 | - 不建议把手机录音、环境录音直接当主 reference | ||
| 100 | |||
| 101 | ### B. Query | ||
| 102 | |||
| 103 | Query 是“未来线上用户会扔给你的东西”,用于训练和评测识别能力。 | ||
| 104 | |||
| 105 | 示例: | ||
| 106 | |||
| 107 | ```json | ||
| 108 | { | ||
| 109 | "song_id": "song_0001", | ||
| 110 | "audio_path": "audio/song_0001_query_03.wav", | ||
| 111 | "duration": 5.0, | ||
| 112 | "type": "clean", | ||
| 113 | "offset": 63.2, | ||
| 114 | "segment_type": "mid", | ||
| 115 | "source_dataset": "internal_bgm" | ||
| 116 | } | ||
| 117 | ``` | ||
| 118 | |||
| 119 | 要求: | ||
| 120 | |||
| 121 | - 来自对应 `song_id` 的 reference 曲目 | ||
| 122 | - 时长稳定 | ||
| 123 | - offset 可追溯 | ||
| 124 | - query/reference 使用同一个 `song_id` | ||
| 125 | |||
| 126 | --- | ||
| 127 | |||
| 128 | ## 2.4 Query 里具体应该是什么内容 | ||
| 129 | |||
| 130 | ### 推荐内容类型 | ||
| 131 | |||
| 132 | | type | 内容 | 用途 | | ||
| 133 | |---|---|---| | ||
| 134 | | `clean` | 原曲直接切片 | 基础训练/评测 | | ||
| 135 | | `augmented` | 加噪、混响、压缩、EQ 后切片 | 提升鲁棒性 | | ||
| 136 | | `confused` | 容易与别的歌混淆的难例片段 | 拉开区分度 | | ||
| 137 | | `humming_like` | 旋律近似、配器弱、手机录音风格片段 | 强化近旋律检索 | | ||
| 138 | | `reference` | 全曲或长片段 | 建库索引 | | ||
| 139 | |||
| 140 | ### 不推荐直接混进训练主集的内容 | ||
| 141 | |||
| 142 | - 完全未知来源、无法映射 `song_id` 的录音 | ||
| 143 | - 严重截断、纯噪声、无有效音乐主体的片段 | ||
| 144 | - 多首歌混在一起、没有主目标标签的片段 | ||
| 145 | |||
| 146 | 这些更适合先放到: | ||
| 147 | |||
| 148 | - 待清洗池 | ||
| 149 | - 难例池 | ||
| 150 | - 线上回流池 | ||
| 151 | 63 | ||
| 152 | --- | 64 | --- |
| 153 | 65 | ||
| 154 | ## 2.5 manifest 应该长什么样 | 66 | ## 3. 3 分钟 mp3 怎么进入训练 |
| 155 | |||
| 156 | ### 最低字段要求 | ||
| 157 | 67 | ||
| 158 | | 字段 | 必需 | 说明 | | 68 | ## 3.1 当前切片策略图 |
| 159 | |---|---|---| | ||
| 160 | | `song_id` | 是 | 同一首歌的统一主标签 | | ||
| 161 | | `audio_path` | 是 | 相对路径,建议相对 manifest 根 | | ||
| 162 | | `duration` | 是 | 秒数 | | ||
| 163 | | `type` | 是 | `reference/clean/augmented/confused/...` | | ||
| 164 | | `offset` | query 建议有 | query 在 reference 中的起始位置 | | ||
| 165 | | `segment_type` | 建议 | `intro/mid/outro/external_query` | | ||
| 166 | | `source_dataset` | 建议 | 数据来源,例如 `fma_small` | | ||
| 167 | |||
| 168 | ### 当前项目 manifest 文件 | ||
| 169 | |||
| 170 | | 文件 | 含义 | | ||
| 171 | |---|---| | ||
| 172 | | `catalog.json` | 全部样本总表,尤其包含 reference | | ||
| 173 | | `train.json` | 训练 query 样本 | | ||
| 174 | | `val.json` | 验证集 query 样本 | | ||
| 175 | | `test.json` | 测试集 query 样本 | | ||
| 176 | |||
| 177 | --- | ||
| 178 | |||
| 179 | ## 3. 如果后面要保存到 pgvector,现在应该怎么处理 | ||
| 180 | |||
| 181 | ## 3.1 正确分层 | ||
| 182 | |||
| 183 | **不要**: | ||
| 184 | - 原始音频直接进 PostgreSQL 大表 | ||
| 185 | - 训练前再从数据库反向拼装所有资产 | ||
| 186 | |||
| 187 | **推荐**: | ||
| 188 | |||
| 189 | | 内容 | 存储位置 | | ||
| 190 | |---|---| | ||
| 191 | | 原始音频 / 标准音频 | 文件系统 / NAS / 对象存储 | | ||
| 192 | | manifest / 结构化元数据 | PostgreSQL 普通表 | | ||
| 193 | | 向量 embedding | `pgvector` 列 | | ||
| 194 | | 检索索引参数 | PostgreSQL 索引 / 服务配置 | | ||
| 195 | |||
| 196 | --- | ||
| 197 | |||
| 198 | ## 3.2 pgvector 推荐数据模型 | ||
| 199 | 69 | ||
| 200 | ```mermaid | 70 | ```mermaid |
| 201 | flowchart TD | 71 | flowchart TD |
| 202 | A[songs] --> B[references] | 72 | A[3min 原始 mp3] --> B[训练 Dataset] |
| 203 | A --> C[segments] | 73 | A --> C[建索引 / 检索] |
| 204 | B --> D[reference_embeddings] | 74 | A --> D[外部数据集 query 生成] |
| 205 | C --> E[query_embeddings] | ||
| 206 | ``` | ||
| 207 | |||
| 208 | 当前仓库已经有对应模板: | ||
| 209 | 75 | ||
| 210 | - [acr-engine/sql/pgvector_schema.sql](../acr-engine/sql/pgvector_schema.sql) | 76 | B --> B1[随机 offset] |
| 211 | - [acr-engine/scripts/export_manifest_to_pgvector_json.py](../acr-engine/scripts/export_manifest_to_pgvector_json.py) | 77 | B1 --> B2[取 5s clip] |
| 212 | - [acr-engine/scripts/pgvector_bulk_load_template.py](../acr-engine/scripts/pgvector_bulk_load_template.py) | ||
| 213 | 78 | ||
| 214 | ### 表职责说明 | 79 | C --> C1[5s window] |
| 215 | 80 | C1 --> C2[2.5s stride] | |
| 216 | | 表 | 存什么 | | 81 | C2 --> C3[50% overlap windows] |
| 217 | |---|---| | ||
| 218 | | `songs` | 歌曲主实体 | | ||
| 219 | | `references` | reference 音频资产 | | ||
| 220 | | `segments` | query 片段 | | ||
| 221 | | `reference_embeddings` | reference 的 embedding | | ||
| 222 | | `query_embeddings` | query 的 embedding | | ||
| 223 | |||
| 224 | --- | ||
| 225 | 82 | ||
| 226 | ## 3.3 现在就应该为 pgvector 预留的字段 | 83 | D --> D1[随机取 1 个 8s query] |
| 84 | ``` | ||
| 227 | 85 | ||
| 228 | 如果你们后面一定要落 PostgreSQL,建议从今天开始在 manifest / 数据处理中保留这些字段: | 86 | ## 3.2 直接回答“有没有重叠窗口” |
| 229 | 87 | ||
| 230 | | 字段 | 作用 | | 88 | | 链路 | 当前答案 | |
| 231 | |---|---| | 89 | |---|---| |
| 232 | | `song_id` | 主连接键 | | 90 | | 训练 | **没有固定重叠滑窗集**,而是随机裁剪 | |
| 233 | | `version_id` | 处理多版本/改编/短版 | | 91 | | 检索 / reference index | **有**,默认 50% overlap | |
| 234 | | `audio_path` / `audio_uri` | 回溯原始资产 | | 92 | | 开放数据 manifest 生成 | **没有**,默认每首歌只生成 1 个 query | |
| 235 | | `duration` | 切片合法性校验 | | ||
| 236 | | `offset` | query 对应 reference 位置 | | ||
| 237 | | `type` | 训练角色 / 查询角色 | | ||
| 238 | | `segment_type` | intro/mid/outro/external | | ||
| 239 | | `source_dataset` | 数据来源治理 | | ||
| 240 | | `license` | 商业化合规 | | ||
| 241 | | `split` | train/val/test | | ||
| 242 | | `model_version` | 向量版本控制 | | ||
| 243 | | `data_version` | 数据快照版本 | | ||
| 244 | |||
| 245 | ### 最重要的原则 | ||
| 246 | 93 | ||
| 247 | > `song_id` 要稳定,`version_id` 要可扩展,`audio_uri` 要可回溯,`model_version/data_version` 要可审计。 | 94 | 所以: |
| 95 | - 如果你担心 3 分钟内容只看一小段,担心是合理的; | ||
| 96 | - 当前训练覆盖靠多次 epoch 的随机采样累积,而不是一次性把整首歌切完; | ||
| 97 | - 如果后续要提高 recall/鲁棒性,可以继续加“多 query / overlap query manifest”这条增强线。 | ||
| 248 | 98 | ||
| 249 | --- | 99 | --- |
| 250 | 100 | ||
| 251 | ## 3.4 一个推荐的数据库入库流程 | 101 | ## 4. 如果有 BGM、音乐录音,应该怎么转成训练数据 |
| 102 | |||
| 103 | ## 4.1 推荐分工图 | ||
| 252 | 104 | ||
| 253 | ```mermaid | 105 | ```mermaid |
| 254 | flowchart LR | 106 | flowchart LR |
| 255 | A[音频目录] --> B[prepare-local] | 107 | A[自有 BGM / 歌曲母带] --> B[reference] |
| 256 | B --> C[manifests] | 108 | A --> C[clean query] |
| 257 | C --> D[导出 pgvector JSON] | 109 | A --> D[augmented query] |
| 258 | D --> E[批量导入 PostgreSQL] | 110 | A --> E[confused / humming_like] |
| 259 | E --> F[计算 embedding] | 111 | F[手机录音 / 环境录音] --> C |
| 260 | F --> G[写入 pgvector] | 112 | F --> E |
| 261 | ``` | 113 | ``` |
| 262 | 114 | ||
| 263 | 推荐执行顺序: | 115 | ## 4.2 转换规则表 |
| 264 | 116 | ||
| 265 | 1. 音频标准化 | 117 | | 原始素材 | 转成什么 | 标记建议 | |
| 266 | 2. 生成 manifest | 118 | |---|---|---| |
| 267 | 3. 用 manifest 导出结构化 JSON | 119 | | 完整 BGM / 完整歌曲 | `reference` | `type=reference` | |
| 268 | 4. 导入 PostgreSQL 元数据表 | 120 | | 原曲直接截 5s/8s | `clean` query | `type=clean` | |
| 269 | 5. 批量计算 embedding | 121 | | 加噪/压缩/混响/EQ 后片段 | `augmented` query | `type=augmented` | |
| 270 | 6. 写入 `pgvector` | 122 | | 容易和别的歌混淆的片段 | 难例 query | `type=confused` | |
| 271 | 7. 建 ANN 索引 | 123 | | 哼唱感、旋律弱、手机录音风格 | 难例 query | `type=humming_like` | |
| 272 | 124 | ||
| 273 | --- | 125 | --- |
| 274 | 126 | ||
| 275 | ## 4. 再回答你的问题 2:BGM、音乐录音怎么转成训练数据 | 127 | ## 4.3 你们自己扩数据集时的最小规则 |
| 276 | |||
| 277 | ## 4.1 场景 A:你有标准 BGM / 母带 / 完整成品 | ||
| 278 | 128 | ||
| 279 | 这是最适合做训练主集的情况。 | 129 | 1. **一首歌必须有稳定 `song_id`**。 |
| 130 | 2. **完整版本或主版本优先做 `reference`**。 | ||
| 131 | 3. **query 一定要能回溯到 reference 的时间位置**,因此最好保留 `offset`。 | ||
| 132 | 4. **不同来源必须保留 `source_dataset`**。 | ||
| 133 | 5. **训练、验证、测试必须保留 `split` 语义**,不要后面再靠文件夹猜。 | ||
| 280 | 134 | ||
| 281 | ### 转化规则 | 135 | --- |
| 282 | 136 | ||
| 283 | | 输入资产 | 转成什么 | | 137 | ## 5. FMA / MTG / 自有数据的目录规范 |
| 284 | |---|---| | ||
| 285 | | 完整曲目 | `reference` | | ||
| 286 | | 从完整曲目切的 5s/8s 片段 | `clean` query | | ||
| 287 | | 加噪/压缩/混响后的派生片段 | `augmented` query | | ||
| 288 | | 易混淆段落 | `confused` query | | ||
| 289 | 138 | ||
| 290 | ### 最小流程 | 139 | ## 5.1 推荐目录图 |
| 291 | 140 | ||
| 292 | ```mermaid | 141 | ```mermaid |
| 293 | flowchart TD | 142 | flowchart TD |
| 294 | A[完整 BGM] --> B[标准化] | 143 | A[acr-engine/data/raw] --> B[fma_small_audio] |
| 295 | B --> C[reference] | 144 | A --> C[mtg_jamendo_audio] |
| 296 | B --> D[切 query 片段] | 145 | A --> D[my_bgm_audio] |
| 297 | D --> E[clean] | ||
| 298 | D --> F[augmented] | ||
| 299 | D --> G[confused] | ||
| 300 | C --> H[manifest] | ||
| 301 | E --> H | ||
| 302 | F --> H | ||
| 303 | G --> H | ||
| 304 | ``` | ||
| 305 | |||
| 306 | ### 标注原则 | ||
| 307 | 146 | ||
| 308 | - 一首歌一个稳定 `song_id` | 147 | E[acr-engine/data/external_ingested] --> F[fma/manifests] |
| 309 | - query 与 reference 共用这个 `song_id` | 148 | E --> G[mtg_jamendo/manifests] |
| 310 | - 不同重编版不要强行共用同一个 `song_id` | 149 | E --> H[my_bgm/manifests] |
| 311 | - 如果是“同一歌不同版本”,建议: | ||
| 312 | - `song_id=主作品ID` | ||
| 313 | - `version_id=具体版本ID` | ||
| 314 | 150 | ||
| 315 | --- | 151 | I[acr-engine/data/external_smoke] --> J[fma_*] |
| 316 | |||
| 317 | ## 4.2 场景 B:你有手机录音、环境录音、直播录屏 | ||
| 318 | |||
| 319 | 这类数据通常更适合作为 **query / hard case**,不适合作为主 reference。 | ||
| 320 | |||
| 321 | ### 推荐映射 | ||
| 322 | |||
| 323 | | 原始录音类型 | 建议角色 | | ||
| 324 | |---|---| | ||
| 325 | | 手机外放录音 | `augmented` 或 `external_query` | | ||
| 326 | | 环境采集 | `augmented` | | ||
| 327 | | 直播录屏截取 | `external_query` | | ||
| 328 | | 强失真但可识别旋律 | `humming_like` | | ||
| 329 | |||
| 330 | ### 转化步骤 | ||
| 331 | |||
| 332 | 1. 先找到它对应哪首 reference | ||
| 333 | 2. 确认主要目标曲目是否单一 | ||
| 334 | 3. 裁成 5s / 8s 片段 | ||
| 335 | 4. 写入同一个 `song_id` | ||
| 336 | 5. 标 `type=augmented / humming_like / confused` | ||
| 337 | 6. 标 `segment_type=external_query` | ||
| 338 | |||
| 339 | 示例: | ||
| 340 | |||
| 341 | ```json | ||
| 342 | { | ||
| 343 | "song_id": "song_0001", | ||
| 344 | "audio_path": "queries/phone/song_0001_live_01.wav", | ||
| 345 | "duration": 8.0, | ||
| 346 | "type": "augmented", | ||
| 347 | "segment_type": "external_query", | ||
| 348 | "source_dataset": "phone_recording" | ||
| 349 | } | ||
| 350 | ``` | 152 | ``` |
| 351 | 153 | ||
| 352 | --- | 154 | ## 5.2 目录职责表 |
| 353 | |||
| 354 | ## 4.3 场景 C:你只有一堆历史文件夹,还没有精标注 | ||
| 355 | |||
| 356 | 这种情况建议先做 **弱监督标准化**,不要卡死在一开始就完美标注。 | ||
| 357 | 155 | ||
| 358 | ### 先做 3 步 | 156 | | 目录 | 作用 | |
| 359 | |||
| 360 | 1. **按文件夹/文件名生成候选 `song_id`** | ||
| 361 | 2. **把完整长音频先当候选 reference** | ||
| 362 | 3. **自动切若干 query 片段,后续再人工抽检修订** | ||
| 363 | |||
| 364 | ### 推荐策略 | ||
| 365 | |||
| 366 | | 阶段 | 做法 | | ||
| 367 | |---|---| | 157 | |---|---| |
| 368 | | 第 1 阶段 | 先把数据“可训练化” | | 158 | | `acr-engine/data/raw/fma_small_audio/` | FMA 原始音频目录 | |
| 369 | | 第 2 阶段 | 对高价值样本做人工修标 | | 159 | | `acr-engine/data/raw/mtg_jamendo_audio/` | MTG-Jamendo 原始音频目录 | |
| 370 | | 第 3 阶段 | 根据误识别样本补 hard cases | | 160 | | `acr-engine/data/external_ingested/<dataset>/manifests/` | 统一转换后的 manifest | |
| 161 | | `acr-engine/data/external_smoke/` | smoke 训练/索引/评测产物 | | ||
| 371 | 162 | ||
| 372 | --- | 163 | --- |
| 373 | 164 | ||
| 374 | ## 5. 标签应该怎么设计 | 165 | ## 6. FMA 的具体说明 |
| 375 | 166 | ||
| 376 | ## 5.1 最少标签集 | 167 | ## 6.1 当前已验证的 FMA 事实 |
| 377 | 168 | ||
| 378 | 对于当前项目,建议先保留以下标签层级: | 169 | | 项 | 当前状态 | |
| 170 | |---|---| | ||
| 171 | | 数据源 | 用户指定 ModelScope FMA Small 链接 | | ||
| 172 | | 本地目录 | `acr-engine/data/raw/fma_small_audio` | | ||
| 173 | | 音频文件数 | `8000` | | ||
| 174 | | 可切 query 文件 | `7994` | | ||
| 175 | | 中位时长 | `29.977s` | | ||
| 176 | | 真实 smoke | **正在运行 / 已产生中间产物** | | ||
| 379 | 177 | ||
| 380 | | 维度 | 字段 | 例子 | | 178 | 真实检查入口: |
| 381 | |---|---|---| | 179 | - [acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `check-local-ready` |
| 382 | | 主标签 | `song_id` | `song_0001` | | 180 | - [acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) `inspect-local` |
| 383 | | 版本标签 | `version_id` | `song_0001_mixA` | | ||
| 384 | | 角色标签 | `type` | `reference/clean/augmented/confused` | | ||
| 385 | | 结构标签 | `segment_type` | `intro/mid/outro/external_query` | | ||
| 386 | | 来源标签 | `source_dataset` | `fma_small` / `internal_bgm` | | ||
| 387 | | 合规标签 | `license` | `cc-by` / `internal` | | ||
| 388 | 181 | ||
| 389 | --- | 182 | --- |
| 390 | 183 | ||
| 391 | ## 5.2 什么情况下要拆 label | 184 | ## 6.2 FMA cookbook |
| 392 | 185 | ||
| 393 | 以下情况建议拆成不同 `song_id` 或 `version_id`: | 186 | ```bash |
| 187 | cd /workspace/acr-engine | ||
| 394 | 188 | ||
| 395 | | 情况 | 建议 | | 189 | /usr/local/miniconda3/bin/python src/data/external_adapters.py inspect-local \ |
| 396 | |---|---| | 190 | fma data/raw/fma_small_audio --eval-ratio 0.2 --query-duration 8.0 |
| 397 | | 主旋律相同但编曲大改 | 拆 `version_id` | | ||
| 398 | | 纯伴奏版 vs 演唱版差异极大 | 拆 `version_id` | | ||
| 399 | | mashup / 混剪 | 不进主训练集,单独 hard-case | | ||
| 400 | | 两首歌拼接 | 单独标记,避免污染主监督 | | ||
| 401 | 191 | ||
| 402 | --- | 192 | /usr/local/miniconda3/bin/python src/data/external_adapters.py prepare-local \ |
| 193 | fma data/raw/fma_small_audio --output-root data/external_ingested \ | ||
| 194 | --eval-ratio 0.2 --query-duration 8.0 | ||
| 403 | 195 | ||
| 404 | ## 6. BGM / 录音转训练集的工业化处理建议 | 196 | /usr/local/miniconda3/bin/python src/data/external_adapters.py validate-local \ |
| 405 | 197 | fma data/external_ingested/fma/manifests | |
| 406 | ## 6.1 推荐目录结构 | ||
| 407 | |||
| 408 | ```text | ||
| 409 | project/ | ||
| 410 | audio/ | ||
| 411 | reference/ | ||
| 412 | queries/ | ||
| 413 | augmented/ | ||
| 414 | manifests/ | ||
| 415 | catalog.json | ||
| 416 | train.json | ||
| 417 | val.json | ||
| 418 | test.json | ||
| 419 | ``` | 198 | ``` |
| 420 | 199 | ||
| 421 | 如果走当前仓库现成流程,也可以直接按: | 200 | 如果只是验证全链路: |
| 422 | |||
| 423 | - [acr-engine/data/raw/fma_small_audio/](../acr-engine/data/raw/fma_small_audio/) | ||
| 424 | - [acr-engine/data/raw/mtg_jamendo_audio/](../acr-engine/data/raw/mtg_jamendo_audio/) | ||
| 425 | |||
| 426 | 然后通过: | ||
| 427 | 201 | ||
| 428 | - [开放数据工作流](./open-dataset-workflow.md) | 202 | ```bash |
| 429 | 203 | /usr/local/miniconda3/bin/python src/data/external_adapters.py smoke-local \ | |
| 430 | 生成标准化输出。 | 204 | fma data/raw/fma_small_audio --output-root data/external_smoke \ |
| 205 | --eval-ratio 0.2 --query-duration 8.0 --train-epochs 1 --batch-size 2 | ||
| 206 | ``` | ||
| 431 | 207 | ||
| 432 | --- | 208 | --- |
| 433 | 209 | ||
| 434 | ## 6.2 推荐的数据处理 checklist | 210 | ## 7. 当前脚本与职责索引 |
| 435 | 211 | ||
| 436 | | 阶段 | 必做项 | | 212 | | 脚本/文件 | 作用 | |
| 437 | |---|---| | 213 | |---|---| |
| 438 | | 音频清洗 | 去坏文件、去空文件、统一采样率 | | 214 | | [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py) | 音频目录 -> manifest | |
| 439 | | 资产标准化 | mono、16k、稳定命名 | | 215 | | [acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py) | inspect / prepare / validate / smoke 统一入口 | |
| 440 | | reference 建立 | 每首歌至少 1 条 reference | | 216 | | [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py) | 训练/测试数据集读取与随机裁剪 | |
| 441 | | query 生成 | 每首歌切多个位置片段 | | 217 | | [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py) | 通用音频处理与滑窗 | |
| 442 | | 标签治理 | `song_id/version_id/type/source_dataset/license` | | 218 | | [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py) | embedding 抽取与 reference 滑窗索引 | |
| 443 | | 数据拆分 | train/val/test 按歌或按 query 控制泄漏 | | 219 | | [acr-engine/train.py](../acr-engine/train.py) | 训练主入口 | |
| 444 | | 评测 | 看 top1/topk、混淆矩阵、难例集 | | 220 | | [acr-engine/evaluate.py](../acr-engine/evaluate.py) | 评测主入口 | |
| 445 | | 入库 | manifest -> JSON -> PostgreSQL/pgvector | | 221 | | [acr-engine/run_demo.py](../acr-engine/run_demo.py) | build-index / query demo | |
| 222 | | [acr-engine/scripts/export_manifest_to_pgvector_json.py](../acr-engine/scripts/export_manifest_to_pgvector_json.py) | manifest 导出为 pgvector-ready JSON | | ||
| 223 | | [acr-engine/scripts/pgvector_bulk_load_template.py](../acr-engine/scripts/pgvector_bulk_load_template.py) | PostgreSQL 批量导入模板 | | ||
| 224 | | [acr-engine/sql/pgvector_schema.sql](../acr-engine/sql/pgvector_schema.sql) | pgvector 表结构模板 | | ||
| 446 | 225 | ||
| 447 | --- | 226 | --- |
| 448 | 227 | ||
| 449 | ## 7. 如果将来要把音频内容保存到 pgvector 检索系统,应该怎么转 | 228 | ## 8. GPU 是否会快很多 |
| 450 | |||
| 451 | ## 7.1 不要直接存“音频”,要存“音频的表示” | ||
| 452 | 229 | ||
| 453 | `pgvector` 适合存: | 230 | ## 8.1 结论先说 |
| 454 | 231 | ||
| 455 | - embedding 向量 | 232 | **会。对于 FMA 这种 8000 首规模的真实数据,GPU 通常会比 CPU 快很多。** |
| 456 | - 指纹向量 | ||
| 457 | - 结构化 metadata | ||
| 458 | 233 | ||
| 459 | 不适合存: | 234 | 原因: |
| 235 | - Mel 特征后面的 ECAPA 前向/反向传播主要是张量计算; | ||
| 236 | - 当前 `train.py` 已支持 `--device auto`,且 CUDA 路径已启用 mixed precision; | ||
| 237 | - 真实 FMA smoke 当前跑在 CPU,上千 batch 训练明显慢。 | ||
| 460 | 238 | ||
| 461 | - 大体积原始 WAV 本体 | 239 | ## 8.2 当前代码现状 |
| 462 | - 大批量训练中间缓存 | ||
| 463 | 240 | ||
| 464 | ### 建议保存的对象 | 241 | | 链路 | 当前状态 | |
| 465 | |||
| 466 | | 对象 | 是否进 pgvector | | ||
| 467 | |---|---| | 242 | |---|---| |
| 468 | | 原始音频文件 | 否 | | 243 | | `train.py` | 支持 `--device auto/cuda/cpu` | |
| 469 | | 标准化音频路径 | 是,存 URI/Path | | 244 | | CUDA mixed precision | 已支持 | |
| 470 | | reference embedding | 是 | | 245 | | `smoke-local` | **当前硬编码 `--device cpu`** | |
| 471 | | query embedding | 可选 | | 246 | | `evaluate.py` | 当前 CLI 默认 `cpu` | |
| 472 | | song metadata | 是,普通表 | | 247 | | `run_demo.py build-index` | 当前 smoke 里也走 `cpu` | |
| 473 | | 标签/来源/license | 是,普通表 | | ||
| 474 | 248 | ||
| 475 | --- | 249 | ### 当前要注意的一点 |
| 476 | 250 | ||
| 477 | ## 7.2 建议的线上检索链路 | 251 | `smoke-local` 虽然支持真实数据,但它现在为了稳妥把: |
| 252 | - 训练 | ||
| 253 | - 建索引 | ||
| 254 | - 评测 | ||
| 478 | 255 | ||
| 479 | ```mermaid | 256 | 都固定到了 **CPU**。所以如果你想真正在本机上加速真实 FMA 训练,后续应该继续把 `smoke-local` 的 device 变成可配置项。 |
| 480 | sequenceDiagram | ||
| 481 | participant U as User Query Audio | ||
| 482 | participant S as ACR Service | ||
| 483 | participant E as Embedder | ||
| 484 | participant P as pgvector | ||
| 485 | participant M as Metadata DB | ||
| 486 | |||
| 487 | U->>S: 上传5s/8s音频 | ||
| 488 | S->>E: 提取128 Mel + embedding | ||
| 489 | E->>P: 向量检索TopK | ||
| 490 | P-->>S: 候选 song_id | ||
| 491 | S->>M: 读取歌曲元数据 | ||
| 492 | M-->>S: title/artist/version/license | ||
| 493 | S-->>U: 返回识别结果 | ||
| 494 | ``` | ||
| 495 | 257 | ||
| 496 | --- | 258 | --- |
| 497 | 259 | ||
| 498 | ## 8. 你们现在就可以采用的落地规范 | 260 | ## 9. 如果后面要保存到 pgvector,现在应该怎么处理 |
| 499 | |||
| 500 | ## 8.1 训练样本规范(建议定版) | ||
| 501 | |||
| 502 | ### 输入规范 | ||
| 503 | 261 | ||
| 504 | - 单条 query:`5s` 或 `8s` | 262 | ## 9.1 正确分层 |
| 505 | - 音乐主体明确 | ||
| 506 | - 16k mono | ||
| 507 | - 每条 query 必须映射到一个 `song_id` | ||
| 508 | 263 | ||
| 509 | ### reference 规范 | 264 | | 内容 | 存储位置 | |
| 510 | 265 | |---|---| | |
| 511 | - 每首歌至少一个完整 reference | 266 | | 原始音频 / 标准音频 | 文件系统 / NAS / 对象存储 | |
| 512 | - reference 不用强切成很多碎片保存 | 267 | | manifest / 元数据 | PostgreSQL 普通表 | |
| 513 | - 以全曲或长片段为主 | 268 | | 向量 embedding | `pgvector` 列 | |
| 514 | 269 | | 检索参数与版本 | PostgreSQL / 配置中心 | | |
| 515 | ### 标签规范 | ||
| 516 | |||
| 517 | - `song_id`:稳定主键 | ||
| 518 | - `version_id`:可扩展 | ||
| 519 | - `type`:固定枚举 | ||
| 520 | - `source_dataset`:必保留 | ||
| 521 | - `license`:商业化必须保留 | ||
| 522 | |||
| 523 | --- | ||
| 524 | |||
| 525 | ## 8.2 面向 pgvector 的规范(建议定版) | ||
| 526 | 270 | ||
| 527 | - manifest 作为唯一数据交换层 | 271 | 原则: |
| 528 | - 音频在文件系统,对象路径写到 `audio_uri` | 272 | - **不要把原始 mp3 直接塞进 pgvector 表**; |
| 529 | - embedding 单独表,带 `model_version` | 273 | - 先标准化音频和 manifest; |
| 530 | - 每次重训后保留 `data_version` | 274 | - 再从 manifest 产出 embedding 与结构化记录。 |
| 531 | - 检索结果必须能追溯到原始 reference | ||
| 532 | 275 | ||
| 533 | --- | 276 | --- |
| 534 | 277 | ||
| 535 | ## 9. 推荐执行路径 | 278 | ## 9.2 pgvector 推荐数据模型 |
| 536 | 279 | ||
| 537 | 如果你们后面要把 BGM、录音、开放数据一起纳入训练,我建议按这个顺序推进: | 280 | ```mermaid |
| 281 | flowchart TD | ||
| 282 | A[songs] --> B[references] | ||
| 283 | A --> C[segments] | ||
| 284 | B --> D[reference_embeddings] | ||
| 285 | C --> E[query_embeddings] | ||
| 286 | ``` | ||
| 538 | 287 | ||
| 539 | 1. 先把所有音频资产标准化为 `16k mono` | 288 | 当前仓库模板: |
| 540 | 2. 给每首歌建立稳定 `song_id` | 289 | - [acr-engine/sql/pgvector_schema.sql](../acr-engine/sql/pgvector_schema.sql) |
| 541 | 3. 完整曲目作为 reference | 290 | - [acr-engine/scripts/export_manifest_to_pgvector_json.py](../acr-engine/scripts/export_manifest_to_pgvector_json.py) |
| 542 | 4. 自动切 5s/8s query | 291 | - [acr-engine/scripts/pgvector_bulk_load_template.py](../acr-engine/scripts/pgvector_bulk_load_template.py) |
| 543 | 5. 增加 `augmented/confused/humming_like` 难例 | ||
| 544 | 6. 生成 manifests | ||
| 545 | 7. 跑训练 / 评测 / 建索引 | ||
| 546 | 8. 从 manifest 导出 pgvector JSON | ||
| 547 | 9. 再接 PostgreSQL + pgvector | ||
| 548 | 292 | ||
| 549 | --- | 293 | --- |
| 550 | 294 | ||
| 551 | ## 10. 直接给你的结论 | 295 | ## 9.3 从今天开始就该保留的字段 |
| 552 | 296 | ||
| 553 | ### 问题 1:当前训练数据和输入数据应该是什么样 | 297 | | 字段 | 作用 | |
| 298 | |---|---| | ||
| 299 | | `song_id` | 主连接键 | | ||
| 300 | | `version_id` | 多版本扩展 | | ||
| 301 | | `audio_path` / `audio_uri` | 回溯音频资产 | | ||
| 302 | | `duration` | 切片合法性校验 | | ||
| 303 | | `offset` | query 对应 reference 的时间位置 | | ||
| 304 | | `type` | 训练/检索角色 | | ||
| 305 | | `segment_type` | intro/mid/outro/external | | ||
| 306 | | `source_dataset` | 数据来源治理 | | ||
| 307 | | `license` | 合规治理 | | ||
| 308 | | `split` | train/val/test | | ||
| 309 | | `model_version` | 向量版本控制 | | ||
| 310 | | `data_version` | 数据快照版本 | | ||
| 554 | 311 | ||
| 555 | 答案: | 312 | --- |
| 556 | 313 | ||
| 557 | - **输入不是单纯音频文件夹,而是“音频 + `song_id` 标签 + manifest”** | 314 | ## 10. 当前一个真实注意点:5s / 8s 配置差异 |
| 558 | - **reference 是完整曲目或长片段,query 是 5s/8s 片段** | ||
| 559 | - **当前推荐统一成 16k mono,输入层采用 128 维 Mel 频谱** | ||
| 560 | - **如果未来要接 pgvector,现在就要保留 `song_id/version_id/audio_uri/source_dataset/license/model_version/data_version` 这些字段** | ||
| 561 | 315 | ||
| 562 | ### 问题 2:BGM、音乐录音怎么转成训练数据 | 316 | 当前仓库里有一个必须写进交接文档的现实问题: |
| 563 | 317 | ||
| 564 | 答案: | 318 | | 项 | 当前事实 | |
| 319 | |---|---| | ||
| 320 | | `smoke-local` 命令 | 常用 `--query-duration 8.0` | | ||
| 321 | | 训练 dataset | 仍按 `segment_dur=5.0` 读取 | | ||
| 322 | | 现有 FMA smoke 报告 `config.json` | 出现过 `query_duration=5.0` 的旧产物 | | ||
| 565 | 323 | ||
| 566 | - **完整 BGM/母带 -> reference** | 324 | 解释: |
| 567 | - **从 reference 切 5s/8s -> clean query** | 325 | - **manifest query 时长**、**训练 crop 时长**、**报告里记录的 query_duration** 当前不是完全同一个配置源; |
| 568 | - **加噪/混响/压缩 -> augmented query** | 326 | - 现有 `fma_reports_smoke/config.json` 时间戳早于最新 manifests,属于需要继续治理的实验产物一致性问题; |
| 569 | - **手机录音/环境录音/直播录屏 -> external query / hard case** | 327 | - 因此后续继续做工业级化时,应该把 “manifest query 时长 / train clip 时长 / eval query 时长 / report metadata” 统一纳入一个显式配置结构。 |
| 570 | - **所有派生片段都必须回挂到统一 `song_id`** | ||
| 571 | 328 | ||
| 572 | --- | 329 | --- |
| 573 | 330 | ||
| 574 | ## 11. 相关仓库内工具 | 331 | ## 11. 给你们后续自建数据集的落地建议 |
| 575 | 332 | ||
| 576 | ### 文档 | 333 | 1. **完整曲库先做 reference 池**。 |
| 577 | - [数据规范](./dataset-spec.md) | 334 | 2. **从 reference 池切出 clean query 作为第一层训练集**。 |
| 578 | - [开放数据工作流](./open-dataset-workflow.md) | 335 | 3. **再做 augmented / confused / humming_like 三类增强 query**。 |
| 579 | - [数据来源与接入](./dataset-sources-and-licensing.md) | 336 | 4. **固定一部分永不训练,只做 test set。** |
| 580 | 337 | 5. **先把 manifest 字段做全,再谈 pgvector 和工业服务。** | |
| 581 | ### 脚本 / SQL | ||
| 582 | - [acr-engine/scripts/export_manifest_to_pgvector_json.py](../acr-engine/scripts/export_manifest_to_pgvector_json.py) | ||
| 583 | - [acr-engine/scripts/pgvector_bulk_load_template.py](../acr-engine/scripts/pgvector_bulk_load_template.py) | ||
| 584 | - [acr-engine/sql/pgvector_schema.sql](../acr-engine/sql/pgvector_schema.sql) | ||
| 585 | 338 | ||
| 586 | ## Sources | 339 | ## Sources |
| 587 | - This guide is grounded in the current repo’s manifest pipeline and pgvector schema templates: | 340 | - 当前代码事实来自 [acr-engine/src/data/dataset.py](../acr-engine/src/data/dataset.py), [acr-engine/src/data/manifest_tools.py](../acr-engine/src/data/manifest_tools.py), [acr-engine/src/data/external_adapters.py](../acr-engine/src/data/external_adapters.py), [acr-engine/src/utils/audio.py](../acr-engine/src/utils/audio.py), [acr-engine/src/engines/ecapa_embedder.py](../acr-engine/src/engines/ecapa_embedder.py), [acr-engine/train.py](../acr-engine/train.py) |
| 588 | - [acr-engine/scripts/export_manifest_to_pgvector_json.py](../acr-engine/scripts/export_manifest_to_pgvector_json.py) | ||
| 589 | - [acr-engine/sql/pgvector_schema.sql](../acr-engine/sql/pgvector_schema.sql) | ||
| 590 | - [数据规范](./dataset-spec.md) | ... | ... |
-
Please register or sign in to post a comment