创作 — 音乐与音频制作

speech-swift 的音乐与音频制作部分由三个本地模块组成,全部通过 MLX 或 CoreML 在 Apple Silicon 上原生运行。MAGNeT 根据文本提示生成 30 秒音乐片段。音源分离(Open-Unmix)将立体声音轨拆分为四个声轨(人声 / 鼓 / 贝斯 / 其他)。语音增强(DeepFilterNet3)实时去除语音中的背景噪声。

模块任务后端输出CLI
MAGNeT文本 → 音乐MLX (INT4 / INT8)30 秒 @ 32 kHz 单声道speech compose
Open-Unmix声轨分离MLX4 声轨 @ 44.1 kHz 立体声speech separate
DeepFilterNet3噪声抑制CoreML (Neural Engine)48 kHz,实时speech denoise

MAGNeT — 文本到音乐生成

Meta MAGNeT(单非自回归 Transformer 的掩码音频生成)的 MLX Swift 移植版本。根据自由形式的英文提示生成 30 秒、32 kHz 单声道音乐片段 —— 例如 "happy rock"、"energetic EDM with synth lead",或使用丰富的描述性文本以获得更干净的效果。

架构

加载三个组件,首次调用时下载:

组件作用来源
MAGNeT 解码 LM作用于 4 个 EnCodec 码本的掩码非自回归 Transformer。24 层(Small, 300M)或 48 层(Medium, 1.5B)。Q/K/V/out 投影 + FFN 线性层量化(MLX-affine,group 64)。aufklarer/MAGNeT-{Small,Medium}-30secs-MLX-{4,8}bit
T5-base 文本编码器用于文本条件化的 110M 参数编码器。FP32(仅编码器路径;无解码器,无 LM 头)。t5-base
EnCodec 32 kHz 解码器SEANet 解码器(Conv1d / ConvTranspose1d / ResnetBlock / 2 层 LSTM)+ 4 码本 Euclidean RVQ。将 LM 的离散 token 映射回 32 kHz 波形。mlx-community/encodec-32khz-float32

掩码并行解码

与自回归的 MusicGen 不同,MAGNeT 总共运行 50 次前向传递(在 4 个码本上的默认分配为 [20, 10, 10, 10]),采用余弦调度的重掩码、无分类器引导退火,以及按阶段的局部注意力窗口。阶段 0 使用完整的自注意力;阶段 1–3 使用 |q − k| ≤ 5 的局部窗口,因为更高的码本仅细化细节。

变体

变体参数LM 磁盘大小峰值 RSS耗时(M 系列,30 秒)RTF
small-int4300M287 MB~1.4 GB~10.8 s0.36×
small-int8300M425 MB~1.5 GB~11 s0.37×
medium-int41.5B1.36 GB~2.2 GB~36 s1.20×
medium-int81.5B2.10 GB~3.0 GB~36 s1.20×

RTF 低于 1.0 = 比实时更快。量化几乎不影响耗时 —— 主导的是注意力而非线性投影 —— 因此 INT4 的实际收益是内存而非延迟。

快速开始

import MAGNeTMusicGen

let model = try await MAGNeTMusicGen.fromPretrained(variant: .smallInt4)
let pcm = model.generate(text: "energetic upbeat rock anthem with electric guitar riffs, driving drums, bass groove")
// pcm: [Float] length 960_000 (30 s × 32 kHz mono)

try WAVWriter.write(samples: pcm, sampleRate: 32_000,
                    to: URL(fileURLWithPath: "out.wav"))

CLI

# Default: small-int4 (~10 s on M-series for 30 s of audio)
speech compose "happy rock" -o happy_rock.wav

# Larger model — better prompt following, ~3.5× slower
speech compose "lo-fi hip hop with mellow piano and warm vinyl crackle" \
    --variant medium-int4 -o lofi.wav

# Reproducible
speech compose "energetic EDM with synth lead" --seed 42 -o edm.wav

参数:--variant {small,medium}-{int4,int8}--temperature(退火,默认 3.0)、--top-p(默认 0.9)、--cfg-max / --cfg-min(默认 10.0 / 1.0)、--steps "20,10,10,10"(每个码本的迭代次数)、--seed

提示工程技巧

"happy rock" 这样的短标签可以工作但感觉单薄。提到 乐器 + 节奏 + 情绪 的描述性提示能显著提高连贯性 —— 在我们的质量测试中,更丰富的提示带来了更高的过零率(0.116 vs 0.093,即更多高频细节)和零削波。比较:

  • "happy rock" — 单薄
  • "energetic upbeat rock anthem with electric guitar riffs, driving drums, bass groove" — 更丰富,通常更好

包与许可

所有四个 MLX 包均派生自 facebook/magnet-small-30secsfacebook/magnet-medium-30secs,继承 Meta 的许可:CC-BY-NC 4.0 — 仅限非商业用途。生成的音频遵循相同的限制。

音源分离 — Open-Unmix(4 声轨)

Open-Unmix HQ / UMX-L 移植到 MLX。通过每个声轨的 BiLSTM 预测器和多通道 Wiener-EM 后置滤波器将立体声混音拆分为四个声轨 —— 人声贝斯其他乐器 —— 全程在 MLX 上端到端运行,通过逆 STFT 完成。M 系列上 30 秒音频的实际 RTF 约为 0.031(比实时快 32 倍)。

# Split mix.wav into vocals/drums/bass/other.wav next to it
speech separate mix.wav

# Or keep stems together
speech separate mix.wav --output stems/

import SourceSeparation

let separator = try await SourceSeparator.fromPretrained()
let stems = try separator.separate(audio: stereoSamples, sampleRate: 44_100)
// stems.vocals, stems.drums, stems.bass, stems.other  — each [Float]

完整的架构、调优和基准测试说明请参见音源分离指南

语音增强 — DeepFilterNet3

运行在神经引擎(CoreML)上的 DeepFilterNet3。使用 2.1M 参数模型实时去除 48 kHz 语音中的背景噪声 —— 足够小,可作为 ASR 流水线的预处理步骤并行运行。

speech denoise noisy.wav -o clean.wav

import SpeechEnhancement

let enhancer = try await SpeechEnhancer.fromPretrained()
let clean = try enhancer.enhance(audio: noisy, sampleRate: 48_000)

完整配置请参见语音增强指南

选择合适的工具

你想要…使用
从文本提示生成音乐MAGNeT (speech compose)
从现有音轨中提取人声或鼓声Open-Unmix (speech separate)
在转录前清理嘈杂的语音DeepFilterNet3 (speech denoise)
将文本转换为语音(语音合成)VoxCPM2 or Qwen3-TTS