Maskinoversættelse · Engelsk original
API og protokoller
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).
import PocketTTS
let model = try PocketTTSModel.fromBundle(URL(fileURLWithPath: "/path/to/bundle"))
try await model.generateStreaming(text: "Hello world.") { chunk in
await consume(chunk.samples)
}Den AudioCommon modul definerer model- agnostic protokoller og delte typer. Enhver ensrettet model kan bruges skiftevis gennem disse grænseflader.
Protokoloversigt
┌─────────────────────────────────────────────────────────┐
│ AudioCommon │
│ │
│ AudioChunk SpeechGenerationModel (TTS) │
│ AlignedWord SpeechRecognitionModel (STT) │
│ SpeechSegment ForcedAlignmentModel │
│ SpeechToSpeechModel │
│ VoiceActivityDetectionModel (VAD) │
│ TurnCompletionProvider (EOT) │
│ SpeakerEmbeddingModel │
│ SpeakerDiarizationModel │
│ SpeakerExtractionCapable │
└─────────────────────────────────────────────────────────┘SpeechAnerkendelse Model
Protokol for speech-to- tekst modeller.
public protocol SpeechRecognitionModel: AnyObject {
var inputSampleRate: Int { get }
func transcribe(audio: [Float], sampleRate: Int, language: String?) -> String
func transcribeWithLanguage(audio: [Float], sampleRate: Int, language: String?) -> TranscriptionResult
}
Konformeringstyper: Qwen3ASRModel, WhisperASRModel, ParakeetASRModel, ParakeetStreamingASRModel, OmnilingualASRModel (CoreML), OmnilingualASRMLXModel (MLX)
SpeechGenerationModel
Protokol for lære- to- tale modeller.
public protocol SpeechGenerationModel: AnyObject {
var sampleRate: Int { get }
func generate(text: String, language: String?) async throws -> [Float]
func generateStream(text: String, language: String?) -> AsyncThrowingStream<AudioChunk, Error> // has default impl
}
generateStream() har en standard implementering, der wraps generate() som et enkelt stykke. Modeller med sand streaming (fx Qwen3-TTS) tilsidesætte det.
Konformeringstyper: Qwen3TTSModel, CosyVoiceTTSModel, VoxCPM2TTSModel, KokoroTTSModel, IndexTTS2TTSModel
IndexTTS2TTSModel tilføjer en reference- audio generate overbelastning for zero-shot voice kloning og anvendelser IndexTTS2SynthesisOptions for tale- rate og pause kontrol.
Qwen3-TTS lokal indlæsning
fromLocal validerer nødvendige filer og checkpoint shard fuldstændighed, så stammer modelstørrelse, kvantisering og arkitektur fra config.jsonDen valgfrie configuration værdi er kun en fallback for udeladte metadata; misdannede eller modstridende metadata kaster Qwen3TTSLoadingError.invalidConfiguration før modeltildelingen.
public static func fromLocal(
modelDirectory: URL,
tokenizerDirectory: URL,
configuration: Qwen3TTSConfig? = nil,
wiredMemoryPolicy: Qwen3TTSWiredMemoryPolicy = .none,
progressHandler: ((Double, String) -> Void)? = nil
) throws -> Qwen3TTSModel
public static func fromPretrained(
modelId: String = Qwen3TTSModel.defaultModelId,
tokenizerModelId: String = "Qwen/Qwen3-TTS-Tokenizer-12Hz",
cacheDir: URL? = nil,
tokenizerCacheDir: URL? = nil,
offlineMode: Bool = false,
wiredMemoryPolicy: Qwen3TTSWiredMemoryPolicy = .pin(fraction: 0.9),
progressHandler: ((Double, String) -> Void)? = nil
) async throws -> Qwen3TTSModel
fromLocal standard til .none, så det ændrer ikke proces- wired Metal wired- memory limit. fromPretrained holder sin .pin(fraction: 0.9) standard. Begge forudtrænede læssere accepterer en separat tokenizerCacheDir.
ForceAlignmentModel
Protokol for tilpasning af tidsstempler på ord- niveau.
public protocol ForcedAlignmentModel: AnyObject {
func align(audio: [Float], text: String, sampleRate: Int, language: String?) -> [AlignedWord]
}
SpeechToSpeechModel
Protokol for talemålemodeller.
public protocol SpeechToSpeechModel: AnyObject {
var sampleRate: Int { get }
func respond(userAudio: [Float]) -> [Float]
func respondStream(userAudio: [Float]) -> AsyncThrowingStream<AudioChunk, Error>
}
Konformeringstyper: PersonaPlexModel
HibikiTranslateModel
Speech- to- tale oversættelse driver. Er ikke i overensstemmelse med SpeechToSpeechModel Da kontrakten er forskellig: input og output er forskellige sprog, output længde er variabel (EOS-drevet, begrænset på max(tSrc * 5/2, tSrc + 20) trin - omtrent 1.0- 1.6 × kildevarighed på FLEURS- stil klip), og der er en parallel tekst- token stream ved siden af lyden. Fuld guide →
public final class HibikiTranslateModel {
public let cfg: HibikiConfig
public static var defaultModelId: String { "aufklarer/Hibiki-Zero-3B-MLX-4bit" }
public static var modelId8bit: String { "aufklarer/Hibiki-Zero-3B-MLX-8bit" }
public static func fromPretrained(
modelId: String = defaultModelId,
cacheDir: URL? = nil,
offlineMode: Bool = false,
progressHandler: ((Double, String) -> Void)? = nil
) async throws -> HibikiTranslateModel
public func warmUp()
public func translate(
sourceAudio: [Float],
sourceLanguage: HibikiSourceLanguage = .fr,
verbose: Bool = false
) -> (audio: [Float], textTokens: [Int32])
public func translateStream(
sourceAudio: [Float],
sourceLanguage: HibikiSourceLanguage = .fr,
streaming: HibikiStreamingConfig = .default,
verbose: Bool = false
) -> AsyncThrowingStream<AudioChunk, Error>
}
public enum HibikiSourceLanguage: String, CaseIterable, Sendable, Codable {
case fr, es, pt, de
}
Prøvesats: 24 kHz mono, både input og output. Rammefrekvens: 12.5 Hz (Mimi codec). Kildesprog: FR / ES / PT / DE. Målsprog: EN. Set HIBIKI_GREEDY=1 ved proceslancering for deterministisk argmax-afkodning (matcher CI-kanarierne).
VoiceActivityDetectionModel
Protokol til afsløring af stemmeaktivitet.
public protocol VoiceActivityDetectionModel: AnyObject {
var inputSampleRate: Int { get }
func detectSpeech(audio: [Float], sampleRate: Int) -> [SpeechSegment]
}
TurnComptionProvider
Protokol for slutteklassifikatorer, der høres af StreamingVADProcessor på hver bekræftet VAD pause. En VAD kun hører stilhed; en turn- completing model lytter til prosody af hele ytterance, så en midtpunkts pause holder agenten venter mens en færdig sætning får et øjeblikkeligt svar. Kort til speech-core 's sc_turn_completion_vtable_t. Se Smart Turn guide.
public protocol TurnCompletionProvider: AnyObject {
/// Probability in [0, 1] that the turn is complete, given the audio of the
/// turn so far (Smart Turn looks at the last 8 s).
func turnCompleteProbability(audio: [Float], sampleRate: Int) throws -> Float
}
Konformeringstyper: SmartTurnModel (Smart Turn v3.2)
SpeakerEmbeddingModel
Protocol for speaker indlejring ekstraktion.
public protocol SpeakerEmbeddingModel: AnyObject {
var inputSampleRate: Int { get }
var embeddingDimension: Int { get }
func embed(audio: [Float], sampleRate: Int) -> [Float]
}
Konformeringstyper: WeSpeakerModel
SpeakerDiarizationModel
Protokol for højttaler diarization modeller, der tildeler højttaler etiketter til lydsegmenter.
public protocol SpeakerDiarizationModel: AnyObject {
var inputSampleRate: Int { get }
func diarize(audio: [Float], sampleRate: Int) -> [DiarizedSegment]
}
Konformeringstyper: DiarizationPipeline (Pyannote), SortformerDiarizer
SpeakerExtractionCapable
Udvidet diariseringsprotokol for motorer, der understøtter udtrækning af en målhøjttalers segmenter ved hjælp af en reference indlejring. Ikke alle motorer understøtter dette (Sortformer er ende- to- end og producerer ikke højttalerindlejringer).
public protocol SpeakerExtractionCapable: SpeakerDiarizationModel {
func extractSpeaker(audio: [Float], sampleRate: Int, targetEmbedding: [Float]) -> [SpeechSegment]
}
Konformeringstyper: DiarizationPipeline (kun Pyannote)
Fælles typer
AudioChunk
public struct AudioChunk {
public let samples: [Float] // PCM samples
public let sampleRate: Int // Sample rate (e.g. 24000)
}
SpeechSegment
public struct SpeechSegment {
public let startTime: Float // Start time in seconds
public let endTime: Float // End time in seconds
}
AlidredWord
public struct AlignedWord {
public let text: String // The word
public let startTime: Float // Start time in seconds
public let endTime: Float // End time in seconds
}
DiarizedSegment
public struct DiarizedSegment {
public let startTime: Float // Start time in seconds
public let endTime: Float // End time in seconds
public let speakerId: Int // Speaker identifier (0-based)
}
DialogueSegment
Et fortolket segment af multi-højtaler dialog tekst med valgfri højttaler og følelser tags. Bruges med DialogueParser og DialogueSynthesizer for CosyVoice3 dialogsyntese.
public struct DialogueSegment: Sendable, Equatable {
public let speaker: String? // Speaker identifier ("S1", "S2"), nil for untagged
public let emotion: String? // Emotion tag ("happy", "whispers"), nil if none
public let text: String // Cleaned text to synthesize
}
DialogueParser
Parses multihøjttalerdialogtekst med inline højttalertags ([S1]) og følelser tags ((happy)).
public enum DialogueParser {
static func parse(_ text: String) -> [DialogueSegment]
static func emotionToInstruction(_ emotion: String) -> String
}
Bygge- i følelser: happy/excited, sad, angry, whispers/whispering, laughs/laughing, calm, surprised, serious. Ukendt mærker passerer igennem som freeform instruktioner.
DialogueSynthesizer
Orkestrerer multisegmentdialog syntese med per- højtaler stemme kloning, stilhed huller, og crossfade.
public enum DialogueSynthesizer {
static func synthesize(
segments: [DialogueSegment],
speakerEmbeddings: [String: [Float]],
model: CosyVoiceTTSModel,
language: String,
config: DialogueSynthesisConfig,
verbose: Bool
) -> [Float]
}
DialogueSynthesiConfig
public struct DialogueSynthesisConfig: Sendable {
public var turnGapSeconds: Float // Default: 0.2
public var crossfadeSeconds: Float // Default: 0.0
public var defaultInstruction: String // Default: "You are a helpful assistant."
public var maxTokensPerSegment: Int // Default: 500
}
PipelineLLM
Protokol for sprogmodel integration med voice pipelines. Broer en LLM til VoicePipeline ASR → LLM R. TTS flow.
public protocol PipelineLLM: AnyObject {
func chat(messages: [(role: MessageRole, content: String)],
onToken: @escaping (String, Bool) -> Void)
func cancel()
}
Byg - i adapter: Qwen3PipelineLLM broer Qwen35MLXChat til denne protokol med token oprydning, annullering, og afventende sætning ophobning.
AudioIO
Genanvendelig lyd I / O manager, der eliminerer AVAudioEngine Mesterplate. Håndterer mic capture, resampling, afspilning, og audio niveau måling.
let audio = AudioIO()
try audio.startMicrophone(targetSampleRate: 16000) { samples in
pipeline.pushAudio(samples)
}
audio.player.scheduleChunk(ttsOutput)
audio.stopMicrophone()
AudioIO omfatter en StreamingAudioPlayer for TTS output og en AudioRingBuffer til trådsikker overførsel af lyd mellem indfangnings- og indkøringstråde.
SystemAudioTap
Opfanger systemets output mix - hvad Mac er i øjeblikket spiller - som mono Float32 på en caller- valgt prøve rate (Core Audio process haner, macOS 14.4+). Mono global tap udelukker den aktuelle proces som standard, så en app 's egen afspilning er aldrig genfanget, og det er pakket i en privat aggregat enhed, der kun indeholder hanen.
let tap = SystemAudioTap()
try tap.start(targetSampleRate: 16000) { samples in
pipeline.pushAudio(samples)
}
tap.stop()
Capture overlever default- output- enhedskontakter - den interne resampler genopbygges, når mixhastigheden ændres. Værtsappen skal erklære NSAudioCaptureUsageDescription. Hvis optagelse tilladelse nægtes, kan et hank stadig oprettes endnu levere kun stilhed: se framesCaptured vokse, mens nonSilentFrames forbliver 0 og mislykkes lukket.
Tidsbegrænsede uafhængige kilder
Begge indfanger klasser afslører tidsstemplede overbelastninger. CapturedAudioChunk bærer mono samples på sampleRate plus en valgfri Mach hostTime for den første inddata ramme. Fordi begge kilder bruger samme vært ur, kan en app holde deres PCM separate og orden afledt udskrift begivenheder uden at blande lyd.
try tap.startTimestamped(targetSampleRate: 16000) { systemChunk in
systemPipeline.pushAudio(systemChunk.samples)
recordSystemTime(systemChunk.hostTime)
}
let microphone = AudioIO(enableAEC: true, enablePlayback: false)
try microphone.startMicrophoneTimestamped(targetSampleRate: 16000) { micChunk in
microphonePipeline.pushAudio(micChunk.samples)
recordMicrophoneTime(micChunk.hostTime)
}
For at lytte, kun fange, enableAEC: true aktiverer Apple Voice Processing, før mikrofonen format læses, og enablePlayback: false udelader den ubrugte spiller. På macOS fjernes afspilningen af enheden fra mikrofonens prøver, og der rapporteres om manglende start af AEC i stedet for at falde tilbage til råinput.
Input og genkendelse af flere filer
CapturedAudioChunk også bærer en monotonisk frameIndex og en isFinal markør. AudioFileLoader.stream producerer disse stykker på efterspørgsel med afgrænset hukommelse, resamples én gang med vedvarende konverter tilstand, og gennemsnit alle input kanaler som standard. .first eller .select([indices]) når kanal routing er kendt.
StreamingRecognitionModel og StreamingRecognitionSession give en cache-conservation incremental API på tværs af Parakeet Streaming og Nemotron Core ML / MLX:
let source = AudioFileLoader.stream(
url: inputURL,
options: AudioFileStreamOptions(targetSampleRate: 16_000,
chunkDuration: 0.32,
channelSelection: .mixAll))
let session = try model.makeStreamingSession(language: "en-US")
for try await chunk in source {
for update in try session.push(chunk) {
render(update.text, final: update.isFinal)
}
}
for update in try session.finish() {
render(update.text, final: true)
}
SentencePieceModel
Fælles protobuflæser til SentencePiece .model filer, bor i AudioCommon. Hvert modul, der har brug for at afkode SentenePiece stykker (PersonaPlex, OmnilingualASR, fremtidige ASR / TTS porte) bygger sin egen dekoder på toppen af denne enkelt læser i stedet for at gen- gennemføre protobuf wire format.
public struct SentencePieceModel: Sendable {
public struct Piece: Sendable, Equatable {
public let text: String
public let score: Float
public let type: Int32
public var pieceType: PieceType? { get }
public var isControlOrUnknown: Bool { get }
}
public enum PieceType: Int32 {
case normal = 1, unknown = 2, control = 3,
userDefined = 4, unused = 5, byte = 6
}
public let pieces: [Piece]
public var count: Int { get }
public subscript(_ id: Int) -> Piece? { get }
public init(contentsOf url: URL) throws
public init(modelPath: String) throws
public init(data: Data) throws
}
Anvendt af: OmnilingualASR.OmnilingualVocabulary, PersonaPlex.SentencePieceDecoder. Dækket af 7 enhedstests i Tests/AudioCommonTests/SentencePieceModelTests.
MLXAPP.SDPA
Skalerede dot- produkt opmærksomhed hjælpere delt på tværs af hver MLX opmærksomhed modul (Qwen3-ASR / Qwen3-TTS-Qwen3-Chat, CosyVoice eller PersonaPlex og OmnilingualASR). Hvert modul holder sine egne fremskrivninger - SDPA kun håndterer omformningen → opmærksomhed → fletning Medicerplate.
public enum SDPA {
// Flat [B, T, H*D] input: project/reshape happens inside
public static func multiHead(
q: MLXArray, k: MLXArray, v: MLXArray,
numHeads: Int, headDim: Int, scale: Float,
mask: MLXArray? = nil
) -> MLXArray
// GQA / MQA variant with separate query and KV head counts
public static func multiHead(
q: MLXArray, k: MLXArray, v: MLXArray,
numQueryHeads: Int, numKVHeads: Int, headDim: Int, scale: Float,
mask: MLXArray? = nil
) -> MLXArray
// Already-shaped [B, H, T, D] (RoPE / KV cache paths)
public static func attendAndMerge(
qHeads: MLXArray, kHeads: MLXArray, vHeads: MLXArray,
scale: Float,
mask: MLXArray? = nil
) -> MLXArray
// Same, with ScaledDotProductAttentionMaskMode enum (newer API)
public static func attendAndMerge(
qHeads: MLXArray, kHeads: MLXArray, vHeads: MLXArray,
scale: Float,
mask: MLXFast.ScaledDotProductAttentionMaskMode
) -> MLXArray
// Low-level head merge: [B, H, T, D] → [B, T, H*D]
public static func mergeHeads(_ attn: MLXArray) -> MLXArray
}
Alle omformer kald brug -1 for batch dimension, så hjælpere komponere med MLX.compile(shapeless:) Grafer, der varierer batch ved runtime (f.eks. Qwen3-TTS Talker auto regressive dekode).
HTTP API Server
Den speech-server binær udsætter hver model i speech-swift som HTTP REST endepunkter plus et WebSocket endpoint, der gennemfører OpenAI Realtime API. Modeller er indlæst dovenskab på første anmodning; pass --preload at varme dem alle ved opstart.
swift build -c release
.build/release/speech-server --port 8080
# Preload every model at startup
.build/release/speech-server --port 8080 --preload
REST Endpoints
| Slutpunkt | Metode | Anmodning | Respons |
|---|---|---|---|
/transcribe | POST | audio/wav organ | JSON { text } (Qwen3-ASR) |
/v1/audio/transcriptions | POST | Multipart { file, model, response_format?, language?, prompt?, temperature? } | JSON, tekst, verbose JSON eller SRT eller VTT |
/v1/audio/speech | POST | JSON { model, input, voice, response_format?, speed? } | audio/wav eller audio/pcm organ |
/speak | POST | JSON { text, engine?, language?, voice? } | audio/wav organ (Qwen3-TTS, CosyVoice og Kokoro) |
/respond | POST | audio/wav organ | audio/wav organ (PersonaPlex) |
/enhance | POST | audio/wav organ | audio/wav organ (DeepFilterNet3) |
/vad | POST | audio/wav organ | JSON-segmentliste |
/diarize | POST | audio/wav organ | JSON DiarizedSegment liste |
/embed-speaker | POST | audio/wav organ | JSON [Float] (256- dim) |
/v1/audio/speech kortlægger standard TTS model og talenavne til lokale motorer. Det er standard for WAV; response_format: "pcm" returnerer hovedløs 24 kHz mono PCM16 little- endian audio. Ikke-understøttede komprimerede formater afvises eksplicit.
/v1/audio/transcriptions accepterer en WAV fil som multipart form data og standard til {"text":"..."}; response_format kan også anmode om tekst, verbose JSON, SRT eller VTT. På Apple, model aliaser vælge en lokal ASR motor. Den emballerede speech-core server tændt Linux og Windows bruger lasagtigt indlæst Parakeet, accepterer PCM16/24/32 eller Float32 WAV, og hætter uploads på 25 MiB og 10 minutter.
# Transcribe a file
curl -X POST http://localhost:8080/transcribe \
--data-binary @recording.wav \
-H "Content-Type: audio/wav"
# Synthesize speech
curl -X POST http://localhost:8080/speak \
-H "Content-Type: application/json" \
-d '{"text": "Hello world", "engine": "cosyvoice"}' \
-o output.wav
# OpenAI-compatible transcription
curl http://localhost:8080/v1/audio/transcriptions \
-F "[email protected];type=audio/wav" \
-F "model=whisper-1"
# OpenAI-compatible speech synthesis
curl http://localhost:8080/v1/audio/speech \
-H "Content-Type: application/json" \
-d '{"model":"tts-1","voice":"alloy","input":"Hello world","response_format":"wav"}' \
-o openai-output.wav
# Full speech-to-speech round trip
curl -X POST http://localhost:8080/respond \
--data-binary @question.wav \
-o response.wav
OpenAI Realtime API (/v1/realtime)
WebSocket endpoint ved ws://host:port/v1/realtime implementerer OpenAI Realtime protokollen. Alle meddelelser er JSON med en type Diskriminator; lyd nyttelast er base64-encoded PCM16 på 24 kHz mono.
Under kolde modelbelastninger eller lange generationer udsender serveren letvægts realtime.keepalive JSON begivenheder og websocket pong kontrol rammer omtrent hver 15 sekunder indtil model output er klar. Klienter kan ignorere disse begivenheder eller behandle dem som aktivitetsindikatorer.
Klient → Serverbegivenheder
| Begivenhed | Formål |
|---|---|
session.update | Indstil motor, sprog, stemme, lydformat og valgfri server VAD |
input_audio_buffer.append | Tilsæt en base64 PCM16-del til inputbufferen |
input_audio_buffer.commit | Indsend den buffered lyd til transskription |
input_audio_buffer.clear | Kassér den aktuelle inputbuffer |
response.create | Anmodning om TTS syntese for den leverede tekst / instruktioner |
Server → Klientbegivenheder
| Begivenhed | Betydning |
|---|---|
session.created | Håndtryk komplet, standardkonfiguration udsendt |
session.updated | Senest session.update anerkendt |
input_audio_buffer.speech_started | Server VAD detekterede begyndelsen af en tale drejning |
input_audio_buffer.speech_stopped | Server VAD sluttede drejning efter stilhed eller varighed grænse |
input_audio_buffer.committed | Lyd accepteret og i kø til transskription |
conversation.item.input_audio_transcription.completed | ASR resultat med endelig udskrift tekst |
response.audio.delta | Base64 PCM16 stykke af syntetiseret lyd |
response.audio.done | Ikke flere lydstykker til dette svar |
response.done | Response finalized (metadata + latency statistik) |
error | Fejlkonvolut med type og message |
Automatiske drejninger med server VAD
Ekplicit input_audio_buffer.commit forbliver standard. For at lade serveren lukke og transskribere drejes automatisk med Silero VAD, konfigurere turn_detection. Serveren holder kun den ønskede pre-roll mens tomgang, udsender tale start / stop og begå begivenheder i rækkefølge, og kraft- lukker en kontinuerlig aktiv drejning på max_turn_duration_ms.
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
}
}
}));
// Disable automatic turns and return to explicit commits:
// { type: 'session.update', session: { turn_detection: null } }
const ws = new WebSocket('ws://localhost:8080/v1/realtime');
// ASR: push audio, request transcription
ws.send(JSON.stringify({ type: 'input_audio_buffer.append', audio: base64PCM16 }));
ws.send(JSON.stringify({ type: 'input_audio_buffer.commit' }));
// → conversation.item.input_audio_transcription.completed
// TTS: request synthesis and stream audio deltas
ws.send(JSON.stringify({
type: 'response.create',
response: { modalities: ['audio', 'text'], instructions: 'Hello world' }
}));
// → response.audio.delta (repeated), response.audio.done, response.done
Serveren bor i AudioServer SPM produkt. Et eksempel browser klient sendes på Examples/websocket-client.html - åbne den sammen med en kørende server for at køre hele ASR + TTS rundturen.
Model Downloads
Alle modeller downloades fra HuggingFace ved første brug og cache i ~/Library/Caches/qwen3-speech/. AudioCommon modul giver en delt HuggingFaceDownloader der håndterer download, caching og integritetskontrol.
Download forsøg igen
Model læssere og download API 'er acceptere downloadOptions: DownloadOptions. onRetry modtager en DownloadRetryEvent før hver backoff, med modelId, attempt, maxAttempts, originalen error, og retryInSeconds. nil betyder, at der ikke er nogen tilbageværende; komplet-cache fallback kan stadig lykkes.
Callbacks er synkrone og @Sendable, uden main- actor garanti. Annullering producerer ingen prøve begivenhed. Sæt retryDelaysSeconds at tilpasse politikken ([] betyder et forsøg); det eksplicitte download API argument har forrang. Standardforsøg tæller og byte fremskridt er bevaret. Fejlslagne forsøg er også logget på opslagsniveau gennem AudioLog.download.
Annullering af samarbejde
For MLX transskription, Qwen3ASRModel.transcribeCheckingCancellation(audio:sampleRate:options:) kaster CancellationError når opgaveaflysning observeres før feature extraction, kodning, dekoderpræfill eller et dekodertrin. GPU arbejde, der allerede er indsendt, kan afslutte. Synkron transcribe og transcribeBatch Api 'er bevarer deres ikke-kaste adfærd og ignorere opgave annullering. speech-server bruger annullerings-aware indgang for Qwen3-ASR.
MOSS- TTS- Nano
MossTTSNanoModel serialiserer anmodninger og skaber frisk CoreML tilstand for hver ytter. syntetisering og synthesize Stream bevare stereo; SpeechGenerationModel returnerer en mono downmix. Pass sprog: nul. Streams slutter med en tom sidste markør.
import AudioCommon
import MossTTSNano
let model = try await MossTTSNanoModel.fromPretrained()
let reference = try await model.encodeReference(url: referenceURL)
let result = try await model.synthesize(
text: "The weather is nice today.", reference: reference,
options: MossTTSNanoOptions(maxFrames: 300, seed: 1))
try WAVWriter.writeStereo(left: result.left, right: result.right,
sampleRate: 48000, to: outputURL)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.
Gemma4UnifiedChat.generateResponse accepterer en valgfri onGeneration callback med en Gemma4GenerationTrace. Callback kører før værktøj fortolkning, herunder når denne afslutning er afvist. Registrering ændrer ikke prøveudtagning eller accepteret værktøj syntaks.
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 returnerede tekst. Orphoned tool- call terminatorer afvises som misdannede svar. 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.
VoxCPM2 understøtter vægtPræcision: .float16 for et ukvantiseret checkpoint. Dens vigtigste parametre bruger FP16; AudioVAE og nogle beregninger forbliver FP32. INT8 checkpoints afvises for denne tilstand.
Gemma4ConversationMessage, Gemma4Tool og generateResponse bevare indfødte værktøjer erklæringer, argumenter og resultathistorie.InferenceCancellationToken annullerer generationen samarbejde. Silero makeIndependenStream isolater stat, og procesChunkThroing udbreder inferensfejl.
Whisper ASRModel.fromDirectory ladninger iscenesat fuld Large-v3 CoreML bundter. 32- layer dekoder kan bygge sin præfiks uden TextDecoderContextPrepill.mlmodelc og frigiver per- step temporaries. Standard Whisper CLI model forbliver Turbo.
Den indfødte service serialiserer chat, syntese og transskription; letvægts VAD har separat stream tilstand. Gemma prefill bruger 256- token batcher, anmodning KV tilstand er frigivet, og MLX cache er begrænset til 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 8080POST /v1/inference
{"operation":"chat","model":"gemma4-e4b-it","requestID":"chat-1","messages":[{"role":"user","content":"Hello"}],"maxTokens":128,"temperature":0}
chat: gemma4-e4b-it
speech: voxcpm2
transcribe: whisper-large-v3
vad: silero-vad
Audio: audioBase64 (mono PCM16), sampleRate
VAD: streamID, reset, endStream; 512 samples/frame at 16000 Hz
Tools: name, description, parameters
Tool call: id, name, arguments
Tool result: role="tool", toolCallID, contentValgfri 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.
import Qwen3ASRRuntime
let runtime = Qwen3ASRRuntime(descriptor: Qwen3ASRDescriptors.small)
let text = try await runtime.transcribe(audio: samples, sampleRate: 16000)
try await runtime.unload()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.
import VoxtralTTS
let model = try await VoxtralTTSModel.fromPretrained()
for try await chunk in model.generateStream(text: "Hello, welcome to Voxtral.", voice: "casual_male") {
print(chunk.frameIndex, chunk.samples.count, chunk.isFinal)
}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.
import AudioCommon
let player = StreamingAudioPlayer()
player.skipInitialSilence = false