Maskinoversættelse · Engelsk original

Speech Server

Indfødt Apple runtime · PocketTTS

PocketTTS tilføjer indfødt CoreML talesyntesse til speech-swift. Alle trin standard til CPU- kun udførelse. Den engelske Alba forudindstillet streams 1,920- prøvesæt på 24 kHz (80 ms per frame).

Brug af Swift og CLI

Brug pocket- tts med voice alba. Streaming HTTP kræver PCM; WebSocket udsender audio deltas. De eksisterende standardmodeller er uændrede.

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.pcm

speech-server er en lokal HTTP + WebSocket server, der udsætter hver Soniqo model gennem en simpel REST API, plus en OpenAI Realtime API- kompatibel WebSocket på /v1/realtime. Det skibe i samme Homebrew flaske som speech CLI - brew install speech Smid begge på din PATH.

Installere og køre

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)

Kommandolinjeflag

FlagStandardVarebeskrivelse
--host127.0.0.1Bindeadresse. Skift til 0.0.0.0 at afsløre på LAN.
--port8080TCP port.
--preloadafIndlæs alle modeller ivrigt ved opstart. Lancer boot (~ 30- 60 s), men nul first-request latency.

Modeller downloades ved første brug og cache i ~/Library/Caches/qwen3-speech/. Den første anmodning om en given model betaler download + belastning omkostninger (30 s - 2 min afhængigt af modelstørrelse); efterfølgende anmodninger er varme.

REST endepunkter

POST /transcribe - Speech- to- tekst

Accepterer enten en rå WAV krop eller en JSON kuvert 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- to- tale

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 body er en WAV blob. Understøttede engine værdier: qwen3 (standard) cosyvoice, kokoro.

POST /respond - Tale-til-tale

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

Kører PersonaPlex 7B - tale ind, tale ud. Udskrift returneres som en X-Response-Text header. Se PersonaPlex guide for stemmenavne.

POST /enhance - Ophøjelse af tale

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. Input rekompileres om nødvendigt.

GET /health - Liveness probe

curl http://127.0.0.1:8080/health
# {"status":"ok"}

HTTP og realtime WebSocket test venter på /health at returnere HTTP 200 med {"status":"ok"}, med en 10- anden opstartsdeadline. Opstartsfejl mislykkes testopsætning, og toardown venter server nedlukning, før genbruge sin port.

WebSocket: /v1/realtime

Drop-in kompatibel med OpenAI Realtime API - det samme JSON event schema (session.update, input_audio_buffer.append, response.create, response.audio.delta,...) med base64-encoded PCM16 lyd på 24 kHz. Klienter skrevet imod OpenAI Realtime SDK arbejde mod speech-server uden kodeændringer (bare skifte WebSocket URL).

Automatiske drejninger med server VAD

Manual input_audio_buffer.commit forbliver standard. Sæt session.turn_detection til server_vad at køre Silero VAD på serveren og automatisk transskribere hver færdig taletur. Præfiks lyd er bevaret, tomgang buffering forbliver afgrænset, og en kontinuerlig aktiv drejning er kraft- lukket på det indstillede 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())

Deployeringsnoter

Kilde

Lokal indfødt inferens

For 12B, gentagne tilstødende værktøjs- call lucking markører umiddelbart efter et komplet, valideret opkald forbruges med dette opkald. De skaber ikke et andet opkald eller ændre sine argumenter. Standalone markører og misdannede argumenter forbliver fejl; E4B bevarer streng håndtering.

For at beholde fejlbehæftede native chat-forespørgsler, sæt failureCaptureDirectory i inferens manifest. Fanget er som standard slukket. Mappen skal nægte gruppe og anden adgang; nye mapper bruges 0700 og fejlfiler bruger 0600. Filer omfatter den nøjagtige anmodning organ, anmode om ID og fejl. Færdiggjort 12B generationer også beholde den afleverede prompt, token id 'er, rå output og stop grund før fortolkning. E4B fejl har ingen rå generation rekord. Disse lokale filer indeholder samtale og værktøj indhold; HTTP fejl og succesfulde anmodninger ikke omfatter dem.

