中文 ▾
用于 TTS 管道的无审查文本 APIhttps://api.ttsapihub.com/v1

Python TTS API 密钥:配置、流式输出与 JSON 模式

这是该网站背后 API 的 Python 指南:存储密钥、创建客户端、流式输出、强制 JSON 输出并处理速率限制。首先注意:它生成文本,而非音频。

更新于

终端上方发光的密钥,数据流不断,展示从 Python 使用的 API 密钥

要点

  • 该接口兼容 OpenAI,因此 openai Python 包在设置 base_url 为 https://api.ttsapihub.com/v1 时可用
  • 将密钥保存在环境变量中,不要保存在源代码中。
  • 支持流式输出、JSON 模式和函数调用;不支持音频输出。
  • 通过短暂等待处理 HTTP 429,并读取 X-Balance-USD 以跟踪支出。

检查密钥的功能

搜索 tts api key python example 的人通常希望将文本转为语音。此服务的密钥不执行此操作。它用于对文本 LLM 发起请求进行身份验证:POST /v1/chat/completions 和 GET /v1/models,使用模型 uncensored。没有语音合成、没有音频上传,也没有嵌入功能。

如果这符合你的项目需求,例如你生成脚本、对话或旁白并传递给单独的语音工具,本页其余部分提供可用的 Python 代码。如果你需要 API 本身输出音频,则选错了服务,最好尽早知晓。文档列出了确切的功能集。

在音频项目中实用使用文本生成的方法是将其视为写作阶段。模型起草旁白,重写一行以符合时间限制,或将笔记转换为多个说话者的对话。你的 Python 代码随后将最终文本交给你使用的任何语音工具。将阶段分开也意味着你可以交换其中任何一个而不影响另一个,并且你只为它写的单词支付此 API 的费用。

要跟随教程,你需要 Python 3.9 或更高版本以及一个密钥。在 API 密钥页面注册并领取一键式 $0.50 试用额度;有效期 7 天,无需信用卡。

存储密钥并安装包

永远不要将密钥写入你提交的文件中。将其放入环境变量,并在运行时读取。

# base URL used below: https://api.ttsapihub.com/v1 , model: uncensored
pip install openai
export API_KEY="paste-your-key-here"

在 Windows PowerShell 中等效的是 $env:API_KEY = "paste-your-key-here"。对于项目,使用 python-dotenv 等包加载的 .env 文件是常见模式,只要 .env 在你的 .gitignore 中即可。

如果密钥泄露到仓库中,将其视为已失效:如果可以,请从历史记录中删除它,并请求一个新的。请记住,密钥会消耗预付额度,因此泄露的密钥也是财务泄露。

创建客户端并进行首次调用

官方包接受 base_url 参数。其余部分均为标准的 OpenAI 调用格式。

import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.ttsapihub.com/v1",
    api_key=os.environ["API_KEY"],
)

resp = client.chat.completions.create(
    model="uncensored",
    messages=[
        {"role": "system", "content": "You write short narration scripts."},
        {"role": "user", "content": "Draft a 40-word intro for a podcast about night trains."},
    ],
    temperature=0.8,
    max_tokens=200,
)

print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)

usage 对象显示调用使用了多少 token,以便你计算成本:输入 token 数量乘以每百万输入 token $0.15,加上输出 token 数量乘以每百万输出 token $0.50。如果上述调用使用了 60 个输入 token 和 80 个输出 token,成本为 $0.000009 加上 $0.00004,即 $0.000049。失败或被拒绝的请求不收费。

max_tokens 是可选的。如果没有它,补全可以使用 100,000-token 窗口中的剩余部分,所以当你要对长度和成本设置硬性限制时,请设置它。

流式输出回复

流式输出使用服务器发送事件返回生成的 token。设置 stream=True 并迭代。

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])

stream = client.chat.completions.create(
    model="uncensored",
    messages=[{"role": "user", "content": "Describe a rainy station platform in four sentences."}],
    stream=True,
)

parts = []
for chunk in stream:
    if not chunk.choices:
        continue
    delta = chunk.choices[0].delta.content or ""
    parts.append(delta)
    print(delta, end="", flush=True)

text = "".join(parts)

检查空 choices 列表的存在是因为流的最后一个事件可能包含使用数据而没有文本。跳过它可以避免索引错误。一个操作细节:流式请求会占用其并发槽位,直到流结束。如果你在线程中启动许多流且从未读取完毕,即使你的请求速率很低,也会达到并发限制。

请求 JSON 并调用工具

JSON 模式

将 response_format 设置为 JSON 对象以使回复可解析。同时在提示词中告知模型你想要 JSON;该设置约束格式,而提示词告知其结构。

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])

resp = client.chat.completions.create(
    model="uncensored",
    response_format={"type": "json_object"},
    messages=[
        {"role": "system", "content": "Reply only with JSON: {\"title\": str, \"beats\": [str]}"},
        {"role": "user", "content": "Outline a three-beat radio drama about a lost key."},
    ],
)

data = json.loads(resp.choices[0].message.content)
print(data["title"], len(data["beats"]))

无论如何将 json.loads 包装在 try 块中。达到 max_tokens 的回复可能会在对象中间被截断。

函数调用

