การแยกแหล่งเสียง
Open-Unmix HQ แยกแทร็กเพลงสเตอริโอออกเป็นสี่ stem ที่เป็นอิสระต่อกัน — vocals, drums, bass และ other โมเดล BiLSTM อิสระสี่ตัว (หนึ่งตัวต่อหนึ่ง stem) สร้างมาสก์ขนาดบน STFT ของส่วนผสม; Wiener post-filter ที่เป็นทางเลือกจะช่วยปรับให้สอดคล้องกัน ทำงานบน Apple Silicon ผ่าน MLX
มันคืออะไร
- 4 stem ต่อแทร็ก — vocals, drums, bass, other แต่ละ stem เป็นไฟล์ 2 channel ที่ 44.1 kHz
- โมเดลมาสก์ขนาด — โมเดลแต่ละ stem ทำนายมาสก์แบบไม่ติดลบที่ใช้กับสเปกโตรแกรมของส่วนผสม; phase นำมาจากส่วนผสม
- Wiener post-filter (ทางเลือก) — ปรับปรุงมาสก์แบบนิ่มๆ ทั้ง 4 stem เพื่อให้รวมกลับเข้าเป็นส่วนผสมได้อย่างสอดคล้องกัน เพิ่ม SDR ~0.5 dB
- ขนาดเล็ก — 8.9M พารามิเตอร์ต่อ stem รวมทั้งหมด ~136 MB สำหรับทั้ง 4 stem
- Apache-2.0 — น้ำหนักต้นน้ำใช้ MIT, การแปลง CoreML/MLX ของเราใช้ Apache-2.0
สถาปัตยกรรม
สี่ stem อิสระ แต่ละตัวเป็นสำเนาของโครงข่ายเดียวกัน
| ขั้นตอน | รูปร่าง / การดำเนินการ |
|---|---|
| STFT | FFT 4096 จุด, hop 1024, หน้าต่าง Hann แบบ periodic, reflect-pad 2049 bin ความถี่ต่อ frame |
| การ normalize อินพุต | ครอปเหลือ 1487 bin (≈16 kHz), ใช้ค่าเฉลี่ยและสเกลต่อ bin ที่เรียนรู้มาจากการฝึก |
| Encoder | Linear 2974 → 512 + BatchNorm + tanh อินพุตคือ 2 channel × 1487 bin |
| BiLSTM | 3 ชั้น, 256 hidden ต่อทิศทาง (512 ที่ใช้งานจริง) เก็บบริบทเชิงเวลาข้าม frame |
| Decoder | Skip-concat ของเอาต์พุต encoder และ LSTM (1024) → Linear 1024 → 512 + BN + ReLU → Linear 512 → 4098 |
| เอาต์พุต denorm + มาสก์ | คูณตามองค์ประกอบกับขนาดของส่วนผสม; phase จากส่วนผสม; iSTFT overlap-add |
| Wiener (ทางเลือก) | มาสก์อัตราส่วนกำลังบนการประมาณ stem ทั้ง 4 ตัว ปรับ phase เพื่อให้ stem รวมกลับเป็นส่วนผสม |
โมเดล
| องค์ประกอบ | ค่า |
|---|---|
| พารามิเตอร์ / stem | 8.9M |
| พารามิเตอร์รวม (4 stem) | ~35.6M |
| Sample rate | 44.1 kHz stereo |
| Chunk latency | ออฟไลน์ (STFT ทั้งแทร็ก) |
| น้ำหนัก | aufklarer/OpenUnmix-HQ-MLX (safetensors, ~136 MB) |
| ต้นน้ำ | sigsep/open-unmix-pytorch (Stöter และคณะ, JOSS 2019) |
เริ่มต้นอย่างรวดเร็ว — Swift
import SourceSeparation
import AudioCommon
let separator = try await SourceSeparator.fromPretrained()
let stereo = try AudioFileLoader.loadStereo(
url: URL(fileURLWithPath: "song.wav"),
targetSampleRate: 44100
)
let stems = separator.separate(audio: stereo, sampleRate: 44100)
// stems[.vocals], stems[.drums], stems[.bass], stems[.other]
// Each is [[Float]] — left channel, right channel.
try WAVWriter.writeStereo(
left: stems[.vocals]![0],
right: stems[.vocals]![1],
sampleRate: 44100,
to: URL(fileURLWithPath: "vocals.wav")
)
ส่งผ่าน wiener: true (ค่าเริ่มต้น) เพื่อคุณภาพที่ดีที่สุด ส่งผ่าน targets: [.vocals] เพื่อแยกเฉพาะ stem ชุดย่อยและข้ามโมเดลอื่นๆ
CLI
speech separate song.wav # all 4 stems into song_stems/
speech separate song.wav --stems vocals # vocals only
speech separate song.wav --stems vocals,drums # subset
speech separate song.wav --output-dir /tmp/stems/ # custom output dir
speech separate song.wav --verbose # show timing
เมื่อใดที่ควรใช้
…คุณต้องการขั้นตอนการแยกแหล่งเสียงที่เบาและออฟไลน์ในแอปหรือไปป์ไลน์บน Apple Silicon 8.9M พารามิเตอร์ต่อ stem ช่วยให้ขนาดดาวน์โหลดและการใช้หน่วยความจำอยู่ในเกณฑ์พอเหมาะ การมาสก์ขนาดร่วมกับ Wiener ให้ stem ที่มีคุณภาพดีกับเนื้อหา pop/rock ส่วนใหญ่ สำหรับการแยกเสียงร้องระดับ state-of-the-art บนเนื้อหาสตูดิโอ คุณอาจต้องใช้โมเดลขนาดใหญ่กว่าระดับ Demucs/MDX-Net; แพ็กเกจนี้มุ่งเป้าไปที่จุดสมดุลเชิงปฏิบัติเพื่อนำเข้าแอปได้