Maskinöversättning · Engelskt original
Speech Server
Native Apple runtime · PocketTTS
PocketTTS lägger till infödd CoreML talsyntes till speech-swift. Alla steg som standard för CPU-bara avrättning. Den engelska Alba förinställda strömmar 1,920-provramarna vid 24 kHz (80 ms per ram).
Använd pocket-tts med röst alba. Streaming HTTP kräver PCM; WebSocket avger ljuddeltagare. De befintliga standardmodellerna är oförändrade.
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 är en lokal HTTP + WebSocket-server som exponerar varje Soniqo modell genom en enkel REST API, plus en OpenAI Realtime API-kompatibel WebSocket på /v1/realtimeDet fartyg i samma Homebrew flaska som speech CLI - brew install speech sjunker både på din PATH.
Installera och köra
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)
Command-line flaggor
| Flaggan | Standard | Beskrivning |
|---|---|---|
--host | 127.0.0.1 | Bind adress. Ändra till 0.0.0.0 för att avslöja på LAN. |
--port | 8080 | TCP-port. |
--preload | off | Ladda alla modeller ivrigt vid start. Slower boot (~ 30-60 s) men noll första begäran latens. |
Modeller laddas ner på första användningen och cachas i ~/Library/Caches/qwen3-speech/. Den första begäran om en viss modell betalar nedladdningen + lastkostnaden (30 s – 2 min beroende på modellstorlek); efterföljande förfrågningar är varma.
REST slutpunkter
POST /transcribe - Tal-till-text
Accepterar antingen en rå WAV kropp eller ett JSON-kuvert med base64-encoded ljud.
# 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 - Text-till-tal
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
Response kropp är en WAV blob. Stöds engine värden: qwen3 (standard), cosyvoice, kokoro.
POST /respond - Tal-till-tal
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
Runs PersonaPlex 7B — tal i, tal ut. Transkript returneras som en X-Response-Text header. Se PersonaPlex guide för röstförinställda namn.
POST /enhance - Talförbättringar
curl -X POST http://127.0.0.1:8080/enhance \
-H "Content-Type: audio/wav" \
--data-binary @noisy.wav \
--output clean.wav
DeepFilterNet3 vid 48 kHz. Input försänds om det behövs.
GET /health - Liveness sond
curl http://127.0.0.1:8080/health
# {"status":"ok"}
HTTP- och realtids WebSocket-test väntar på /health för att returnera HTTP 200 med {"status":"ok"}, med en 10-sekund start deadline. Startup fel misslyckas testinställning, och teardown väntar serverstängning innan återanvändning av sin port.
WebSocket: /v1/realtime
Drop-in kompatibel med OpenAI realtid API samma JSON-evenemangsschema (JSON)session.update, input_audio_buffer.append, response.create, response.audio.delta, ...) med base64-encoded PCM16 ljud på 24 kHz. Kunder skrivna mot OpenAI realtid SDK arbetar mot speech-server utan kodändringar (bara växla WebSocket URL).
Automatiska svängningar med server VAD
Manuell input_audio_buffer.commit förblir standard. Set session.turn_detection till server_vad för att köra Silero VAD på servern och automatiskt transkribera varje färdigt tal. Prefix ljud behålls, idle buffering stannar bunden, och en kontinuerlig vändning är
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 exempel
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 exempel
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())
Distributionsnoter
- Ingen auth som standard.
speech-serverbinder127.0.0.1och litar på varje uppmaning. Lägg den bakom en omvänd proxy (Caddy, nginx, tailscale) om du exponerar den bortom lokalhost. - Modeller är latfyllda. Första förfrågan på
/transcribeutlöser ASR nedladdning + belastning (~700 MB, 30-60 s). Använd--preloadför noll kallstart men långsammare start. - Ingen strömmande transkription ännu.
POST /transcribeförväntar sig hela WAV framsidan. Använd/v1/realtimeför streaming. - Systemd/lanserad. Ingen serviceenhet fartyg idag. En vanlig
nohup speech-server &eller din vanliga process handledare fungerar.
Källa
- Källor/AudioServer — Hummingbird-baserad HTTP-router, lat modellregister,
/v1/realtimeWebSocket-handtagare. - Källor/AudioServerCLI --
@mainingångspunkt, argument parser. - Uppströms: OpenAI Realtime API referens.
Lokal inhemsk slutsats
För 12B, upprepade intilliggande verktygslåda stängning markörer omedelbart efter en fullständig, validerad samtal konsumeras med det samtalet. De skapar inte ett annat samtal eller ändrar sina argument. Standalone markörer och missbildade argument förbli fel; E4B behåller strikt hantering.
För att behålla misslyckade inhemska chattförfrågningar, ange failureCaptureDirectory i slutsatsen manifest. Capture är av som standard. Katalogen måste neka grupp och annan åtkomst; nya kataloger använder 0700 och misslyckande filer använder 0600Filer inkluderar den exakta förfrågan organ, begära ID och fel. Slutförda 12B generationer behåller också de återgivna snabb, token ID, rå utgång och stoppa anledning innan parsing. E4B fel har ingen rå generation rekord. Dessa lokala filer innehåller konversation och verktyg innehåll; HTTP fel och framgångsrika förfrågningar inte inkludera dem.
Optionell agentDirectory laddar en iscensatt Gemma 4 12B Unified INT4 textmodell tillsammans E4B. Använd modell: "gemma4-12b-it"för chatt med inhemska verktyg, resultathistorik och avbokning. E4B förblir tillgänglig för andra förfrågningar. Gemma4UnifiedChat Använder Pinned MLX text implementering och släpper varje förfrågan KV cache. Response parsing tar bort kanalavgränsare från returnerad text. Föräldralösa verktygsuppsägare avvisas som missbildade svar. Misslyckade icke-strömmande förfrågningar loggar deras begäran ID, operation och underliggande fel i serverprocessen. Gemma 4 12B, verktygsmeddelandeinnehåll bevarar JSON som text, som matchar checkpoint chat mall.
Källan bygger acceptera --inference-manifest modeller.json att ladda iscensatt Gemma 4 E4B INT4, VoxCPM2full, full Whisper Large-v3och Silero VADDenna tjänst startar offline och avvisar oförenliga modellidentiteter.
Den infödda tjänsten serialiserar chatt, syntes och transkription; lätt VAD har separat strömstatus. Gemma prefill utvärderar varje 256-token sats innan nästa, begär KV-status släpps, och MLX cache är capped på 128 MiB med en 20 GiB allokatorgräns.
Tal med ström: sann returnerar NDJSON ljudhändelser vid 48 kHz, följt av gjort eller fel. Avbryt genom requestID på /v1 / slutsats / avbryt. GET /v1/inference/capabilities och/v1/Inference/provenance report model identities, parameter dtypes, asset pins och minnesräknare.
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"
}Valfri modell ägande
SpeechRuntime tillhandahåller delad lastning, avbokningsbar FIFO-antagning och serialiserad avrättning. Qwen3ASRRuntime väljer MLX eller full CoreML genom explicita deskriptorer; inhemska API och CLI-flaggor finns tillgängliga.
Ljudservern har ett genomförandetillstånd genom varje fullständig förfrågan, inklusive strömmat utgång, med upp till 32 förfrågningar som väntar. ASR fel ger HTTP-fel eller WebSocket felhändelser; giltiga tomma utskrifter förblir framgångsrika. Playback bevarar överflödesprover. Cachade modeller och pending uppspelningsljud upptar fortfarande minne.
Voxtral TTS
Voxtral 4B TTS 2603 körs lokalt på Apple Silicon genom Voxtral TTS-modulen: 20 förinställda röster, nio språk och 24 kHz monotal.
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.wavFörinställda röster endast; referens-audio kloning är otillgänglig. Audio utgångsströmmar genom SDK, CLI, WebSocket och HTTP PCM. Supply the fullständig input text up front. Model vikter använder CC BY-NC 4.0.
Gemma 4 12B prompt prefill
Den infödda inferensservicen laddar den iscensatta Gemma 4 12B Unified INT4 modell med agentDirectoryVälj det för chatt med modell ID gemma4-12b-it.
Gemma 4 12B prefill fyller KV-status i partier på upp till 256 tokens och beräknar de första provtagningsloggarna från det slutliga snabbtoken. Intermediate vocabulary prognoser är hoppade. Förfrågan KV cache släpps efter avslutad eller avbokning.
Ett oförändrat system / verktyg prefix kan förbli cachade i kompletta 256-token block. Varje förfrågan sträcker en separat arbetskopia. Användarmeddelanden, konversationshistorik och verktygsresultat går aldrig in i den behållna ögonblicksbilden. SPEECH_SWIFT_GEMMA4_PREFIX_CACHE_MB begränsa behållna MiB, eller 0 att inaktivera återanvändning. clearPrefixCache() släpper snapshot. HTTP-rapporter återanvända tokens i cachedPrefixTokens; Provenance records gemma4_12b_prefix_cache_budget_bytesKalla förfrågningar behandlar fortfarande hela prompten.
Native Gemma verktygshistorik håller verktygsrespons och en assistent fortsättning i samma modellvridning. Ett efterföljande användarmeddelande stänger den modellen vändning innan nästa användarvridning öppnas. Skicka varje resultat med sin ursprungliga toolCallID.