【語音合成技術 - Kokoro TTS】比想像中更強!用 Python + uv 打造支援繁中的語音 API

更新 發佈閱讀 13 分鐘

🚀 前言:一場意外的發現之旅

我一直以為語音生成(TTS)技術的門檻很高,不是要靠 Google Cloud、Azure Cognitive Service,就是要跑大量 GPU 模型,部署又複雜、成本又高,很難真正「自己掌握」。

直到某天,我在 GitHub 上看到 Kokoro TTS 一個開源、小體積、速度快、語音自然,而且竟然還支援繁體中文的模型!

我抱著「應該很難跑起來吧」的心態實測,沒想到:

👉 不到 10 秒完成安裝

👉 第一次執行會自動下載模型

👉 20 行 Python 就能生成音檔

👉 支援中文。

於是,我直接把它包成 API,做成一個可以網頁輸入文字 → 返回語音 → 直接播放的小專案。

這篇文章就帶你一步步實作它!

🧐 為什麼選擇 Kokoro TTS?我的實測心得

raw-image


🛠️ 實作藍圖:我們要打造什麼?

我們目標是建立一個「前後端分離」的極簡語音服務,為了讓大家更清楚資料是怎麼流動的,我畫了一張簡單的流程圖:

raw-image


💻 動手實作:Python + uv 的現代化開發體驗

這次我們不使用傳統的 pip 和 venv,改用最近 Python 社群爆紅的工具 uv。相信我,用過它極速的安裝體驗後,你就回不去了。

✨ 步驟一:閃電般的虛擬環境建置 (使用 uv)

打開你的終端機 (Terminal),跟著我輸入幾個指令,環境瞬間就架好了:

# 1. 初始化一個新專案 ✨
uv init my-kokoro-api
cd my-kokoro-api

# 2. 建立虛擬環境 (.venv) 📦
uv venv

# 3. 啟動虛擬環境 (Windows) -> 記得看到命令列前面出現 (.venv)
.venv\Scripts\activate
# 3. 啟動虛擬環境 (Mac/Linux)
# source .venv/bin/activate


🔹 步驟二: pyproject.toml 定義專案環境

[project]
name = "my-kokoro-api"
version = "0.1.0"
description = "Kokoro TTS API with FastAPI and PyTorch"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"fastapi>=0.115.0",
"uvicorn[standard]>=0.32.0",
"torch>=2.5.0",
"numpy>=2.0.0",
"kokoro>=0.2.0",
"misaki[zh]>=0.1.0",
]

安裝相依套件:

uv sync


🔹 步驟三:打造後端核心 (main.py)

修改專案裡面的 main.py 檔案,貼上以下程式碼。我已經加上了詳細的註解,讓你看看它有多簡單:

import io
import wave
import numpy as np
from fastapi import FastAPI
from fastapi.responses import StreamingResponse, HTMLResponse
from pydantic import BaseModel
from kokoro import KPipeline

app = FastAPI()

# 全域變數存放模型
pipeline = None

def get_pipeline():
"""延遲載入模型"""
global pipeline
if pipeline is None:
pipeline = KPipeline(lang_code='z') # 'z' = Mandarin Chinese
return pipeline

class TTSRequest(BaseModel):
text: str

@app.post("/api/tts")
async def text_to_speech(request: TTSRequest):
# 1. 呼叫 Kokoro 模型生成音訊
tts_pipeline = get_pipeline()
results = list(tts_pipeline(request.text, voice='zf_xiaoxiao'))

# 取得音訊數據 (3個元素是音訊tensor)
_, _, audio_tensor = results[0]
samples = audio_tensor.cpu().numpy()
sample_rate = 24000 # Kokoro 的採樣率

# 2. 轉換為 16-bit PCM 格式
audio_data = (samples * 32767).astype(np.int16)

# 3. 建立 WAV 檔案
wav_buffer = io.BytesIO()
with wave.open(wav_buffer, 'wb') as wav_file:
wav_file.setnchannels(1)
wav_file.setsampwidth(2)
wav_file.setframerate(sample_rate)
wav_file.writeframes(audio_data.tobytes())

