{"openapi":"3.1.0","info":{"title":"声选 Voice Casting API","version":"1.0.0","description":"1,248 条积木音色参考音频。无需密钥的公开只读检索、角色匹配与音频服务；不提供语音生成。"},"servers":[{"url":"https://voices.ebeb.fun"}],"paths":{"/api/health":{"get":{"operationId":"health","summary":"服务健康状态","responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/stats":{"get":{"operationId":"stats","summary":"音色总数、语言与分类字典","responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/voices":{"get":{"operationId":"searchVoices","summary":"检索、筛选与分页","parameters":[{"name":"q","in":"query","schema":{"type":"string"},"description":"名称、编号、风格词；语义近义词可检索"},{"name":"category","in":"query","schema":{"type":"string"},"description":""},{"name":"gender","in":"query","schema":{"type":"string"},"description":""},{"name":"language","in":"query","schema":{"type":"string"},"description":"ISO 639-1，如 zh/en/ja，或中文语言名"},{"name":"country","in":"query","schema":{"type":"string"},"description":""},{"name":"ageGroup","in":"query","schema":{"type":"string"},"description":"child/young/adult/senior，标签推断"},{"name":"tags","in":"query","schema":{"type":"string"},"description":"逗号分隔，全部标签均需命中"},{"name":"sort","in":"query","schema":{"type":"string"},"description":"相关性默认；name/duration_asc/duration_desc"},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":24}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"default":0}}],"responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"offset":{"type":"integer"},"limit":{"type":"integer"},"hasMore":{"type":"boolean"},"items":{"type":"array","items":{"$ref":"#/components/schemas/Voice"}}}}}}}}}},"/api/voices/{id}":{"get":{"operationId":"getVoice","summary":"音色详情与稳定音频地址","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"example":"voice-001"}],"responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Voice"}}}},"404":{"description":"音色不存在"}}}},"/api/match":{"post":{"operationId":"matchCharacters","summary":"单角色或多角色匹配，按录音哈希去重","description":"按原站名称、标签、语言与年龄感线索评分。分数不是声学相似度、生成效果保证或客观音质分。明确的性别、语言、ageGroup、tags 与排除条件是硬筛选；description 中年龄感为排序偏好。默认语言为中文，默认多角色主选不共享同一录音。","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Role"},{"type":"object","required":["roles"],"properties":{"roles":{"type":"array","minItems":1,"maxItems":20,"items":{"$ref":"#/components/schemas/Role"}},"uniqueAudio":{"type":"boolean","default":true},"limit":{"type":"integer","minimum":1,"maximum":10,"default":3}}}]},"example":{"roles":[{"id":"lead","name":"林舟","gender":"male","language":"zh","description":"32岁，沉稳克制、低沉磁性的男主"}],"uniqueAudio":true,"limit":3}}}},"responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object","properties":{"method":{"type":"string"},"scoreMeaning":{"type":"string"},"uniqueAudio":{"type":"boolean"},"roles":{"type":"array","items":{"type":"object","properties":{"roleId":{"type":"string"},"roleName":{"type":"string"},"primary":{"anyOf":[{"$ref":"#/components/schemas/Candidate"},{"type":"null"}]},"alternatives":{"type":"array","items":{"$ref":"#/components/schemas/Candidate"}},"candidateCount":{"type":"integer"},"warnings":{"type":"array","items":{"type":"string"}}}}}}}}}},"400":{"description":"无效输入"},"413":{"description":"超过 64 KB"}}}},"/api/catalog":{"get":{"operationId":"fullCatalog","summary":"完整目录（约 1.2 MB，通常优先使用分页检索）","responses":{"200":{"description":"成功","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/audio/{filename}":{"get":{"operationId":"getReferenceAudio","summary":"原始音频；支持 Range、CORS 与下载","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string"},"example":"voice-001.wav"},{"name":"Range","in":"header","schema":{"type":"string"},"example":"bytes=0-1023"}],"responses":{"200":{"description":"完整 WAV/MP3","content":{"audio/wav":{"schema":{"type":"string","format":"binary"}},"audio/mpeg":{"schema":{"type":"string","format":"binary"}}}},"206":{"description":"音频字节片段"},"416":{"description":"无效字节范围"}}},"head":{"operationId":"headReferenceAudio","summary":"音频大小与 MIME 类型","parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"音频元数据"}}}}},"components":{"schemas":{"Voice":{"type":"object","required":["id","name","audioUrl","sha256"],"properties":{"id":{"type":"string"},"code":{"type":"string"},"name":{"type":"string"},"category":{"type":"string"},"categoryName":{"type":"string"},"gender":{"type":"string"},"genderLabel":{"type":"string"},"ageGroup":{"type":"string"},"language":{"type":"string"},"languageCode":{"type":"string"},"country":{"type":"string"},"countryCode":{"type":"string"},"emotion":{"type":"string"},"description":{"type":"string"},"durationMs":{"type":"integer"},"bytes":{"type":"integer"},"mimeType":{"type":"string"},"sampleRate":{"type":"integer"},"channels":{"type":"integer"},"sha256":{"type":"string"},"audioUrl":{"type":"string"},"downloadUrl":{"type":"string"},"pageUrl":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}}}},"Role":{"type":"object","anyOf":[{"required":["description"]},{"required":["name"]},{"required":["q"]}],"description":"声音需求应放在 description，性别与语言等明确要求可用结构化字段；年龄感来自标签推断。","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"q":{"type":"string"},"language":{"type":"string"},"country":{"type":"string"},"accent":{"type":"string"},"tone":{"type":"string"},"pitch":{"type":"string"},"texture":{"type":"string"},"pace":{"type":"string"},"style":{"type":"string"},"emotion":{"type":"string"},"personality":{"type":"string"},"gender":{"type":"string","enum":["male","female","unspecified"]},"age":{"type":"integer","minimum":0,"maximum":120},"ageGroup":{"type":"string","enum":["child","young","adult","senior"]},"category":{"type":"string","enum":["male","female","senior","child","dialect","international"]},"avoid":{"type":"array","items":{"type":"string"}},"excludeTags":{"type":"array","items":{"type":"string"}},"excludeVoiceIds":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"string"}}}},"Candidate":{"type":"object","properties":{"voice":{"$ref":"#/components/schemas/Voice"},"score":{"type":"integer","minimum":0,"maximum":100},"scoreType":{"const":"metadata-fit"},"reasons":{"type":"array","items":{"type":"string"}},"evidence":{"type":"array","items":{"type":"string"}},"warnings":{"type":"array","items":{"type":"string"}}}}}},"security":[]}