{"openapi":"3.1.0","info":{"title":"voice-generator API","description":"Zero-shot text-to-speech (OmniVoice, Rust/candle): voice cloning, voice design and auto voice. A gRPC interface with the same operations is served separately; the proto file is available at /api/v1/proto.","contact":{"name":"kerk","email":"kerk@invako.kr"},"license":{"name":"Proprietary — internal use only"},"version":"0.1.0"},"servers":[{"url":"/","description":"this server"}],"paths":{"/api/v1/info":{"get":{"tags":["system"],"summary":"Information about the loaded model.","operationId":"engine_info","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EngineInfoDto"}}}}}}},"/api/v1/instructs":{"get":{"tags":["system"],"summary":"Valid voice-design instruct items.","operationId":"instruct_catalog","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstructCatalogDto"}}}}}}},"/api/v1/languages":{"get":{"tags":["system"],"summary":"Supported languages (600+), sorted by name.","operationId":"list_languages","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LanguageDto"}}}}}}}},"/api/v1/synthesize":{"post":{"tags":["synthesis"],"summary":"Synthesize speech and return a WAV file.","description":"Long texts are chunked automatically. Generation is CPU/GPU bound and can\ntake tens of seconds on CPU; requests are queued (see `--max-concurrency`).","operationId":"synthesize","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeDto"}}},"required":true},"responses":{"200":{"description":"WAV audio (mono, 16-bit PCM, 24 kHz). Headers: X-Audio-Duration-Seconds, X-Elapsed-Seconds","content":{"audio/wav":{}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/synthesize/base64":{"post":{"tags":["synthesis"],"summary":"Synthesize speech and return the WAV file as base64 inside JSON.","operationId":"synthesize_base64","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeDto"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeBase64Dto"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/synthesize/codes":{"post":{"tags":["synthesis"],"summary":"Streaming synthesis delivered as audio *codes* (NDJSON, ~2 kbps) for\nclient-side decoding with `omnivoice-decoder` (native, mobile or WASM).","description":"One JSON object per line: first `{\"type\":\"meta\",...}` (sample rate,\ncodebook layout, post-processing parameters), then `{\"type\":\"chunk\",\n\"index\",\"total\",\"text\",\"codes\":[[...8 rows...]],\"is_last\"}` per chunk;\n`{\"type\":\"error\",\"message\"}` if generation fails mid-stream. Decoding a\nchunk and applying the post-processing described by the metadata gives the\nsame waveform as `/api/v1/synthesize/stream`.","operationId":"synthesize_codes","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeDto"}}},"required":true},"responses":{"200":{"description":"NDJSON code stream (meta, then chunks)","content":{"application/x-ndjson":{}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/synthesize/stream":{"post":{"tags":["synthesis"],"summary":"Streaming synthesis: raw 16-bit little-endian mono PCM, sent chunk by\nchunk as soon as each text chunk is generated.","description":"The first chunk is kept short (`options.first_chunk_duration`, default 5 s)\nso playback can start early; concatenate the bytes to obtain the full\nutterance. Response headers: `X-Audio-Format: pcm_s16le`, `X-Sample-Rate`,\n`X-Channels`. Errors after the first chunk terminate the stream.","operationId":"synthesize_stream","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthesizeDto"}}},"required":true},"responses":{"200":{"description":"Chunked raw PCM (16-bit LE, mono). Headers: X-Audio-Format, X-Sample-Rate, X-Channels","content":{"application/octet-stream":{}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/voices":{"get":{"tags":["voices"],"summary":"List stored voices.","operationId":"list_voices","responses":{"200":{"description":"","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VoiceDto"}}}}}}},"post":{"tags":["voices"],"summary":"Register a reference recording as a reusable voice for cloning.","operationId":"create_voice","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CreateVoiceForm"}}},"required":true},"responses":{"201":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceDto"}}}},"400":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"415":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}},"500":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/api/v1/voices/{id}":{"get":{"tags":["voices"],"summary":"Get one stored voice.","operationId":"get_voice","parameters":[{"name":"id","in":"path","description":"voice id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceDto"}}}},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}},"delete":{"tags":["voices"],"summary":"Delete a stored voice.","operationId":"delete_voice","parameters":[{"name":"id","in":"path","description":"voice id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"deleted"},"404":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorDto"}}}}}}},"/healthz":{"get":{"tags":["system"],"summary":"Liveness probe.","operationId":"healthz","responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthDto"}}}}}}}},"components":{"schemas":{"CreateVoiceForm":{"type":"object","description":"Multipart form for `POST /api/v1/voices`.","required":["name","ref_text","file"],"properties":{"file":{"type":"string","format":"binary","description":"Reference recording as WAV (any sample rate, mono or stereo, at most 60 s; 3–10 s recommended)."},"name":{"type":"string","description":"Display name of the voice.","example":"alice"},"preprocess":{"type":["boolean","null"],"description":"Trim silences / add end punctuation (default `true`)."},"ref_text":{"type":"string","description":"Transcript of the reference recording (required).","example":"Hello, this is my reference recording."}}},"EngineInfoDto":{"type":"object","required":["model","device","dtype","sample_rate","frame_rate","num_codebooks","version"],"properties":{"device":{"type":"string","example":"Cpu"},"dtype":{"type":"string","example":"f32"},"frame_rate":{"type":"integer","format":"int32","example":25,"minimum":0},"model":{"type":"string","example":"k2-fsa/OmniVoice"},"num_codebooks":{"type":"integer","format":"int32","example":8,"minimum":0},"sample_rate":{"type":"integer","format":"int32","example":24000,"minimum":0},"version":{"type":"string","description":"Server version."}}},"ErrorDto":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Machine-readable error code.","example":"invalid_input"},"message":{"type":"string","description":"Human-readable message."}}},"HealthDto":{"type":"object","required":["status"],"properties":{"status":{"type":"string","description":"Always `\"ok\"` when the process is up.","example":"ok"}}},"InstructCatalogDto":{"type":"object","required":["english","chinese"],"properties":{"chinese":{"type":"array","items":{"type":"string"},"description":"Chinese items (full-width comma separated), e.g. `女`, `四川话`."},"english":{"type":"array","items":{"type":"string"},"description":"English items (comma + space separated when combined), e.g. `male`, `british accent`."}}},"LanguageDto":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","example":"ko"},"name":{"type":"string","example":"korean"}}},"SynthesisOptionsDto":{"type":"object","description":"Decoding knobs; omitted fields use the engine defaults.","properties":{"chunk_duration":{"type":["number","null"],"format":"float","description":"Target duration (s) of subsequent chunks (default 15)."},"class_temperature":{"type":["number","null"],"format":"float","description":"Gumbel temperature for token sampling (default 0 = greedy)."},"denoise":{"type":["boolean","null"],"description":"Prepend the denoise token when cloning (default true)."},"first_chunk_duration":{"type":["number","null"],"format":"float","description":"Streaming: target duration (s) of the first chunk (default 5).","example":5.0},"first_chunk_num_step":{"type":["integer","null"],"format":"int32","description":"Streaming: `num_step` override for the first chunk (e.g. 16 for faster first audio).","minimum":0},"guidance_scale":{"type":["number","null"],"format":"float","description":"Classifier-free guidance scale (default 2.0).","example":2.0},"layer_penalty_factor":{"type":["number","null"],"format":"float","description":"Codebook layer penalty (default 5.0)."},"num_step":{"type":["integer","null"],"format":"int32","description":"Iterative unmasking steps (default 32; 16 is ~2× faster).","example":32,"maximum":256,"minimum":1},"position_temperature":{"type":["number","null"],"format":"float","description":"Gumbel temperature for position selection (default 5.0, 0 = greedy)."},"postprocess_output":{"type":["boolean","null"],"description":"Remove long silences from the output (default true)."},"seed":{"type":["integer","null"],"format":"int64","description":"RNG seed for reproducible sampling.","minimum":0},"t_shift":{"type":["number","null"],"format":"float","description":"Time-step shift (default 0.1)."}}},"SynthesizeBase64Dto":{"type":"object","description":"Synthesis result with the WAV file inlined as base64.","required":["audio_base64","content_type","sample_rate","duration_secs","elapsed_secs"],"properties":{"audio_base64":{"type":"string","description":"Base64-encoded WAV file (mono, 16-bit PCM)."},"content_type":{"type":"string","example":"audio/wav"},"duration_secs":{"type":"number","format":"float","example":3.24},"elapsed_secs":{"type":"number","format":"float","example":41.2},"sample_rate":{"type":"integer","format":"int32","example":24000,"minimum":0},"voice_id":{"type":["string","null"]}}},"SynthesizeDto":{"type":"object","description":"Text-to-speech request. Provide `voice_id` for cloning, `instruct` for\nvoice design, or neither for an automatically chosen voice.","required":["text"],"properties":{"duration":{"type":["number","null"],"format":"float","description":"Fixed output duration in seconds (overrides `speed`)."},"instruct":{"type":["string","null"],"description":"Voice-design instruction, e.g. `\"female, young adult, british accent\"`.","example":"female, young adult"},"language":{"type":["string","null"],"description":"Language name (`\"English\"`) or id (`\"ko\"`); omit for language-agnostic mode.","example":"Korean"},"options":{"$ref":"#/components/schemas/SynthesisOptionsDto"},"speed":{"type":["number","null"],"format":"float","description":"Speaking speed factor (> 1 faster, default 1.0)."},"text":{"type":"string","description":"Text to synthesize (max 5000 characters).","example":"안녕하세요, 러스트로 만든 음성 합성기입니다."},"voice_id":{"type":["string","null"],"description":"Id of a stored voice (see `POST /api/v1/voices`)."}}},"VoiceDto":{"type":"object","required":["id","name","ref_text","num_frames","reference_secs","created_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"name":{"type":"string","example":"alice"},"num_frames":{"type":"integer","format":"int32","description":"Number of codec frames (25 per second).","minimum":0},"ref_text":{"type":"string"},"reference_secs":{"type":"number","format":"float"}}}}},"tags":[{"name":"system","description":"Health and engine information"},{"name":"synthesis","description":"Text-to-speech"},{"name":"voices","description":"Reusable reference voices for cloning"}]}