아키텍처
speech-swift는 공유 프로토콜, 독립적인 모델 모듈, 통합 CLI를 갖춘 모듈식 Swift 패키지로 구성되어 있습니다. 모든 추론은 MLX (Metal GPU) 또는 CoreML (Neural Engine)을 사용해 온디바이스에서 실행됩니다.
모듈 종속성 그래프
┌──────────┐
│ AudioCLI │ (entry point)
└────┬─────┘
│
┌──────┴──────┐
│ AudioCLILib │ (commands)
└──────┬──────┘
│
┌─────────┬───────┼───────┬──────────┬──────────────┐
│ │ │ │ │ │
┌────┴───┐ ┌──┴──┐ ┌──┴──┐ ┌─┴────┐ ┌───┴────┐ ┌──────┴───────┐
│Qwen3ASR│ │Qwen3│ │Cosy │ │Perso-│ │Speech- │ │ Speech- │
│Parakeet│ │ TTS │ │Voice│ │naPlex│ │ VAD │ │Enhancement │
└────┬───┘ └──┬──┘ └──┬──┘ └──┬───┘ └───┬───┘ └──────┬───────┘
│ │ │ │ │ │
└────────┴───────┼───────┴─────────┘ │
│ │
┌──────┴──────┐ │
│ Qwen3Common │ (shared layers) │
└──────┬──────┘ │
│ │
┌──────┴──────┐ │
│ AudioCommon │ ◄──────────────────────┘
└─────────────┘ (protocols, audio I/O)MOSS Transcribe Diarize
MossTranscribe는 네이티브 CoreML 및 MLX 백엔드로 화자 정보가 있는 타임스탬프 구간을 반환합니다. CoreML은 짧은 녹음용 고정 1,024-token 상태를 사용하고, MLX는 동적 131,072-token 컨텍스트, affine INT5/INT8 디코더 가중치 및 선택적 FP16/INT8 KV 캐시를 사용합니다. 둘 다 스트리밍이 아닌 오프라인 자기회귀 런타임입니다.
VoiceChat 11B
작업 및 참고: 전이중 speech-to-speech. SALM-Duplex: Efficient and Direct Duplex Modeling for Speech-to-Speech Language Model (Interspeech 2025)을 NVIDIA 업스트림 VoiceChat 모델 카드가 인용합니다.
전체 런타임, M5 Pro 48 GB, Release, 80 ms 라이브 주기: 보호된 헤드 INT5의 피크 RSS는 약 8.69 GB이며, 제어된 3회의 전체 파이프라인 RTF는 0.96, 0.96, 0.99였습니다. 최적화된 INT8 성능은 아직 재측정하지 않았습니다.
VoiceChat는 인과 FastConformer 인식, Nemotron-H 전이중 텍스트/함수 채널, 8회 MaskGIT 반복을 사용하는 독립 텍스트 조건부 EAR-TTS 디코더, 22.05 kHz 신경 코덱으로 구성된 완전한 네이티브 MLX 오디오-오디오 경로를 구현합니다. 스트리밍은 계층별 유한 어텐션과 인과 합성곱 캐시를 유지하고, 정상 상태의 8프레임 라이브 코덱 윈도우는 컴파일된 그래프를 사용합니다. 각 80 ms 입력 프레임은 언어 결정, 31개 RVQ 코드, 정확히 1,764개 출력 샘플을 생성합니다. 로더는 완전한 encoder/ + llm/ + tts/ bundle을 요구하며 이전 이해 전용 내보내기를 거부합니다. INT5는 테스트한 M5 Pro에서 평균 RTF 1 미만을 유지하지만 프레임별 p95 여유는 아직 좁습니다.
추론 백엔드
| 백엔드 | 하드웨어 | 모델 |
|---|---|---|
| MLX | Metal GPU | Qwen3-ASR, Qwen3-TTS, CosyVoice3, IndexTTS2, Qwen3.5-Chat, PersonaPlex, VoiceChat 11B, Omnilingual ASR (300M / 1B / 3B / 7B), Cohere Transcribe 2B, Voxtral Mini 3B, Pyannote, Silero VAD, WeSpeaker, MOSS Transcribe Diarize, SpeechBrain ECAPA LID |
| CoreML | Neural Engine | Qwen3-ASR 인코더 (하이브리드), Parakeet TDT, Parakeet EOU 스트리밍, Omnilingual ASR 300M, Kokoro-82M, Qwen3.5-Chat (옵션), Sortformer 화자 분리, DeepFilterNet3, Silero VAD (옵션), WeSpeaker (옵션), MOSS Transcribe Diarize, SpeechBrain ECAPA LID |
| Accelerate | CPU (SIMD) | 오디오 전처리 (STFT, 멜, FFT), 신호 처리 |
모델 웨이트 포맷
MLX 모델은 4비트 또는 8비트 양자화 (그룹 크기 64)를 적용한 safetensors 포맷을 사용합니다. CoreML 모델은 컴파일된 .mlmodelc 포맷을 사용합니다. scripts/의 변환 스크립트가 PyTorch 체크포인트로부터 변환합니다.
Cohere와 Voxtral은 MLX 어파인 INT5 번들도 제공합니다. MLX는 어파인 INT7을 지원하지 않으며, 더 높은 품질의 지원 옵션은 INT8입니다.
| 모델 | 파라미터 | 양자화 | 디스크 크기 |
|---|---|---|---|
| Qwen3-ASR 0.6B (MLX) | 약 600M | 4비트 / 8비트 | 680 MB / 1.0 GB |
| Qwen3-ASR 0.6B (CoreML) | 약 186M (인코더) | INT8 | 약 180 MB |
| Qwen3-ASR 1.7B (MLX) | 약 1.7B | 4비트 / 8비트 | 2.1 GB / 3.2 GB |
| Parakeet-TDT 0.6B (CoreML) | 약 600M | INT8 | 500 MB |
| Whisper Large-v3 Turbo (CoreML) | 809M | FP16 | 1.6 GB |
| MOSS Transcribe Diarize 0.9B (MLX) | 908.5M | FP16 audio + INT5 / INT8 decoder | 987.0 MiB / 1,200.1 MiB |
| MOSS Transcribe Diarize 0.9B (CoreML) | ~900M | FP16 / INT8 block-32 | 1.7 GB / 1.2 GB |
| Parakeet-EOU 120M (CoreML) | 약 120M | INT8 | 약 120 MB |
| Omnilingual-ASR-CTC 300M (CoreML) | 326M | INT8 | 312 MB |
| Omnilingual-ASR-CTC 300M (MLX) | 326M | 4비트 / 8비트 | 193 MB / 342 MB |
| Omnilingual-ASR-CTC 1B (MLX) | 1.01B | 4비트 / 8비트 | 549 MB / 1006 MB |
| Omnilingual-ASR-CTC 3B (MLX) | 약 3B | 4비트 / 8비트 | 1.71 GB / 3.16 GB |
| Omnilingual-ASR-CTC 7B (MLX) | 약 7B | 4비트 / 8비트 | 3.55 GB / 6.63 GB |
| Cohere Transcribe 2B (MLX) | 2B | FP16 / INT5 / INT8 | 3.85 / 1.62 / 2.25 GiB |
| Voxtral Mini 3B 2507 (MLX) | 3B | FP16 / INT5 / INT8 | 8.71 / 3.77 / 5.18 GiB |
| Qwen3-ForcedAligner 0.6B (MLX) | 약 600M | 4비트 / 8비트 | 979 MB / 1.4 GB |
| Qwen3-ForcedAligner 0.6B (CoreML) | 약 600M | INT4 / INT8 | 630 MB / 1.0 GB |
| Qwen3-TTS 0.6B (MLX) | 약 600M | 4비트 / 8비트 | 1.7 GB / 2.4 GB |
| Qwen3-TTS 1.7B (MLX) | 약 1.7B | 4비트 / 8비트 | 3.2 GB / 4.8 GB |
| CosyVoice3 0.5B (MLX) | 약 500M | 4비트 LLM | 약 1.2 GB |
| IndexTTS2 expanded bundle (MLX) | 1.5B-class | FP16 + auxiliary models | ~4.8 GB |
| Kokoro-82M (CoreML) | 82M | INT8 (1 버킷) | 약 89 MB |
| Qwen3.5-Chat 0.8B (MLX) | 약 800M | INT4 | 418 MB |
| Qwen3.5-Chat 0.8B (CoreML) | 약 800M | INT8 | 981 MB |
| PersonaPlex 7B (MLX) | 약 7B | 4비트 / 8비트 | 4.9 GB / 9.1 GB |
| VoiceChat 11B (MLX) | ~11B | INT5 / INT8 | 8.56 GB / 12.11 GB |
| Pyannote VAD (MLX) | 약 1.49M | float32 | 약 5.7 MB |
| Silero VAD v5 | 약 309K | float32 | 약 1.2 MB (MLX 및 CoreML) |
| WeSpeaker ResNet34 | 약 6.6M | float32 | 약 25 MB (MLX 및 CoreML) |
| SpeechBrain ECAPA VoxLingua107 | 21.25M | FP16 | ~40.6 MiB (MLX) / ~40.8 MiB (CoreML) |
| ReDimNet2-B6 | 12.3M | float16 | 약 25 MiB (CoreML) |
| Pyannote Community-1 (CoreML) | 8.35M | float32 + native VBx | ~32 MB |
| Sortformer (CoreML) | — | float16 | 약 50 MB |
| DeepFilterNet3 (CoreML) | 약 2.1M | FP16 | 약 4.2 MB |
| LocalVQE v1.4-AEC (CoreML + C++) | 200K + 2,742 | FP16 + FP32 | 약 732 KB |
성능 최적화
- MLX compile() — 자기회귀 루프를 위한 커널 융합. Talker는
compile(shapeless: true)를, Code Predictor는 고정 캐시 크기와 함께compile(shapeless: false)를 사용합니다. - Metal 셰이더 라이브러리 — 사전 컴파일된 metallib로 약 5배의 JIT 컴파일 오버헤드를 회피합니다.
scripts/build_mlx_metallib.sh로 빌드합니다. - 청크 단위 코덱 디코딩 — TTS 디코더는 GPU 타임아웃을 피하기 위해 25 프레임 청크와 10 프레임 컨텍스트 오버랩으로 오디오를 처리합니다.
- 배치 2배 CFG — CosyVoice3 DiT는 조건부 + 무조건부를 함께 배치 처리하여 flow matching 패스를 절반으로 줄입니다.
- 융합 RoPE — 수동 회전 대신 Metal 커널 기반
MLXNN.RoPE를 사용합니다. - BN 융합 — WeSpeaker 배치 정규화는 변환 시 Conv2d 가중치에 융합됩니다.
오디오 처리
모든 오디오 I/O는 Float32 PCM을 사용합니다. 내부 리샘플링이 포맷 변환을 처리합니다:
| 모델 | 요구 샘플레이트 | 포맷 |
|---|---|---|
| Qwen3-ASR | 16 kHz | 모노 Float32 |
| Cohere Transcribe 2B | 16 kHz | Mono Float32 |
| Voxtral Mini 3B | 16 kHz | Mono Float32 |
| Qwen3-TTS | 24 kHz 출력 | 모노 Float32 |
| CosyVoice3 | 24 kHz 출력 | 모노 Float32 |
| Kokoro-82M | 24 kHz 출력 | 모노 Float32 |
| PersonaPlex | 24 kHz I/O | 모노 Float32 |
| Pyannote VAD | 16 kHz | 모노 Float32 |
| Silero VAD | 16 kHz | 모노 Float32 |
| WeSpeaker | 16 kHz | 모노 Float32 |
| SpeechBrain ECAPA LID | 16 kHz | Mono Float32 |
| ReDimNet2-B6 | 16 kHz | 모노 Float32 |
| DeepFilterNet3 | 48 kHz | 모노 Float32 |
소스 구조
Sources/
AudioCommon/ 공유 프로토콜, 오디오 I/O, 시스템 출력 캡처(SystemAudioTap),
HuggingFace 다운로더, SentencePieceModel(protobuf 리더)
MLXCommon/ MLX 유틸리티: 웨이트 로딩, QuantizedLinear 헬퍼,
SDPA 멀티헤드 어텐션 헬퍼, metal budget
Qwen3Common/ 공유 모델 컴포넌트 (KV 캐시, RoPE, 양자화)
Qwen3ASR/ Qwen3-ASR 음성-텍스트 변환
ParakeetASR/ Parakeet TDT 음성-텍스트 변환 (CoreML)
ParakeetStreamingASR/ Parakeet EOU 120M 스트리밍 받아쓰기 (CoreML)
OmnilingualASR/ Meta wav2vec2 + CTC, 1,672개 언어
(CoreML 300M + MLX 300M / 1B / 3B / 7B)
CohereTranscribeASR/ Cohere Transcribe 2B speech-to-text (MLX)
VoxtralASR/ Voxtral Mini 3B speech-to-text (MLX)
Qwen3TTS/ Qwen3-TTS 텍스트-음성 변환
CosyVoiceTTS/ CosyVoice3 텍스트-음성 변환
KokoroTTS/ Kokoro-82M 텍스트-음성 변환 (CoreML)
Qwen3Chat/ Qwen3.5-0.8B 온디바이스 LLM 채팅 (MLX + CoreML)
PersonaPlex/ PersonaPlex 음성-음성 변환
SpeechVAD/ VAD (Silero + Pyannote), 화자 분리, 화자 임베딩
SpeechLanguageID/ 음성 언어 식별(SpeechBrain ECAPA, MLX + CoreML, 107개 레이블)
SpeechEnhancement/ DeepFilterNet3 노이즈 억제 (CoreML)
SourceSeparation/ Open-Unmix HQ / UMX-L + HTDemucs (Demucs v4) music source separation (MLX, 4 stems)
MAGNeTMusicGen/ MAGNeT text-to-music generation (MLX, 30 s @ 32 kHz, INT4/INT8)
VoxCPM2TTS/ VoxCPM2 text-to-speech (MLX, 48 kHz, voice cloning + voice design)
IndexTTS2TTS/ IndexTTS2 voice cloning (MLX, semantic GPT + emotion/tempo/pause control + S2Mel + BigVGAN)
VibeVoiceTTS/ VibeVoice long-form / multi-speaker TTS (MLX, EN/ZH)
MADLADTranslation/ MADLAD-400 many-to-many translation (MLX, 400+ languages)
AudioCLILib/ CLI 명령 구현
AudioCLI/ CLI 진입점
scripts/ 모델 변환 (PyTorch → MLX/CoreML), 벤치마킹
Tests/ 단위 및 통합 테스트
Examples/ 데모 앱 (PersonaPlexDemo, SpeechDemo)