wav_buffer.seek(0)

# 4. 回傳 WAV 音訊流
return StreamingResponse(wav_buffer, media_type="audio/wav")

@app.get("/", response_class=HTMLResponse)
async def homepage():
with open("index.html", encoding="utf-8") as f:
return HTMLResponse(f.read())

if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=9000)


啟動服務器:

uv run uvicorn main:app --reload --port 9000


瀏覽器開啟: 👉 http://localhost:9000


🔹 步驟四:簡易前端測試 (index.html)

最後,我們寫一個超級陽春的 HTML 頁面來測試成果。在同一個資料夾下建立 index.html:

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kokoro TTS 範例</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
h1 {
color: #333;
}
textarea {
width: 100%;
height: 100px;
padding: 10px;
font-size: 16px;
margin: 10px 0;
}
button {
background-color: #4CAF50;
color: white;
padding: 15px 32px;
font-size: 16px;
border: none;
cursor: pointer;
border-radius: 4px;
}
button:hover {
background-color: #45a049;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
#status {
margin-top: 20px;
padding: 10px;
border-radius: 4px;
}
.success {
background-color: #d4edda;
color: #155724;
}
.error {
background-color: #f8d7da;
color: #721c24;
}
</style>
</head>
<body>
<h1>🔊 Kokoro TTS 範例</h1>
<textarea id="textInput" placeholder="請輸入要轉換為語音的文字...">你好,這是使用 Kokoro 的中文語音合成範例。</textarea>
<br>
<button id="generateBtn" onclick="generateSpeech()">生成語音</button>
<div id="status"></div>

<script>
async function generateSpeech() {
const text = document.getElementById('textInput').value;
const button = document.getElementById('generateBtn');
const status = document.getElementById('status');

if (!text.trim()) {
status.className = 'error';
status.textContent = '請輸入文字!';
return;
}

button.disabled = true;
status.className = '';
status.textContent = '正在生成語音...';

try {
// 1. 發送文字請求到後端
const response = await fetch('/api/tts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: text })
});

if (!response.ok) {
throw new Error('生成失敗');
}

// 2. 接收音訊數據
const blob = await response.blob();
const audioUrl = URL.createObjectURL(blob);

// 3. 播放聲音
const audio = new Audio(audioUrl);
audio.play();

status.className = 'success';
status.textContent = '✓ 語音生成成功!正在播放...';

} catch (error) {
status.className = 'error';
status.textContent = '✗ 錯誤:' + error.message;
} finally {
button.disabled = false;
}
}
</script>
</body>
</html>
raw-image


🎉 結語:實現「語音自由」

打開 index.html,在文字框裡輸入一句繁體中文,按下按鈕。幾秒鐘後,聽到瀏覽器播報出聲音的那一刻,是不是超有成就感?

透過 Kokoro-82M 這個小而美的模型,加上 Python 強大的生態系,我們幾乎是用「零成本」的方式,在自己電腦上實現了高品質的語音合成服務。

這意味著,未來你想幫你的聊天機器人加上嘴巴、想自動把網路文章轉成 Podcast,都不再需要依賴昂貴的外部服務。技術掌握在自己手裡,這種感覺真的很棒!

如果你也對語音技術有興趣,強烈推薦你動手玩玩看 Kokoro!

😎 後續我們也會分享更輕量、效率更高的 onnx版本, 甚至我們會加入ASR的整合應用, 打造一個Voicebot應用, 敬請期待 😎。