传递 tools 和可选的 tool_choice。当模型请求工具时,自己运行它并将结果作为带有 role: "tool" 的消息发回。

import json, os
from openai import OpenAI

client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])

tools = [{
    "type": "function",
    "function": {
        "name": "word_count",
        "description": "Count the words in a text",
        "parameters": {
            "type": "object",
            "properties": {"text": {"type": "string"}},
            "required": ["text"],
        },
    },
}]

messages = [{"role": "user", "content": "How many words are in: the quick brown fox?"}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
msg = first.choices[0].message

if msg.tool_calls:
    call = msg.tool_calls[0]
    args = json.loads(call.function.arguments)
    result = len(args["text"].split())
    messages.append(msg)
    messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
    final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
    print(final.choices[0].message.content)

保持对话并监控 token 预算

API 是无状态的。如果你需要一个能记住对话内容的聊天,需在程序中保留消息列表,并在每次调用时发送全部消息。一个简单的类即可完成此工作,也是限制历史记录以防止成本增加的最佳位置。

import os
from openai import OpenAI

client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])

history = [{"role": "system", "content": "You are a dialogue writer. Keep replies under 120 words."}]

def say(user_text, keep_last=12):
    history.append({"role": "user", "content": user_text})
    # keep the system message plus the most recent turns
    trimmed = [history[0]] + history[1:][-keep_last:]
    resp = client.chat.completions.create(model="uncensored", messages=trimmed, max_tokens=250)
    reply = resp.choices[0].message.content
    history.append({"role": "assistant", "content": reply})
    return reply, resp.usage.total_tokens

print(say("Open a scene in a ticket office at closing time.")[0])

修剪历史记录对省钱比节省上下文窗口更重要。模型总共接受最多 100,000 个 token,但如果每轮都重发 30,000 个历史记录 token,仅输入成本每次调用就为 $0.0045(30,000 乘以每百万个 $0.15)。五十轮这样的调用累计达 $0.225,此时甚至还未计算单个输出 token。保留最近十几轮,或将旧内容总结为简短笔记,通常能保持质量并大幅降低账单。

并发是另一个需要设计考虑的因素。如果你的程序同时服务多个用户,使用限制大小为密钥限制(完整密钥为 8,试用密钥为 2)的信号量,可避免触发 concurrency 错误。超过限制的调用会在你自己的队列中等待,这比在 429 错误时重试更友好。

测试也值得一提。编写一个小型脚本,使用固定的 seed、低 temperature 和短 max_tokens 调用 API,并在更改提示词或设置时运行。种子和低 temperature 使输出更具可重复性,从而让你在不受随机性干扰的情况下比较两个提示词版本。保持这些测试极小化;花费不到一美分的测试可在每次提交时运行,且无人会注意到账单。

最后,记录每个回复的请求 ID。当调用行为异常时,该 ID 是让支持团队定位确切请求的最快方式。

处理限制、错误和余额

完整密钥允许 8 个并发请求和每分钟 300 个请求。试用密钥允许 2 个和 60 个。超过第一个返回 HTTP 429,错误代码为 concurrency,超过第二个返回 429,错误代码为 rate_limited。临时过载也返回带有 Retry-After: 5 头的 429。

OpenAI 包会自动重试一些失败,你可以使用 max_retries 提高该值。对于批处理作业,也添加你自己的并行工作上限,以便保持在并发限制之下,而不是依赖重试。

import os
from openai import OpenAI, RateLimitError

client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"], max_retries=3)

raw = client.chat.completions.with_raw_response.create(
    model="uncensored",
    messages=[{"role": "user", "content": "One sentence about trains."}],
    max_tokens=60,
)
print("balance:", raw.headers.get("X-Balance-USD"))
print("request id:", raw.headers.get("X-Request-Id"))
print(raw.parse().choices[0].message.content)

响应头 X-Request-Id 和 X-Balance-USD 在日志中很有用。联系支持时请引用请求 ID。费用列在 定价页面:每 1M 输入 token $0.15,每 1M 输出 token $0.50,充值金额为 $20 至 $500,并在 $50、$100 和 $200 时分别提供 5%、10% 和 15% 的奖金。接受银行卡(Visa、Mastercard、Apple Pay、Google Pay)和加密货币(TRC20 网络上的 USDT、Base 网络上的 USDC)。提示词不用于训练。该模型适用于合法成人用途,且绝不允许涉及未成年人的色情内容。

问答

此 API 密钥可在 Python 中用于文本转语音吗?

不行。该密钥用于验证文本 LLM API,无音频输出。用它生成文本,然后将文本传递给语音工具。

我应该使用哪个 Python 包?

官方 openai 包。将 base_url 设置为 https://api.ttsapihub.com/v1,将模型设置为 uncensored。

如何将密钥排除在代码之外?

从 API_KEY 等环境变量读取,并将任何 .env 文件排除在版本控制之外。

如何查看每次调用的费用?

读取 resp.usage 获取 token 计数,读取 X-Balance-USD 响应头获取剩余余额。

达到速率限制时会发生什么?

API 返回 HTTP 429,错误代码为 rate_limited 或 concurrency。等待几秒后重试;该失败的请求不收费。

只差一张表单,即可获得密钥

创建账户,复制密钥,更改基础 URL。这就是全部设置。

获取 API 密钥