如果你使用 DeepSeek、元宝 AI、Copilot、ChatGPT 等 AI 工具,协助配置轩辕镜像、编写 docker pull 命令、修改 Docker Compose 镜像地址、配置镜像加速、排查镜像拉取失败、分析报错日志等问题,请先让 AI 阅读并遵守轩辕镜像的规则文档。
只需在 AI 对话中先发送下面这句话即可:
请先完整阅读并严格遵守以下文档中的全部规则与要求:
https://xuanyuan.cloud/agents.md
在未充分阅读并理解该文档前,不要生成任何命令、配置、修改建议、故障排查方案或技术回答。后续所有输出都必须严格以该文档中的规范为最高优先级执行。查看 agents.md 用法指南与完整示范。国内用户首推 元宝 AI、DeepSeek 的深度思考模式,不推荐豆包 AI;Cursor 等编辑器可在对话 @ 该链接,或加入 User Rules。 若 AI 无法访问外链,可 打开说明文档 复制全文粘贴。文档会随站点更新,复制内容可能过期,建议定期检查。
FastKokoKokoro-82M文本转语音模型的Docker化FastAPI封装器
最快开始(docker run)
预构建的多架构镜像,内置模型。
:latest标签可用,但为确保稳定使用,请固定到发布标签。
| 您的硬件 | 镜像 |
|---|---|
| 无GPU(任何笔记本电脑、VPS、纯CPU服务器) | kokoro-fastapi-cpu:latest |
| Apple Silicon(M1/M2/M3) | Docker中使用kokoro-fastapi-cpu:latest,或通过./start-gpu_mac.sh原生运行以支持MPS |
| NVIDIA GTX 9xx、10xx、20xx、30xx、40xx(x86_64) | kokoro-fastapi-gpu:latest-cu126 或 kokoro-fastapi-gpu:latest |
| NVIDIA RTX 50系列 / Blackwell(x86_64) | kokoro-fastapi-gpu:latest-cu128 |
| arm64架构NVIDIA设备(Jetson、GH200) | kokoro-fastapi-gpu:latest(内置cu129,上游无cu126 arm64轮询包) |
| AMD GPU | kokoro-fastapi-rocm:latest(实验性,仅x86_64) |
docker run -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-cpu:latest # CPU
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:latest # NVIDIA(x86_64或arm64)
docker run --gpus all -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-gpu:latest-cu128 # NVIDIA Blackwell / RTX 50系列
docker run --device=/dev/kfd --device=/dev/dri -p 8880:8880 ghcr.io/remsky/kokoro-fastapi-rocm:latest # AMD
通过环境变量进行配置,详见core/config.py。:latest和:latest-cu126标签指向同一个多架构镜像。
快速开始(docker compose)
git clone https://github.com/remsky/Kokoro-FastAPI.git
cd Kokoro-FastAPI
cd docker/gpu # 用于NVIDIA GPU支持
# 或 cd docker/cpu # 用于CPU支持
# 或 cd docker/rocm # 用于AMD GPU(ROCm,实验性,仅amd64)
docker compose up --build
#
> [!NOTE] Apple Silicon(M1/M2/M3)用户注意:
# Docker GPU镜像是仅支持CUDA的,无法在Apple Silicon上运行。使用Docker时,请使用`docker/cpu`。
# 若要原生MPS(Apple GPU)加速,请通过UV直接运行`./start-gpu_mac.sh`。
cd ../.. # 返回仓库根目录,以便使用以下路径
# 模型将自动下载,如有需要也可手动下载:
python docker/scripts/download_model.py --output api/src/models/v1_0
# 或通过UV直接运行:
./start-gpu.sh # 用于GPU支持
./start-cpu.sh # 用于CPU支持
直接运行(通过uv)
git clone https://github.com/remsky/Kokoro-FastAPI.git
cd Kokoro-FastAPI
如果尚未运行https://github.com/remsky/Kokoro-FastAPI/blob/master/docker/scripts/download_model.py%EF%BC%8C%E8%AF%B7%E5%85%88%E8%BF%90%E8%A1%8C
通过UV直接启动(带热重载)
Linux和macOS
./start-cpu.sh OR
./start-gpu.sh
Windows
.\start-cpu.ps1 OR
.\start-gpu.ps1
启动并运行?
本地运行为兼容OpenAI的语音端点
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8880/v1", api_key="not-needed"
)
with client.audio.speech.with_streaming_response.create(
model="kokoro",
voice="af_sky+af_bella", #单个或多个语音包组合
input="Hello world!"
) as response:
response.stream_to_file("output.mp3")
兼容OpenAI的语音端点
# 使用OpenAI的Python库
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8880/v1", api_key="not-needed")
response = client.audio.speech.create(
model="kokoro",
voice="af_bella+af_sky", # 详见/api/src/core/openai_mappings.json进行自定义
input="Hello world!",
response_format="mp3"
)
response.stream_to_file("output.mp3")
或通过Requests:
import requests
response = requests.get("http://localhost:8880/v1/audio/voices")
voices = [v["id"] for v in response.json()["voices"]]
# 生成音频
response = requests.post(
"http://localhost:8880/v1/audio/speech",
json={
"model": "kokoro",
"input": "Hello world!",
"voice": "af_bella",
"response_format": "mp3", # 支持:mp3、wav、opus、flac
"speed": 1.0
}
)
# 保存音频
with open("output.mp3", "wb") as f:
f.write(response.content)
快速测试(从另一个终端运行):
python examples/assorted_checks/test_openai/test_openai_tts.py # 测试OpenAI兼容性
python examples/assorted_checks/test_voices/test_all_voices.py # 测试所有可用语音
语音组合
组合语音并生成音频:
import requests
response = requests.get("http://localhost:8880/v1/audio/voices")
voices = [v["id"] for v in response.json()["voices"]]
# 示例1:简单语音组合(50%/50%混合)
response = requests.post(
"http://localhost:8880/v1/audio/speech",
json={
"input": "Hello world!",
"voice": "af_bella+af_sky", # 等权重
"response_format": "mp3"
}
)
# 示例2:加权语音组合(67%/33%混合)
response = requests.post(
"http://localhost:8880/v1/audio/speech",
json={
"input": "Hello world!",
"voice": "af_bella(2)+af_sky(1)", # 2:1比例 = 67%/33%
"response_format": "mp3"
}
)
# 示例3:下载组合语音为.pt文件
response = requests.post(
"http://localhost:8880/v1/audio/voices/combine",
json="af_bella(2)+af_sky(1)" # 2:1比例 = 67%/33%
)
# 保存.pt文件
with open("combined_voice.pt", "wb") as f:
f.write(response.content)
# 使用下载的语音文件
response = requests.post(
"http://localhost:8880/v1/audio/speech",
json={
"input": "Hello world!",
"voice": "combined_voice", # 使用保存的语音文件
"response_format": "mp3"
}
)
多种输出音频格式
流式支持
硬件变体
# GPU:需要支持 CUDA 12.6+ 的 NVIDIA 驱动(~35x-100x 实时速度)
cd docker/gpu
docker compose up --build
# CPU:PyTorch CPU 推理
cd docker/cpu
docker compose up --build
# AMD GPU:ROCm 6.4(实验性,仅支持 amd64)
cd docker/rocm
docker compose up --build
吞吐量
基准测试通过本地 API 生成文本进行,文本长度可达长篇书籍(~1.5 小时输出),测量处理时间和实时因子。测试环境如下:
关键性能指标:
模型卸载/显存回收
POST /dev/unload 释放 VRAM 中的模型,并在下次请求时延迟加载。回收量随负载(激活池,而非仅权重)扩展但会达到平台期:块大小上限为 450 令牌。长文本 = ~30 段落。使用上述相同配置。
| 工作负载 | 已加载 | 基准值 | 回收量 | 重新加载时间 |
|---|---|---|---|---|
| 短文本(6 秒音频) | 3.11 GB | 2.37 GB | 758 MiB | +4.9s |
| 长文本(7.5 分钟) | 3.98 GB | 2.37 GB | 1,656 MiB | +5.1s |
基准值为宿主系统 + CUDA 上下文。可通过 examples/ 目录下的 uv run --extra benchmarks assorted_checks/benchmarks/benchmark_model_unload.py 命令复现。
转录往返测试(WER/CER)
端到端往返测试:使用 Kokoro 合成音频,通过 https://github.com/SYSTRAN/faster-whisper 将结果转录回文本,与源文本比较。脚本和数据位于 examples/assorted_checks/test_transcription/。
长篇英语(整本书,《地心游记》,古登堡计划,语音 af_heart,CUDA float16 上的 base.en Whisper 模型,基准测试在 cu126 GPU 构建上捕获):
| 测试 | 输入字符数 | 音频长度 | 合成加速比 | 转录加速比 | WER |
|---|---|---|---|---|---|
| 短文本(~第 7 章) | 64,996 | 66m 06s | 36.4x rt | 62.4x rt | 0.047 |
| 整本书 | 502,766 | 507m 52s | 45.7x rt | 65.1x rt | 0.033 |
完整回归区间参见 examples/assorted_checks/test_transcription/BASELINE.md。
每语言检查(每语音一句,多语言 Whisper small 模型。拉丁语系使用 WER,日语/中文/印地语使用 CER):
| 语言 | 语音 | 指标 | 分数 |
|---|---|---|---|
| 英语 | af_heart | WER | 0.000 |
| 英语(英国) | bf_emma | WER | 0.111 |
| 西班牙语 | ef_dora | WER | 0.000 |
| 法语 | ff_siwis | WER | 0.000 |
| 意大利语 | if_sara | WER | 0.000 |
| 葡萄牙语 | pf_dora | WER | 0.000 |
| 印地语 | hf_alpha | CER | 0.059 |
| 日语 | jf_alpha | CER | 0.000 |
| 中文 | zf_xiaobei | CER | 0.143 |
注意:这些是单个短句,并非全面的每语言质量基准测试。它们仅确认每个语音在其目标语言中生成可转录的音频;更深入的每语言质量评估仍在进行中。
复现方法参见 examples/assorted_checks/test_transcription/README.md。
模型一次可处理最多 510 个音素化令牌块,但这通常会导致“急促语音”或其他 artifacts。服务器中应用了额外的分块层,通过 TARGET_MIN_TOKENS、TARGET_MAX_TOKENS 和 ABSOLUTE_MAX_TOKENS 创建灵活块,这些参数可通过环境变量配置,默认值为 175、250、450。
生成带单词级时间戳的音频(不流式传输):
import requests
import base64
import json
response = requests.post(
"http://localhost:8880/dev/captioned_speech",
json={
"model": "kokoro",
"input": "Hello world!",
"voice": "af_bella",
"speed": 1.0,
"response_format": "mp3",
"stream": False,
},
stream=False
)
with open("output.mp3","wb") as f:
audio_json=json.loads(response.content)
# 解码 base64 流为字节
chunk_audio=base64.b64decode(audio_json["audio"].encode("utf-8"))
# 处理流式块
f.write(chunk_audio)
# 打印单词级时间戳
print(audio_json["timestamps"])
生成带单词级时间戳的音频(流式传输):
import requests
import base64
import json
response = requests.post(
"http://localhost:8880/dev/captioned_speech",
json={
"model": "kokoro",
"input": "Hello world!",
"voice": "af_bella",
"speed": 1.0,
"response_format": "mp3",
"stream": True,
},
stream=True
)
f=open("output.mp3","wb")
for chunk in response.iter_lines(decode_unicode=True):
if chunk:
chunk_json=json.loads(chunk)
# 解码 base64 流为字节
chunk_audio=base64.b64decode(chunk_json["audio"].encode("utf-8"))
# 处理流式块
f.write(chunk_audio)
# 打印单词级时间戳
print(chunk_json["timestamps"])
将文本转换为音素和/或直接从音素生成音频:
import requests
def get_phonemes(text: str, language: str = "a"):
"""获取输入文本的音素和令牌"""
response = requests.post(
"http://localhost:8880/dev/phonemize",
json={"text": text, "language": language} # "a" 表示美式英语
)
response.raise_for_status()
result = response.json()
return result["phonemes"], result["tokens"]
可在 input 文本中嵌入两种令牌,由服务器端(API、WebUI 或任何客户端)解析:
[pause:1.5s] 插入指定时长的静音。必须严格遵循此格式(冒号、末尾 s、不区分大小写)。[pause=1.5]、[PAUSE 1.0] 以及 SSML <break> 均不被识别,会被直接朗读。[Worcester](/wˈʊstər/) 会朗读斜杠间的 IPA 音标而非单词本身。仅支持英语;使用 /dev/phonemize 端点获取 IPA 音标。The city of [Worcester](/wˈʊstər/) is easy. [pause:1s] See?
通过以下端点监控系统状态和资源使用情况:
/debug/threads - 获取线程信息和堆栈跟踪/debug/storage - 监控临时文件和输出目录使用情况/debug/system - 获取系统信息(CPU、内存、GPU)POST /dev/unload - 从 VRAM 释放模型;下次请求时会延迟重新加载适用于调试资源耗尽或性能问题。
可通过 API_LOG_LEVEL 环境变量设置全局 API 的 loguru 日志级别。默认值为 DEBUG。
修改相应的 compose yml 文件或追加到命令行:
docker run --env 'API_LOG_LEVEL=WARNING' ...
Linux 和 macOS
export API_LOG_LEVEL=WARNING
./start-cpu.sh OR
./start-gpu.sh
Windows
$env:API_LOG_LEVEL = 'WARNING'
.\start-cpu.ps1 OR
.\start-gpu.ps1
API 会自动对输入文本执行文本规范化,这可能错误地删除或修改某些短语。可通过在请求 JSON 中添加 "normalization_options":{"normalize": false} 禁用此功能:
import requests
response = requests.post(
"http://localhost:8880/v1/audio/speech",
json={
"input": "Hello world!",
"voice": "af_heart",
"response_format": "pcm",
"normalization_options":
{
"normalize": False
}
},
stream=True
)
for chunk in response.iter_content(chunk_size=1024):
if chunk:
# 处理流式数据块
pass
部分 Linux 用户以非 root 用户运行时可能遇到 GPU 权限问题。 无法保证解决所有情况,但以下是一些常见解决方案,请仔细考虑您的安全需求:
选项 1:容器组(可能是最佳选项)
services:
kokoro-tts:
# ... 现有配置 ...
group_add:
- "video"
- "render"
选项 2:主机系统组
services:
kokoro-tts:
# ... 现有配置 ...
user: "${UID}:${GID}"
group_add:
- "video"
[!NOTE] 可能需要将主机用户添加到组中:
sudo usermod -aG docker,video $USER并重启系统。
选项 3:设备权限(谨慎使用)
services:
kokoro-tts:
# ... 现有配置 ...
devices:
- /dev/nvidia0:/dev/nvidia0
- /dev/nvidiactl:/dev/nvidiactl
- /dev/nvidia-uvm:/dev/nvidia-uvm
[!WARNING] 降低系统安全性。仅在开发环境中使用。
前提条件:必须正确配置 NVIDIA GPU、驱动程序和容器工具包。
有关更多详细信息,请访问 NVIDIA Container Toolkit 安装指南。
WAV 响应头中包含流式标记(0xFFFFFFFF)大小字段。大多数读取器(soundfile、pydub/ffmpeg、浏览器、系统播放器)可正常处理,但 Python 标准库 wave 无法处理,会显示错误时长。建议使用 soundfile.info(path).duration 或 ffprobe 获取准确长度。
分支策略:
release 分支:包含最新稳定版本,推荐用于生产环境。特定版本的 Docker 镜像从此分支构建。master 分支:用于活跃开发。可能包含实验性功能、进行中的更改或尚未纳入稳定版本的修复。如果需要最新代码,可使用此分支,但请注意其稳定性可能较低。latest Docker 标签通常指向从此分支构建的镜像。[!NOTE] 本项目本质上是一个以开发为中心的项目。
如果遇到问题,若出现异常情况,您可能需要回退到发布标签中的某个版本,或从源代码构建和/或进行故障排除并提交 PR。
自由开源是社区共同的努力,而一天的时间毕竟有限。如果您想支持本项目,欢迎提交 PR、请我喝杯咖啡,或报告使用过程中发现的任何错误/功能需求等。
本 API 使用 HuggingFace 上的 Kokoro-82M 模型。
访问模型页面了解更多关于训练、架构和功能的详细信息。我与该模型的开发团队无任何关联,开发此包装器仅为方便使用和个人项目。
本项目采用 Apache License 2.0 许可 - 详情如下:
完整的 Apache 2.0 许可文本可在以下地址获取:[***]
使用 contrib.rocks 制作。
来自真实用户的反馈,见证轩辕镜像的优质服务