留言
avatar-img
留言分享你的想法!
avatar-img
阿Han的沙龍
148會員
317內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
阿Han的沙龍的其他內容
2025/10/02
在AI、機器學習的領域裡, 我們常常需要評估訓練模型的好與壞, 通常我們關注的是準確率, 其中還有兩個容易被搞混的名詞: • Precision(精確率) • Recall(召回率) 為了搞懂這些名詞, 我們將以2020年發生的Covid-19來舉例說明, 幫助需要的朋友快速理解兩者差異。
Thumbnail
2025/10/02
在AI、機器學習的領域裡, 我們常常需要評估訓練模型的好與壞, 通常我們關注的是準確率, 其中還有兩個容易被搞混的名詞: • Precision(精確率) • Recall(召回率) 為了搞懂這些名詞, 我們將以2020年發生的Covid-19來舉例說明, 幫助需要的朋友快速理解兩者差異。
Thumbnail
2025/09/25
✨ 前言 如果說 GPT 就像是一位聰明的助手,那 AutoGen 就是讓你能夠組建一個小型 AI 團隊,彼此協作完成任務的框架。 就像我們真實的世界裡一般, 這個時代不再是單打獨鬥的時代了, 而是組成一個團隊, 針對共同的問題去解決, 團隊中各個成員具備不同的能力與思維, 我們驅動者要學會如何
Thumbnail
2025/09/25
✨ 前言 如果說 GPT 就像是一位聰明的助手,那 AutoGen 就是讓你能夠組建一個小型 AI 團隊,彼此協作完成任務的框架。 就像我們真實的世界裡一般, 這個時代不再是單打獨鬥的時代了, 而是組成一個團隊, 針對共同的問題去解決, 團隊中各個成員具備不同的能力與思維, 我們驅動者要學會如何
Thumbnail
2025/09/18
你有沒有遇過這樣的情況:打開一份上百頁的 PDF 文件,只是為了找一個小小的答案,結果花了半小時還翻不到重點? 我常常在讀技術文件或研究資料時,都遇到這種麻煩,於是我開始想:能不能做一個「文件助理」,讓我可以直接問它問題,它會自動在文件裡找到相關內容,再用 AI 幫我整理答案? 就這樣,我設計並
Thumbnail
2025/09/18
你有沒有遇過這樣的情況:打開一份上百頁的 PDF 文件,只是為了找一個小小的答案,結果花了半小時還翻不到重點? 我常常在讀技術文件或研究資料時,都遇到這種麻煩,於是我開始想:能不能做一個「文件助理」,讓我可以直接問它問題,它會自動在文件裡找到相關內容,再用 AI 幫我整理答案? 就這樣,我設計並
Thumbnail
看更多
你可能也想看
Thumbnail
近來隨AI技術演進,網際智慧重新開發,推出「文字MP3專業版」,將應用層面擴大至有聲書、影片配音等,獲得2022年金塾獎新興技術組秀才。「文字MP3專業版」提供高品質真人發音引擎,可將大量文字内容轉換為朗讀聲音檔,並可在同一篇文字內容中切換不同朗讀聲音,並輸出為MP3或WAV聲音檔案。
Thumbnail
近來隨AI技術演進,網際智慧重新開發,推出「文字MP3專業版」,將應用層面擴大至有聲書、影片配音等,獲得2022年金塾獎新興技術組秀才。「文字MP3專業版」提供高品質真人發音引擎,可將大量文字内容轉換為朗讀聲音檔,並可在同一篇文字內容中切換不同朗讀聲音,並輸出為MP3或WAV聲音檔案。
Thumbnail
「文字MP3」是如何將一篇包含有中文、英文、數字、符號的文字使用朗讀内容時,能夠用我們口語化、習慣的唸法進行朗讀? 「文字MP3」支援的文字正規化 (text normalization):
Thumbnail
「文字MP3」是如何將一篇包含有中文、英文、數字、符號的文字使用朗讀内容時,能夠用我們口語化、習慣的唸法進行朗讀? 「文字MP3」支援的文字正規化 (text normalization):
Thumbnail
TTS文字轉語音應用特色 1. TTS主要功能 將text文字檔的內容,轉換為wav檔,可送到Buffer,播放軟體可以讀取buffer做聲音後處理 能自動判斷前後文,自動判斷常用多音字、年份、日期、時間、電話、數字、%
Thumbnail
TTS文字轉語音應用特色 1. TTS主要功能 將text文字檔的內容,轉換為wav檔,可送到Buffer,播放軟體可以讀取buffer做聲音後處理 能自動判斷前後文,自動判斷常用多音字、年份、日期、時間、電話、數字、%
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News