Maskinoversettelse · Engelsk original
Speech Server
Native Apple Runtime · PocketTTS
PocketTTS legger til opprinnelig CoreML talesyntese til speech-swift. Alle stadier er standard til CPU-beskyttelse. Den engelske Alba-forhåndsinnstilte strømmer 1.920-prøverammer ved 24 kHz (80 ms per ramme).
Bruk lommeknepninger med stemmealba. Strømming HTTP krever PCM; WebSocket sender ut lyddeltaer. De eksisterende standardmodellene er uendret.
curl http://localhost:8080/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{"model":"pocket-tts","voice":"alba","input":"Hello world.","response_format":"pcm","stream":true}' \
-o hello.pcmspeech-server er en lokal HTTP + WebSocket server som avslører hver Soniqo modell gjennom en enkel REST API, pluss en OpenAI Realtime API-kompatible WebSocket på /v1/realtime. Det skip i samme Homebrew flaske som speech CLI — brew install speech dråper på PATH.
Installer og kjør
brew install speech
speech-server --port 8080
# Starting server on http://127.0.0.1:8080
# Endpoints:
# POST /transcribe - Speech-to-text (WAV body or JSON with audio_base64)
# POST /speak - Text-to-speech (JSON: {text, engine?, language?})
# POST /respond - Speech-to-speech (WAV body, voice/max_steps via query)
# POST /enhance - Speech enhancement (WAV body)
# GET /health - Health check
# WS /v1/realtime - OpenAI Realtime API (JSON events, base64 PCM16 audio)
Kommandolinjeflagg
| Flag | Standard | Beskrivelse |
|---|---|---|
--host | 127.0.0.1 | Bindeadresse. Endre til 0.0.0.0 for å eksponere på LAN. |
--port | 8080 | TCP-port. |
--preload | av | Last alle modeller ivrig ved oppstart. Slower boot (~30-60 s) men null første-spørre latens. |
Modellene lastes ned ved første bruk og cached i ~/Library/Caches/qwen3-speech/. Den første forespørselen om en gitt modell betaler nedlastingen + belastningskostnaden (30 s- 2 min avhengig av modellstørrelse); påfølgende forespørsler er varme.
REST endepunkter
POST /transcribe — Tale-til-tekst
Aksepterer enten en rå WAV kropp eller en JSON konvolutt med base64-encoded lyd.
# WAV body (preferred — lower overhead)
curl -X POST http://127.0.0.1:8080/transcribe \
-H "Content-Type: audio/wav" \
--data-binary @recording.wav
# JSON with base64
curl -X POST http://127.0.0.1:8080/transcribe \
-H "Content-Type: application/json" \
-d '{"audio_base64":"'"$(base64 -i recording.wav)"'","language":"en"}'
Svar: {"text": "…", "language": "en", "confidence": 0.93}.
POST /speak — Tekst-til-speech
curl -X POST http://127.0.0.1:8080/speak \
-H "Content-Type: application/json" \
-d '{"text":"Hello, world!","engine":"kokoro","language":"en"}' \
--output hello.wav
Svarkroppen er en WAV blob. Støttet engine verdier: qwen3 (standard), cosyvoice, kokoro.
POST /respond — Tale-to-speech
curl -X POST "http://127.0.0.1:8080/respond?voice=en_female_calm&max_steps=256" \
-H "Content-Type: audio/wav" \
--data-binary @question.wav \
--output answer.wav
Kjører PersonaPlex 7B - tale i, tale ut. Transkript returneres som en X-Response-Text-topptekst. Se PersonaPlex for stemmeforvalgte navn.
POST /enhance — Taleforbedring
curl -X POST http://127.0.0.1:8080/enhance \
-H "Content-Type: audio/wav" \
--data-binary @noisy.wav \
--output clean.wav
DeepFilterNet3 ved 48 kHz. Inngang blir reprøvet om nødvendig.
GET /health — Levetidssonde
curl http://127.0.0.1:8080/health
# {"status":"ok"}
HTTP og sanntid WebSocket-testene venter på /health for å returnere HTTP 200 med {"status":"ok"}, med en 10 sekunders oppstartsfrist. Oppstartsfeil mislykkes testoppsett, og nedbrytning venter på at serveren avsluttes før den gjenbruker porten.
WebSocket: /v1/realtime
Drop-in-kompatible med OpenAI Realtime API — det samme arrangementsskjemaet JSON (session.update, input_audio_buffer.append, response.create, response.audio.delta, ...) med base64-encoded PCM16-lyd på 24 kHz. Kunder skrevet mot OpenAI s Realtime SDK arbeid mot speech-server uten kodeendringer (bare bytte WebSocket-URL).
Automatiske svinger med serveren VAD
Manuell input_audio_buffer.commit forblir standard. Set session.turn_detection til server_vad å kjøre Silero VAD på serveren og automatisk overføre hver fullført taletur. Prefiks lyd blir beholdt, inaktiv buffering forblir bundet, og en kontinuerlig aktiv tur er tvangslukket på det konfigurerte maksimum.
ws.send(JSON.stringify({
type: "session.update",
session: {
turn_detection: {
type: "server_vad",
threshold: 0.5,
prefix_padding_ms: 300,
silence_duration_ms: 500,
max_turn_duration_ms: 120000
}
}
}));
// Event order for each detected turn:
// input_audio_buffer.speech_started
// input_audio_buffer.speech_stopped
// input_audio_buffer.committed
// conversation.item.input_audio_transcription.completed
// Set turn_detection to null (or { type: "none" }) for manual commits.
JavaScript eksempel
const ws = new WebSocket("ws://127.0.0.1:8080/v1/realtime");
ws.onopen = () => {
ws.send(JSON.stringify({
type: "session.update",
session: { modalities: ["audio", "text"] }
}));
// Stream PCM16 mono 24kHz audio from the mic:
const audioBase64 = await capturePCM16Chunk();
ws.send(JSON.stringify({
type: "input_audio_buffer.append",
audio: audioBase64
}));
ws.send(JSON.stringify({ type: "response.create" }));
};
ws.onmessage = ev => {
const msg = JSON.parse(ev.data);
if (msg.type === "response.audio.delta") {
playPCM16Base64(msg.delta);
}
};
Python eksempel
import asyncio, base64, json, wave, websockets
async def main():
async with websockets.connect("ws://127.0.0.1:8080/v1/realtime") as ws:
await ws.send(json.dumps({"type": "session.update",
"session": {"modalities": ["audio", "text"]}}))
with wave.open("question.wav", "rb") as wav:
pcm16 = wav.readframes(wav.getnframes())
await ws.send(json.dumps({"type": "input_audio_buffer.append",
"audio": base64.b64encode(pcm16).decode()}))
await ws.send(json.dumps({"type": "response.create"}))
async for raw in ws:
msg = json.loads(raw)
if msg["type"] == "response.audio.delta":
open("answer.pcm", "ab").write(base64.b64decode(msg["delta"]))
elif msg["type"] == "response.done":
break
asyncio.run(main())
Utdelingsnotater
- Ingen auth som standard.
speech-serverbinder127.0.0.1og stoler på hver samtale. Sett den bak en omvendt proxy (Caddy, nginx, haleskala) hvis du avslører den utenfor lokalhost. - Modeler er lat-lastet. Første forespørsel for
/transcribeutløser ASR laste ned + belastning (~ 700 MB, 30-60 s). Bruk--preloadfor null kald-start men langsommere oppstart. - Ingen streaming trankripsjon ennå.
POST /transcribeforventer det hele WAV opp foran. Bruk/v1/realtimefor streaming. - Systemt / lansert. Ingen tjenesteenhet skip i dag. En vanlig
nohup speech-server &eller din vanlige prosessleder fungerer.
Kilde
- Kjelder/AudioServer — Hummingbird-basert HTTP router, lat modell register,
/v1/realtimeWebSocket handsamar. - Kjelder/AudioServerCLI —
@maininngangspunkt, argumenttolker. - Upstream: OpenAI Realtime API referanse.
Lokalt innfødt inferens
For 12B, gjentatte tilstøtende verktøy-kall stenge markører umiddelbart etter en fullstendig, validert samtale er forbrukt med det anropet. De oppretter ikke et annet anrop eller endrer argumentene. Standalone markører og feilaktige argument forblir feil; E4B beholder streng håndtering.
For å beholde feil innfødte chatforespørsler, sett failureCaptureDirectory i inferien manifest. Fange er av som standard. Katalogen må nekte gruppe og annen tilgang; nye kataloger bruker 0700 og feilfiler bruker 0600. Filene inkluderer nøyaktige forespørselsorgan, be om ID og feil. Fullførte 12B generasjoner beholder også den gjengitte spørrings-, token-ID-er, rå utgangs- og stoppgrunn før tolking. E4B feil har ingen rågenerasjonspost. Disse lokale filene inneholder konversasjon og verktøyinnhold; HTTP-feil og vellykket forespørsler inkluderer dem ikke.
Valgfritt agentDirectory laster en scened Gemma 4 12B-samlede INT4 tekstmodell ved siden av E4B. Bruk modell: .gemma4-12b-itFor chat med innfødte verktøy, resultathistorie og kansellering. E4B Forblir tilgjengelig for andre forespørsler. Gemma4UnifiedChat bruk av festet MLX tekst implementasjon og frigjør hver forespørsels KV cache. Response parsing fjerner kanalskillerne fra returnert tekst. Orphanede verktøy-kall terminatorer blir avvist som feilaktige svar. Feil ikke-strømsforespørsler logger deres forespørsler ID, operasjon og underliggende feil i serverprosessen. For Gemma 4 12B, verktøy-melding innhold bevarer JSON som tekst, samsvarer med checkpoint chat malen.
Kildebygg aksepterer --inference-manifest modeller.json å laste iscenelagt Gemma 4 E4B INT4, VoxCPM2, full Whisper Large-v3, og Silero VAD. Denne tjenesten starter offline og avviser ikke-kompatibel modellidentiteter.
Den opprinnelige tjenesten serialiserer chat, syntese og transkripsjon; lett VAD har separat stream-tilstand. Gemma forhåndsfylling vurderer hver 256-token batch før start den neste, ber KV-tilstanden frigjøres, og MLX cacheen er caped på 128 MiB med en 20 GiB allocator grense.
Tal med stream: ekte returnerer NDJSON-lydhendelser ved 48 kHz, etterfulgt av gjort eller feil. Avbryt ved forespørselID på /v1/inferens/cancel. GET /v1/inference/capabilities og /v1
speech-server --inference-manifest models.json --port 8080{
"runtimeRevision": "your-source-revision",
"gemmaDirectory": "/models/gemma4-e4b-it-int4",
"voxDirectory": "/models/voxcpm2-unquantized",
"whisperDirectory": "/models/whisper-large-v3-coreml",
"vadDirectory": "/models/silero-vad-coreml"
}Valgfritt modelleierskap
SpeechRuntime gir delt lasting, kancellerbar FIFO-opptak og seriealisert utførelse. Qwen3ASRRuntime velger MLX eller full CoreML gjennom eksplisitte deskriptorer; innfødte API-er og CLI-flagg forblir tilgjengelige.
Lydserveren har én utføringstillatelse gjennom hver fullstendige forespørsel, inkludert streamingutgang, med opptil 32 forespørsler som venter. ASR feil produserer HTTP-feil eller WebSocket feilhenvisninger; gyldige tomme transkripsjoner forblir vellykket. Avspilling bevarer overflytprøver. Cachede modeller og avventende lyd fortsatt okkupasjonsminne.
Voxtral TTS
Voxtral 4B TTS 2603 kjører lokalt på Apple Silicon gjennom Voxtral TTS-modulen: 20 forhåndsinnstilte stemmer, ni språk og 24 kHz mono tale.
curl http://localhost:8080/v1/audio/speech \
-H 'Content-Type: application/json' \
-d '{"model":"voxtral-tts","input":"Hello, welcome to Voxtral.","voice":"casual_male","response_format":"wav"}' \
-o hello.wavBare forhåndsinnstillinger; referanse-audio kloning er utilgjengelig. Lydutgangsstrømmer gjennom SDK, CLI, WebSocket og HTTP PCM. Gi den komplette inngangsteksten opp foran. Modellvekter bruker CC BY-NC 4.0.
Gemma 4 12B-førfylling
Den opprinnelige inferenstjenesten laster den iscenelagte Gemma 4 12B Unified INT4 modellen ved hjelp av agentDirectory. Velg den for chat med modellen ID gemma4-12b-it.
Gemma 4 12B påfyller KV-tilstand i partier på opptil 256 token og beregner de første prøvetakingsloggene fra den endelige hurtigsymbolet. Mellomliggende ordforrådsprojeksjoner hoppes over. Forespørselens KV-buffer frigjøres etter fullføring eller kansellering.
Et uendret system/verktøyprefiks kan forbli cached i fullstendig 256-token blokker. Hver forespørsel utvider en separat arbeidskopi. Brukermeldinger, samtalehistorikk og verktøyresultater kan aldri gå inn i det beholdte øyeblikksbildet. Sett SPEECH_SWIFT_GEMMA4_PREFIX_CACHE_MB for å begrense beholdt MBB, eller 0 for å deaktivere gjenbruk. clearPrefixCache() frigjør øyeblikksbilde. HTTP-rapporter gjenbrukte poliner i cachedPrefixTokens; dokumenteringsposter gemma4_12b_prefix_cache_budget_bytes. Kalde forespørsler prosesserer fortsatt i full kontakt.
Native Gemma verktøyloggen holder verktøyresponsene og en assistent fortsetter i samme modell. En etterfølgende brukermelding lukker den modellens sving før neste brukersving. Send hvert resultat med sin opprinnelige toolCallID.