OpenAI 오디오 API¶
mlxcel은 OpenAI 호환 음성 합성, 전사, 번역 경로를 구현합니다. 오디오 체크포인트는 오디오 전용 서버 프로세스를 점유합니다. 음성-텍스트 변환(STT)에는 Whisper를, 텍스트-음성 변환(TTS)에는 Kokoro를 사용하고 채팅이나 텍스트 생성은 별도 프로세스에서 실행하십시오.
엔드포인트¶
| 메서드 | 경로 | 기능 |
|---|---|---|
POST | /v1/audio/speech | Kokoro TTS. JSON 입력, WAV 출력 |
POST | /v1/audio/transcriptions | Whisper 음성 전사 |
POST | /v1/audio/translations | Whisper 영어 번역 |
각 route는 /audio/speech처럼 /v1 prefix를 뺀 별칭도 제공합니다.
로드한 체크포인트가 요청한 기능을 제공하지 않으면 요청을 검증한 뒤 HTTP 501을 반환합니다.
전이중(full-duplex) 음성 대 음성 모델인 Nemotron VoiceChat은 이 경로를 사용하지 않고 WebSocket으로 서비스합니다. Realtime VoiceChat API를 참고하세요.
오디오 서버 시작¶
Whisper STT¶
체크포인트는 model_type: "whisper"를 선언하고 config.json, tokenizer.json, SafeTensors 가중치를 포함해야 합니다. 네이티브 MLX 키 배열과 Hugging Face WhisperForConditionalGeneration 키 배열을 모두 지원합니다.
현재 입력은 WAV만 지원합니다. mlxcel은 PCM16 또는 float32 오디오를 모노로 변환하고 16 kHz로 리샘플링하며, 30초보다 긴 입력은 연속 구간으로 나눕니다. Whisper는 현재 비양자화 fp16/f32 체크포인트와 greedy decoding만 지원합니다. Beam search, timestamp, VAD chunking, MP3, FLAC은 아직 지원하지 않습니다.
Kokoro TTS¶
Kokoro는 istftnet 설정 블록 또는 kokoro-v1_0.safetensors로 감지합니다. 디렉터리에 config.json, Kokoro 가중치, voices/*.safetensors 음성 팩이 있어야 합니다. Kokoro 체크포인트에는 토크나이저 파일이 필요 없는데, 음소 어휘를 config.json에서 읽기 때문입니다. 이런 서버에서 /tokenize, /detokenize, /apply-template은 생성 라우트와 마찬가지로 501을 반환합니다. vocab이나 가중치 파일이 빠진 경우처럼 체크포인트를 로드할 수 없으면, TTS 슬롯 없이 도는 대신 서버가 기동 단계에서 종료합니다.
기본 음성은 af_heart입니다. 안전한 음성 이름은 voices/<name>.safetensors를 선택하며, 알 수 없거나 안전하지 않은 이름은 기본값으로 대체됩니다. 내장 grapheme-to-phoneme front end는 미국 영어용입니다. 입력은 4,096자에서 잘리고 acoustic model은 최대 510개 phoneme token을 사용합니다. 출력 형식은 WAV만 지원합니다.
음성 합성¶
curl -s http://localhost:8080/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{"model":"kokoro","input":"Hello from mlxcel.","voice":"af_heart","speed":1.0,"response_format":"wav"}' \
--output speech.wav
| JSON 필드 | 필수 | 기본값 | 설명 |
|---|---|---|---|
model | 예 | - | API 호환용 식별자. 실제로는 서버에 로드한 체크포인트를 사용합니다 |
input | 예 | - | 합성할 텍스트 |
voice | 아니요 | af_heart | Kokoro 음성 팩 이름 |
response_format | 아니요 | wav | wav만 허용합니다 |
speed | 아니요 | 1.0 | 양의 유한 duration scale. 1보다 크면 더 빠르게 합성합니다 |
성공 응답은 PCM16 RIFF 본문을 가진 audio/wav입니다.
전사와 번역¶
두 경로 모두 multipart/form-data를 받습니다.
curl -s http://localhost:8080/v1/audio/transcriptions \
-F file=@recording.wav \
-F model=whisper \
-F language=ko \
-F response_format=json
| Multipart 필드 | 필수 | 기본값 | 설명 |
|---|---|---|---|
file | 예 | - | 최대 25 MiB의 WAV 오디오 |
model | 아니요 | - | provider로 전달하는 호환용 식별자 |
language | 아니요 | 자동 | ISO 639-1 원문 언어 힌트 |
response_format | 아니요 | json | json, text, verbose_json |
temperature | 아니요 | provider 기본값 | 유한 부동소수점 sampling temperature |
json은 {"text":"..."}를, text는 UTF-8 일반 텍스트를 반환합니다. verbose_json은 값이 있을 때 language와 duration을 추가합니다. 번역 경로는 같은 요청·응답 형식을 사용하지만 Whisper에 영어 출력을 요청합니다.
수락 제어¶
오디오 작업은 MLX를 소유한 단일 worker thread에서 직렬화됩니다. 다음 서버 옵션으로 메모리 사용량과 대기 시간을 제한합니다.
| CLI 옵션 | 환경 변수 | 기본값 | 효과 |
|---|---|---|---|
--audio-queue-depth <N> | MLXCEL_AUDIO_QUEUE_DEPTH | 8 | 대기 가능한 오디오 명령 수. 가득 차면 503을 반환합니다 |
--audio-request-timeout-secs <N> | MLXCEL_AUDIO_REQUEST_TIMEOUT_SECS | 120 | 호출자 대기 제한. 만료되면 504를 반환하지만 이미 실행 중인 작업은 취소하지 않습니다 |
각 업로드가 최대 25 MiB이므로 기본값에서 대기 중인 STT payload는 실행 중 요청 외에 약 200 MiB를 보유할 수 있습니다.
오류와 제한¶
| 상태 | 의미 |
|---|---|
400 | 잘못된 JSON/multipart, 파일 누락, 미지원 형식 또는 유효하지 않은 오디오 |
413 | 업로드가 25 MiB를 초과함 |
500 | 서버 측 실패(server_error): 오디오 worker 패닉, 추론 실패 또는 응답 생성 실패 |
501 | 로드한 체크포인트가 STT 또는 TTS를 제공하지 않음 |
503 | 오디오 큐 또는 생성 수락 큐가 가득 참 |
504 | 오디오 worker 응답 시간 초과 |
Bearer 인증을 설정했다면 다른 API 엔드포인트와 마찬가지로 오디오 경로에도 적용됩니다.