Valgfri agentDirectory indlæser en iscenesat Gemma 4 12B Ensartet INT4 tekstmodel ved siden af E4B. Brug model: "gemma4-12b-it"for chat med indfødte værktøjer, resultat historie, og annullering. E4B forbliver til rådighed for andre anmodninger. Gemma4UnifiedChat bruger den fæstnede MLX tekst implementering og frigiver hver anmodning KV cache. Response parsing fjerner kanal afgrænsere fra returneret tekst. Orphanded tool- call terminatorer afvises som misdannede svar. Mislykkedes ikke-streaming anmodninger log deres anmodning ID, operation, og underliggende fejl i serveren proces. Gemma 4 12B, værktøjs- message indhold bevarer JSON som tekst, der matcher checkpoint chat skabelonen.

Kildeopbygninger accepterer --inference-manifest models.json at indlæse iscenesat Gemma 4 E4B INT4, VoxCPM2, fuld Whisper Large-v3, og Silero VADDenne tjeneste starter offline og afviser uforenelige model identiteter.

Den indfødte service serialiserer chat, syntese og transskription; letvægts VAD har separat stream tilstand. Gemma prefill evaluerer hver 256- token batch, før du starter den næste, anmodning KV tilstand er frigivet, og MLX cache er begrænset på 128 MiB med en 20 GiB tildelingsgrænse.

Tale med stream: true returnerer NDJSON audio events på 48 kHz, efterfulgt af gjort eller fejl. Annullér af request at /v1/ inferens / aflys. GET /v1/ inferens / kapaciteter og /v1/ inferens / herkomst rapport model identiteter, parameter dtypes, aktiv pins, og memory counters.

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"
}

API-oplysninger

Valgfri modelejerskab

SpeechRuntime giver delt indlæsning, annullerbar FIFO optagelse og serialiseret udførelse. Qwen3ASRRuntime vælger MLX eller fuld CoreML via eksplicitte deskriptorer; indfødte API 'er og CLI-flag forbliver tilgængelige.

Lydserveren har en udførelsestilladelse gennem hver komplet anmodning, herunder streamet output, med op til 32 anmodninger venter. ASR fejl producerer HTTP fejl eller WebSocket fejlbegivenheder; gyldige tomme udskrifter forbliver vellykket. Playback bevarer overløb prøver. Cached modeller og venter afspilning lyd stadig optager hukommelse.

Voxtral TTS

Voxtral 4B TTS 2603 kører lokalt Apple Silicon gennem Voxtral TTS-modulet: 20 forudindstillet stemmer, ni sprog, 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.wav

Foretag kun stemmer; reference- audio kloning er ikke tilgængelig. Lydoutput strømme gennem SDK, CLI, WebSocket og HTTP PCM. Levere den komplette input tekst op foran. Model vægte bruge CC BY-NC 4.0.

Læs vejledningen Voxtral TTS

Gemma 4 12B prompt prefill

Den indfødte inference service indlæser den iscenesatte Gemma 4 12B Unified INT4 model ved hjælp af agentDirectory. Vælg det til chat med modellen ID gemma4-12b-it.

Gemma 4 12B prefill fylder KV-tilstand i batcher på op til 256 tokens og beregner de første samplinglogin fra den endelige prompt token. Mellemliggende ordforrådsfremskrivninger sprunges. Forespørgslens KV cache frigives efter afslutning eller annullering.

Et uændret system / værktøj præfiks kan forblive cachet i komplette 256- token blokke. Hver anmodning udvider en separat arbejdskopi. Brugermeddelelser, samtale historie, og værktøj resultater aldrig indtaste den tilbageholdte snapshot. SPEECH_SWIFT_GEMMA4_PREFIX_CACHE_MB at begrænse tilbageholdte MiB, eller 0 at deaktivere genbrug. clearPrefixCache() frigiver snapshot. HTTP rapporter genbrugt tokens i cachedPrefixTokens; Originaloptegnelser gemma4_12b_prefix_cache_budget_bytesKolde anmodninger stadig behandle den fulde prompt.

Native Gemma toolhistorik holder værktøjets respons og en assisterende fortsættelse inde i samme model drejning. En følgende brugermeddelelse lukker denne model drejning, før du åbner den næste bruger tur. Send hvert resultat med sin oprindelige toolCallID.