[{"data":1,"prerenderedAt":132},["ShallowReactive",2],{"reference-detail-zh-create_speech_api_v1_tts_post":3,"developer-code-tpufuf":130,"developer-code-2ucgch":131},{"tag":4,"sourceTag":5,"tagSlug":6,"method":7,"path":8,"slug":9,"summary":10,"description":11,"operationId":12,"groupOrder":13,"descriptionHtml":14,"parameters":15,"requestBody":23,"responses":55,"security":117,"codeSamples":120},"Text to Speech","Speech","speech","POST","\u002Fapi\u002Fv1\u002Ftts","create-speech","生成语音","使用 VisionStory 智能 TTS 将文本转换为语音。从 GET \u002Fapi\u002Fv1\u002Fvoices 选择公共声音或自己的克隆声音。服务会根据声音和文本语言自动选择合适的合成策略。按每 1000 字符 2 点计费，向上取整，仅成功时扣费。\n\n此接口同步执行，响应体直接返回 MP3 音频（`audio\u002Fmpeg`）。时长与计费信息通过 `X-Audio-Duration-Sec`、`X-Usage-Characters` 和 `X-Cost-Credit` 响应头返回。服务端不保存音频，请保存响应体；重复调用会重新生成并再次计费。Beta 期间每个 API Key 的并发数受限，超限请求会被拒绝，不会排队。","create_speech_api_v1_tts_post",70,"\u003Cp>使用 VisionStory 智能 TTS 将文本转换为语音。从 GET \u002Fapi\u002Fv1\u002Fvoices 选择公共声音或自己的克隆声音。服务会根据声音和文本语言自动选择合适的合成策略。按每 1000 字符 2 点计费，向上取整，仅成功时扣费。\u003C\u002Fp>\u003Cp>此接口同步执行，响应体直接返回 MP3 音频（\u003Ccode>audio\u002Fmpeg\u003C\u002Fcode>）。时长与计费信息通过 \u003Ccode>X-Audio-Duration-Sec\u003C\u002Fcode>、\u003Ccode>X-Usage-Characters\u003C\u002Fcode> 和 \u003Ccode>X-Cost-Credit\u003C\u002Fcode> 响应头返回。服务端不保存音频，请保存响应体；重复调用会重新生成并再次计费。Beta 期间每个 API Key 的并发数受限，超限请求会被拒绝，不会排队。\u003C\u002Fp>",[16],{"name":17,"in":18,"required":19,"description":20,"type":21,"example":22},"X-API-Key","header",true,"你的 VisionStory API Key（`sk-vs-...`），请仅保存在服务端。可在 [API Key 管理](\u002Fapi-keys) 中创建或管理，需要 Pro 或更高方案。","string","sk-vs-your-api-key",{"required":19,"contentType":24,"schema":25,"example":51},"application\u002Fjson",{"type":26,"description":27,"nullable":28,"properties":29},"CreateSpeechRequest","",false,[30,35,43,47],{"name":31,"required":28,"type":32,"description":33,"nullable":19,"properties":34},"locale","string | null","可选的 BCP 47 语言区域标记（例如 `en-GB`、`zh-TW`），用于指定多语言声音的发音和口音。具体效果取决于声音引擎的支持情况。默认使用该声音的原生语言区域。",[],{"name":36,"required":28,"type":32,"description":37,"nullable":19,"enum":38,"properties":42},"speech_rate","相对语速：`slow` \u002F `normal` \u002F `fast`，默认 `normal`。与 POST \u002Fapi\u002Fv1\u002Fvideo 中的 `text_script.speech_rate` 使用相同取值。声音引擎原生支持语速控制时由引擎处理，否则通过约 10% 的音频时长伸缩实现，保持音高不变。具体时长变化因声音而异，请读取 `X-Audio-Duration-Sec`。",[39,40,41],"slow","normal","fast",[],{"name":44,"required":19,"type":21,"description":45,"nullable":28,"properties":46},"text","要合成的文本，最多 3000 个字符。",[],{"name":48,"required":19,"type":21,"description":49,"nullable":28,"properties":50},"voice_id","公共声音或克隆声音的 ID，请查询 GET \u002Fapi\u002Fv1\u002Fvoices。",[],{"text":52,"voice_id":53,"locale":54,"speech_rate":40},"Welcome to VisionStory.","voice_123456","en-GB",[56,87],{"status":57,"description":58,"contentType":59,"schema":60,"example":63,"headers":64},"200","MP3 音频（44.1kHz）。用量信息通过响应头返回。示例文本仅为二进制响应体的占位说明，不是可播放音频或 JSON。","audio\u002Fmpeg",{"type":61,"description":27,"nullable":28,"properties":62},"string · binary",[],"\u003Cbinary MP3 audio bytes; save the response body as speech.mp3>",[65,71,76,82],{"type":66,"description":67,"nullable":28,"example":68,"properties":69,"name":70,"required":28},"number","实际生成时长，单位为秒。",1.5,[],"X-Audio-Duration-Sec",{"type":21,"description":72,"nullable":28,"example":73,"properties":74,"name":75,"required":28},"生成音频的标识符。","example_audio_id",[],"X-Audio-Id",{"type":77,"description":78,"nullable":28,"example":79,"properties":80,"name":81,"required":28},"integer","扣除的点数。示例仅用于说明，并非实际报价。",2,[],"X-Cost-Credit",{"type":77,"description":83,"nullable":28,"example":84,"properties":85,"name":86,"required":28},"计费字符数。",22,[],"X-Usage-Characters",{"status":88,"description":89,"contentType":24,"schema":90,"example":113,"headers":116},"default","错误响应。所有失败均使用统一结构：`error` 对象包含数字错误码 `code`、便于阅读的 `message`、可选的 `details` 字符串，以及提供后续处理建议的可选 `hint`（便于 AI Agent 使用）。",{"type":91,"description":27,"nullable":28,"properties":92},"ErrorResponse",[93],{"name":94,"required":19,"type":95,"description":27,"nullable":28,"properties":96},"error","ErrorDetail",[97,101,105,109],{"name":98,"required":19,"type":77,"description":99,"nullable":28,"properties":100},"code","机器可读的错误码。传输层失败时对应 HTTP 状态码（例如 401、404、422、500），其他情况可能使用业务专用错误码。",[],{"name":102,"required":28,"type":32,"description":103,"nullable":19,"properties":104},"details","可选的结构化错误详情，例如 422 响应中逐字段校验错误的 JSON 字符串。无补充信息时不返回。",[],{"name":106,"required":28,"type":32,"description":107,"nullable":19,"properties":108},"hint","供用户和 AI Agent 参考的错误处理建议，例如如何修正请求或在哪里获取 API Key。可能不返回此字段。",[],{"name":110,"required":19,"type":21,"description":111,"nullable":28,"properties":112},"message","便于阅读的错误原因说明，可安全记录到日志或展示给最终用户；此返回值未本地化。",[],{"error":114},{"code":115,"message":21,"details":21,"hint":21},1,[],[118],{"APIKeyHeader":119},[],[121,124,127],{"lang":122,"source":123},"SDK","from pathlib import Path\nfrom visionstory import VisionStoryClient\n\nclient = VisionStoryClient.from_env()\nspeech = client.create_speech(\n    text=\"Welcome to VisionStory.\",\n    voice_id=\"voice_123456\",\n    locale=\"en-GB\",\n    speech_rate=\"normal\",\n)\nPath(\"speech.mp3\").write_bytes(speech[\"audio\"])\nprint({key: value for key, value in speech.items() if key != \"audio\"})",{"lang":125,"source":126},"REST","from pathlib import Path\nimport os\nimport requests\n\nresponse = requests.post(\n    \"https:\u002F\u002Fopenapi.visionstory.ai\u002Fapi\u002Fv1\u002Ftts\",\n    headers={\"X-API-Key\": os.environ[\"VISIONSTORY_API_KEY\"]},\n    json={\n      \"text\": \"Welcome to VisionStory.\",\n      \"voice_id\": \"voice_123456\",\n      \"locale\": \"en-GB\",\n      \"speech_rate\": \"normal\"\n    },\n)\nresponse.raise_for_status()\nPath(\"response.mp3\").write_bytes(response.content)",{"lang":128,"source":129},"cURL","curl --request POST 'https:\u002F\u002Fopenapi.visionstory.ai\u002Fapi\u002Fv1\u002Ftts' \\\n  --header 'X-API-Key: $VISIONSTORY_API_KEY' \\\n  --header 'Content-Type: application\u002Fjson' \\\n  --data '{\n  \"text\": \"Welcome to VisionStory.\",\n  \"voice_id\": \"voice_123456\",\n  \"locale\": \"en-GB\",\n  \"speech_rate\": \"normal\"\n}' \\\n  --output 'response.mp3'","\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF7B72\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> pathlib \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> Path\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF7B72\">from\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> visionstory \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">import\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> VisionStoryClient\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E6EDF3\">client \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> VisionStoryClient.from_env()\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E6EDF3\">speech \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> client.create_speech(\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFA657\">    text\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"Welcome to VisionStory.\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFA657\">    voice_id\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"voice_123456\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFA657\">    locale\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"en-GB\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#FFA657\">    speech_rate\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">=\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"normal\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">,\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E6EDF3\">)\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E6EDF3\">Path(\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"speech.mp3\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">).write_bytes(speech[\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\">\"audio\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">])\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79C0FF\">print\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">({key: value \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">for\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> key, value \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">in\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> speech.items() \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">if\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> key \u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">!=\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> \"audio\"\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">})\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>","\u003Cpre class=\"shiki github-dark-default\" style=\"background-color:#0d1117;color:#e6edf3\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#FF7B72\">HTTP\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\">\u002F\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\">1.1\u003C\u002Fspan>\u003Cspan style=\"color:#79C0FF\"> 200\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> OK\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#7EE787\">Content-Type\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> audio\u002Fmpeg\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#7EE787\">X-Audio-Duration-Sec\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> 1.5\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#7EE787\">X-Audio-Id\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> example_audio_id\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#7EE787\">X-Cost-Credit\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> 2\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#7EE787\">X-Usage-Characters\u003C\u002Fspan>\u003Cspan style=\"color:#FF7B72\">:\u003C\u002Fspan>\u003Cspan style=\"color:#A5D6FF\"> 22\u003C\u002Fspan>\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003C\u002Fspan>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E6EDF3\">&#x3C;\u003C\u002Fspan>\u003Cspan style=\"color:#7EE787\">binary\u003C\u002Fspan>\u003Cspan style=\"color:#E6EDF3\"> MP3 audio bytes; save the response body as speech.mp3>\u003C\u002Fspan>\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>",1788547144540]