内容
# 频谱分析工具
**机器可读的音频分析结果。**
指向 `beatlyzer` 一个 `.mp3`(或 `.wav`、`.flac`、`.ogg`、`.m4a` 等)文件,它会生成:
- 一个 **结构化、适合大型语言模型的 JSON** 描述文件,
- 一个 **丰富的终端摘要**,
- 一个 **带注释的多面板可视化**(PNG)文件,标注 **节拍下降**、**音量激增**、**高音调**、亮度、结构和频谱图,
- 一个可选的 **Markdown 报告**。
它的设计使得视觉或文本能力的人工智能模型可以“理解”一首歌曲:它听起来是什么样的,它的结构是什么,能量峰值在哪里,以及确切的 **什么时候** 会出现有趣的时刻。
---
## 示例
`beatlyzer demo.wav` 生成了这个四面板分析:

除了 PNG 文件外,它还写入了一个机器可读的 [`demo.beatlyzer.json`](demo.beatlyzer.json) 和一个 [`demo.beatlyzer.md`](demo.beatlyzer.md) 报告 — 两个文件都包含在此。请使用 `python scripts/make_sample.py demo.wav` 自行生成演示输入。
---
## 检测内容
| 信号 | 方法 | 输出 |
| --- | --- | --- |
| **节奏和节拍** | 使用 librosa 进行节拍跟踪 | BPM + 节拍网格 |
| **调** | Krumhansl-Schmuckler 色谱相关性 | 例如 `F 小调` |
| **节拍下降** | 急剧上升到响亮、**低音丰富** 的段落,锁定到节拍 | 时间线事件 |
| **音量激增** | 音量逐渐增加 / 响亮度跳跃(不是下降) | 时间线事件 |
| **高音调** | 谱质心 + 高频能量峰值 | 时间线事件 |
| **响亮度和动态** | RMS 以 dB 为单位,相对于峰值 | 平均值 / 峰值 / 动态范围 |
| **亮度** | 谷值谱质心 | 黑 ↔ 明亮 |
| **结构** | 基于音色和谐的凝聚聚类 | 前奏 → 发展 → 高潮 → 结尾 |
---
## 安装
需要 Python 3.9+(3.10+ for MCP 服务器)。对于 **mp3/m4a/aac** 解码,你需要在 PATH 中安装 **ffmpeg** (`sudo dnf install ffmpeg` / `brew install ffmpeg` / `apt install ffmpeg`).
### 作为全局 CLI 工具 — 推荐,无需管理虚拟环境
获取 `beatlyzer`(和 `beatlyzer-mcp`)最干净的方法是在任何地方都可用,是使用 [pipx](https://pipx.pypa.io) 或 [uv](https://docs.astral.sh/uv/),它们各自将工具安装到独立的环境中,并将命令放在你的 PATH 上 — 你永远不需要创建或激活虚拟环境:
```bash
# pipx
pipx install 'git+https://github.com/Profazia/beatlyzer.git'
pipx inject beatlyzer mcp # 添加 MCP 服务器额外功能
# 或 uv
uv tool install 'beatlyzer[mcp] @ git+https://github.com/Profazia/beatlyzer.git'
# 运行一次,无需永久安装任何内容:
uvx --from 'git+https://github.com/Profazia/beatlyzer.git' beatlyzer song.mp3
```
> **注意:** `librosa`/`numba` 可能落后于最新的 Python 版本。如果构建失败,请固定解释器:`pipx install --python python3.12 ...`。
### 从克隆(开发)
```bash
pip install -e ".[dev,mcp]" # 可编辑安装,包含测试和 MCP 依赖项
```
这安装了 `beatlyzer` 和 `beatlyzer-mcp` 命令。
---
## 用法
```bash
# 分析文件 — 在其旁边写入 <name>.beatlyzer.{png,json,md}
beatlyzer song.mp3
# 选择输出目录,并在完成后打开图像
beatlyzer track.wav -o out/ --open
# 仅限机器可读的 JSON,打印到 stdout,无文件,无提示
beatlyzer mix.flac --format json --print-json --quiet
```
没有文件吗?生成一个演示曲目:
```bash
python scripts/make_sample.py sample.wav
beatlyzer sample.wav --open
```
### 选项
```
-o, --output-dir DIR 输出文件的位置(默认:与输入文件相同)
-f, --format CHOICE all | png | json | md | none (默认:all)
--stem NAME 输出文件的基本名称(默认:输入文件名)
--sr INT 分析采样率(默认:22050)
--dpi INT PNG 分辨率(默认:140)
--open 完成后打开 PNG
--quiet 禁止终端摘要
--print-json 将 JSON 摘要打印到 stdout
-V, --version 显示版本
```
也可以作为模块运行:`python -m beatlyzer song.mp3`.
---
## AI 可读的 JSON
`<name>.beatlyzer.json` 遵循 `beatlyzer.analysis/v1` 模式。直接将其输入 LLM — 它是自我描述的(参见 `ai_notes` 字段):
```jsonc
{
"schema": "beatlyzer.analysis/v1",
"metadata": { "duration_hms": "0:24", "tempo_bpm": 128.0, "estimated_key": "A minor", ... },
"loudness": { "average_db": -18.4, "dynamic_range_db": 31.2, "description": "wide dynamics" },
"brightness":{ "average_centroid_hz": 2680.0, "description": "balanced" },
"sections": [ { "label": "intro", "start_hms": "0:00", "energy_level": "low" }, ... ],
"events": [
{ "time_hms": "0:09", "type": "beat_drop", "strength_0_1": 1.0, "bass_share": 0.71,
"description": "Beat drop at 0:09 — energy surges into a loud, bass-heavy section." },
{ "time_hms": "0:17", "type": "high_tone", "strength_0_1": 0.93, "centroid_hz": 6011.0, ... }
],
"energy_profile": [ { "t": 0.0, "energy": 0.05, "loudness_db": -34.1, "brightness": 0.2 }, ... ],
"summary_text": "This 0:24 track is a high-energy piece at 128 BPM in A minor. ...",
"ai_notes": "Times are seconds from the start. 'loudness' is dB relative to the track's peak ..."
}
```
## 可视化
`<name>.beatlyzer.png` 是一个四面板图表,共享一个时间轴:
1. **波形**,带有阴影结构部分和淡色节拍网格。
2. **响亮度(dB)**,带有 **节拍下降**(红色)和 **音量激增**(橙色)。
3. **亮度**(谱质心),带有 **高音调** 峰值(紫色)。
4. **梅尔频谱图**,带有叠加的下降线。
---
## 用作 MCP 服务器
beatlyzer 附带了一个 [MCP](https://modelcontextprotocol.io) 服务器,以便 AI 代理 — Claude Code、Claude Desktop、Cursor 等 — 可以直接分析音频。它通过标准输入输出运行,并公开三个工具:
| 工具 | 返回 |
| --- | --- |
| `analyze_audio(file_path, sample_rate=22050)` | 完整的结构化 JSON 摘要 |
| `describe_audio(file_path)` | 简短的文字描述 |
| `visualize_audio(file_path, output_path=None, dpi=140)` | 带注释的 PNG,作为模型可见的图像 |
确保已安装 `mcp` 额外功能 (`pipx inject beatlyzer mcp` 或 `pip install 'beatlyzer[mcp]'`),然后注册服务器。
**Claude Code:**
```bash
claude mcp add beatlyzer beatlyzer-mcp
```
**Claude Desktop / 任意 MCP 客户端** (`claude_desktop_config.json` 或等效):
```json
{
"mcpServers": {
"beatlyzer": {
"command": "beatlyzer-mcp"
}
}
}
```
如果 `beatlyzer-mcp` 不在客户端的 PATH 中,请使用绝对路径(例如 `~/.local/bin/beatlyzer-mcp` 或 `pipx list` 打印的路径)。一个现成的代码片段位于 [`examples/mcp-config.json`](examples/mcp-config.json).
然后直接问模型诸如 *"分析 ~/Music/track.mp3 并告诉我节拍下降的位置"* 或 *"可视化这首歌"* 之类的问题。
---
## 作为库
```python
from beatlyzer import analyze_file
from beatlyzer.report import build_result_dict
result = analyze_file("song.mp3")
print(result.summary_text)
print([e.time for e in result.drops])
doc = build_result_dict(result) # JSON-ready 字典
```
---
## 检测原理(简版)
每个检测器都会平滑特征轨迹,衡量其 **过渡**(某个时刻后的平均能量 - 之前的平均能量),然后保留突出、分离良好的峰值,并将其与最近的节拍对齐:
- **下降** 将整体 RMS 与低于 250 Hz 的 **低音** 能量相结合,还要求着陆段真正响亮 — 一个逐渐消失的积累不是下降。
- **激增** 跟踪音量跳跃,并与下降去重。
- **高音调** 将谱质心与 >4 kHz 能量份额相结合。
这些是透明的启发式方法,而不是训练过的模型 — 快速、依赖性轻、易于解释。在 `src/beatlyzer/events.py` 中调整阈值。
## 开发
```bash
pip install -e ".[dev]"
pytest
```
## 许可证
MIT — 见 [LICENSE](LICENSE).