目錄(23 節)

Python 粵語 TTS cookbook:用 Python 生成廣東話語音完整教學

用 Python 幾十行 code 就出到廣東話語音:申請金鑰、發出第一個生成請求、輪詢任務、下載音頻、攞 SRT 字幕,仲有貼稿轉換、拆段並行、錯誤處理、批量排程同成本管理貼士。

— 港嘢內容團隊約 12 分鐘粵語TTSPythonAPI 教學
分享:

一句答你: 用 Python 生成廣東話語音,行一條 REST API 流程就夠:POST 提交文字任務、攞 job id、輪詢狀態、下載音頻,需要嘅話仲可以同時攞 SRT 字幕。單次任務上限 500 字符,異步輪詢配合 requests 幾十行就寫得完,免費開戶即有 每月 5,000 字符試玩。呢篇 cookbook 由環境準備教到批量同成本管理。

Key Takeaways

  • 粵語 TTS 以異步為主:提交任務回 202 加 job id,輪詢 GET 攞狀態,completed 先有音頻連結。
  • 單次 text 限 1 至 500 字符,超額成個請求被拒、唔會截斷,長文要預先拆段。
  • SRT 字幕喺提交時開 srt 選項就有,同樣行異步軌;同步捷徑唔支援字幕。
  • 免費帳戶每月 5,000 字符;免費同入門方案可以開沙盒金鑰,每日 20 個生成提交,輪詢下載唔計數。
  • 在途任務上限按方案分級:免費 3、入門 5、專業 10、工作室 20,並行拆段要用佇列控制。
  • 批量一次最多 25 項,專業同工作室方案專屬;一次批量只計一次限流。

Python 開發者點解要識粵語 TTS

Python 係香港好多人做內容同數據處理嘅主力工具,而「將文字變成廣東話聲音」正正係好多 Python 項目缺嘅最後一塊:每日新聞摘要變成朝早嘅語音簡報、課程文字稿變成旁白、報告重點變成電話通知、文章平台加返個朗讀掣。呢啲嘢嘅共通點係文字不斷更新,預錄根本追唔切,一定要靠即場生成。

再諗深一層,語音化其實係好抵嘅二次利用:你手上已經有嘅文章、通訊、教材,全部係現成稿源,行一次轉換流程就多一條內容線,唔使由零創作。對一個人手緊絀嘅小團隊嚟講,等於免費多咗個製作助手,而且佢唔會攞假期的。

仲有一個實際考量:香港受眾對「把聲正唔正」好敏感。同一篇稿,用帶廣東話語感嘅聲線讀,同用其他語言聲線讀,觀眾留低嘅印象差好遠。所以喺香港做內容自動化,揀一個專心做好粵語嘅語音引擎,唔係錦上添花,係基本盤。未接觸過粵語語音合成嘅讀者,建議先睇廣東話 TTS 完全指南打好底,再返嚟跟住做。

技術上,粵語 TTS API 係純 REST 設計,以異步流程為主:提交任務之後,用 job id 輪詢狀態,完成先攞到音頻。呢個模式用 Python 寫極之直接,一個 requests 加一個簡單循環就搞定,唔使裝任何官方 SDK,亦都唔使學新嘅設定語言。

本篇結構照住開發順序行:先準備金鑰同額度,再出第一個請求,跟住輪詢同下載,之後先係字幕、貼稿、拆段、批量呢啲進階位。有經驗嘅讀者可以直跳去需要嗰節;但建議至少睇埋錯誤處理同成本兩節,呢兩樣先係上線之後救你命嘅嘢。

環境準備:金鑰同套件

申請同保管金鑰

喺港嘢帳戶入面建立 API 金鑰:正式環境用 sk_live_ 開頭嘅金鑰,開發調試用 sk_test_ 開頭嘅沙盒金鑰。原始金鑰字串只會顯示一次,系統之後只保留加密指紋,所以建立嗰刻就要擺入環境變數,用 python-dotenv 之類管理,切勿寫死喺程式碼或者 commit 上去。團隊合作的話,建議開發、正式各有各嘅金鑰,限流同月度上限分開設定,就算開發環境失控都唔會食晒正式嘅配額。

權限用預設嘅 tts:generate 已經覆蓋生成同查詢;要接聲音複製先至需要額外開 tts:clone。

額度點計

  • 免費帳戶:每月 5,000 字符,唔會每月重置;按每分鐘約 240 字符估算,約莫 21 分鐘音頻,夠你行通整條流程。
  • 沙盒金鑰:免費同入門方案每日 20 個生成提交,只計提交,輪詢同下載免計,開發期用最啱。升級專業後金鑰即時自動轉全速。
  • 付費方案:入門每月 200,000 字符(HK$128)、專業 600,000(HK$338)、工作室 1,400,000(HK$688),每個帳單週期重置,同網頁版共用。

套件方面,一個 requests 就夠全篇用。想跟埋由零開始嘅註冊同設定步驟,可以對照粵語 TTS API 快速上手一齊行。

第一個生成請求

生成入口係 POST /v1/audio/jobs,最簡單嘅請求只要 text(1 至 500 字符)同 voice(聲線嘅英文識別碼)兩個欄位。

import os, requests

BASE = "https://canto-gen.com"
KEY = os.environ["CANTO_API_KEY"]
HEADERS = {"Authorization": "Bearer " + KEY}

resp = requests.post(
    BASE + "/v1/audio/jobs",
    headers=HEADERS,
    json={
        "text": "各位早晨,今日嘅天氣同交通消息即刻為你送上。",
        "voice": "sum",
    },
    timeout=30,
)
print(resp.status_code, resp.json())  # 202 加 job_id

三個細節要留神:

  • voice 填英文識別碼,唔係中文名。識別碼係穩定嘅 ASCII 字串,例如心妍係 sum;用 GET /v1/voices 可以攞到完整目錄,每把聲線都有試聽片段,落手寫 code 之前先聽清楚。
  • 202 先算成功。回應帶 job_id,記低佢做輪詢用;呢個 id 亦係你日誌入面排查嘅主鑰匙,建議同稿件版本一齊記錄。
  • 文字限 1 至 500 字符,超額回 400 text_too_long 而且成個請求被拒,唔會幫你截短。

除咗用現成圖庫聲線,仲可以用 design 模式輸入性別同年齡兩個條件,生成一把切合需求嘅聲線,再加情緒設定或者自由指示調節演繹方式。留意 design 生成係逐次請求計,唔會儲存成固定資產,每次都要重新生成;想長期用同一把聲,圖庫聲線加識別碼先係穩陣做法。

輪詢任務同下載音頻

任務狀態會行 queued → processing → completed 三步,用 GET /v1/audio/jobs/{id} 查詢;completed 之後回應先會有 audio_url。

import time

def wait_audio(job_id, max_polls=60, interval=3):
    url = BASE + "/v1/audio/jobs/" + job_id
    for _ in range(max_polls):
        job = requests.get(url, headers=HEADERS, timeout=30).json()
        if job["status"] == "completed":
            return job["audio_url"]
        if job["status"] in ("failed", "cancelled"):
            raise RuntimeError("任務未成功:" + job["status"])
        time.sleep(interval)
    raise TimeoutError("輪詢超時")

輪詢上限都要諗埋:一段 500 字符嘅稿,一般幾十秒內完成,但尖鋒時段會慢啲。建議 max_polls 設 60 次、每次隔 3 秒,即三分鐘上限;超時就記錄 job id 之後退場,等下一輪排程再查,唔好無了期等死個 process。

拿到 audio_url 之後,直接用 requests.get 下載就得——連結本身已經預簽,下載唔使再帶授權 header。時效方面要記住兩個數:由生成端直接出嘅連結 7 日內有效,已入音頻庫嘅 1 小時;過期就重新查詢任務攞新連結。另外 queued、processing、failed、cancelled 呢幾個狀態都唔會有 audio_url,程式要寫埋呢啲分支,唔好假定個 field 永遠存在。

輪詢建議兩三秒一次。查詢類請求唔計入限流,所以唔會侵蝕你嘅每分鐘配額,但都冇需要密過半秒;太密除咗冇益,仲會令你自己嘅日誌難睇。

出埋字幕:SRT 一次搞定

做影片配音嘅話,好多時音頻同字幕要一齊交。粵語 TTS 支援喺提交任務時開 SRT 選項,任務完成除咗音頻連結,仲會附上對應嘅字幕檔,等於一個請求出兩樣嘢,條片嘅後期製作慳一大截。

resp = requests.post(
    BASE + "/v1/audio/jobs",
    headers=HEADERS,
    json={
        "text": "第一課:粵語聲調入門。今日我哋由六個聲調講起。",
        "voice": "sum",
        "srt": True,
    },
    timeout=30,
)

兩個位要留意:字幕同樣行異步軌,跟返同一套輪詢流程攞;而同步捷徑係唔支援字幕嘅,硬塞會回 400 srt_not_supported_sync,照行異步就得。字幕時間軸要再微調嘅話,SRT 字幕時間軸對齊教學有批量調整同逐句校準嘅方法。

貼稿準備:書面語定口語?

Python pipeline 好多時食嘅係書面來源——新聞稿、報告、維基文字。呢啲稿直接入語音引擎,讀出嚟會有啲「讀文件」嘅感覺;如果目標係輕鬆嘅節目感,就要先行一步貼稿轉換:將書面詞換做口語詞,長句切短,刪走唔會讀嘅符號。

幾條實用轉換原則:

  • 書面詞換口語詞:「立刻」變「即刻」、「什麼」變「乜嘢」,睇落細,聽感差好遠。
  • 符號要清:項目符號、markdown 標記、連結字串,全部唔應該入語音引擎。
  • 數字寫法:涉及金額、日期嘅重點,可以考慮直接寫做中文字,讀音更可控。
  • 句子長度:口語句子短,一句一句饋入,節奏先似講嘢而唔係誦經。
  • 保留適量標點:頓號、逗號喺廣東話朗讀有天然停頓效果,貼稿嗰陣毋須連標點都剷清,留返先至有節奏。

當然,唔係所有場景都要口語化:正式報告、公告類內容用書面語反而穩重。重點係有意識咁揀,唔係求其貼。兩種寫法嘅取捨,書面語定口語?廣東話 TTS 貼稿轉換全攻略有深入對照。

長文拆段同並行控制

500 字符上限聽落緊,其實夠讀兩分幾鐘。拆段拆得好,成品先流暢:

  • 沿自然邊界切:段落、句子、逗號都係好嘅切割點,唔好喺詞語中間斬開。
  • 每段均勻:目標每段 200 至 400 字符,太短令停頓怪怪哋,太長貼近上限冇緩衝。
  • 並行有上限:在途任務免費 3 個、入門 5 個、專業 10 個、工作室 20 個,超額回 429 in_flight_limit_reached。用佇列或者信號量控制在限額內,完成一件先放下一件。
  • 按序拼合:記低提交順序,下載後按序處理,或者逐段餵俾播放器。

實作上一個簡單做法:先用正則按句號、問號切句,逐句裝入緩衝區,滿到接近 400 字符就封一段;每段一個任務,用簡單嘅工作佇列維持在途數量,完成後按提交次序合併。穩陣嘅開發節奏係先用單線行通全條流程,確認拆段、輪詢、下載都冇問題,先至開並行;並行度一開始設得比上限低一兩格,留位俾重試。

錯誤處理同重試

錯誤碼HTTP點處理
text_too_long400拆段再提交
invalid_or_expired_token401檢查金鑰同環境變數
insufficient_scope403金鑰缺權限,例如聲音複製要另外開
monthly_cap_reached403金鑰月度上限到,調高或者買字符包
rate_limit_exceeded429照 Retry-After 等待再重試
in_flight_limit_reached429等在途任務完成先提交新的
pool_cold503服務未準備好,稍等再試

重試紀律:429 跟 Retry-After 秒數等;其他 5xx 指數退避,設最大重試次數;4xx 直接報錯上拋,重試冇用。建議每次提交都記低 job_id、聲線、字符數同結果,方便事後對配額同排查。每個錯誤碼嘅詳細說明,可以睇TTS API 錯誤碼對照。

批量同定時任務

有成批固定文案(例如幾十條課程句子、幾十段報告摘要)嘅話,用批量:同一個提交入面帶 items 陣列,一次最多 25 項。規則有三條:批量係專業同工作室方案功能,免費同入門提交會回 403 batch_requires_pro 而且零扣費;驗證全有或全無,任何一項無效成批回 400 invalid_items;超過 25 項回 400 too_many_items,分批交。好彩嘅係一次批量只計一次限流,批量本身已經係慳配額嘅手法。

舉個實際排法:每晚十點抓取明日內容清單,逐項驗字數同符號,25 項一批交出去,然後輪詢收貨,下載歸檔,最後發個完成通知去團隊群。成個流程由觸發到收工,人手參與係零。批量流程嘅完整設計,批量生成粵語語音 workflow有由分批到失敗重交嘅全套講解。

成本管理:簡單數學就計到

換算用一條式:每分鐘音頻約 240 字符。所以:

  • 10 分鐘旁白約 2,400 字符(入門約 HK$1.54、專業約 HK$1.35、工作室約 HK$1.18)
  • 5,000 字符約 21 分鐘;300 分鐘嘅長內容大約 72,000 字符
  • 100,000 字符約 417 分鐘,即大約 7 小時音頻

用呢條式,你可以喺立項之前就估算到每月成本:例如每日出一條 5 分鐘簡報,一個月大約 36,000 字符,入門方案都裝得落有餘。冇超額收費呢回事,配額用完就停,加量買字符包:四檔劃一每千字符 HK$0.80,最小 HK$50 有 62,500 字符。金鑰可以設月度字符上限做防爆欄,API 同網頁版共用同一筆配額呢點都要記住。各方案詳細價目同單價,廣東話 TTS 價錢點計逐項拆過。

常見問題 FAQ

要裝邊啲套件?

一個 requests 就夠。金鑰管理想乾淨啲可以加 python-dotenv。唔需要任何官方 SDK,純 REST 直接行。

500 字符係咪好唔夠用?

單次上限 500 字符約等於兩分鐘朗讀。成篇稿用拆段策略處理:沿標點切句、每段 200 至 400 字符、佇列控制在途上限、按序拼合,幾千字文章都應付到。

免費可以玩到幾盡?

每月 5,000 字符(約 21 分鐘音頻);免費同入門方案另可開沙盒金鑰,每日 20 個生成提交,輪詢同下載唔計數,開發調試夠用有餘。

SRT 字幕點攞?

提交任務時開 SRT 選項,任務完成就會有字幕檔,同樣行異步軌。同步捷徑唔支援字幕,硬嚟會回 srt_not_supported_sync。

邊個方案先有全速 API?

全速 API 係專業同工作室專屬;免費同入門用沙盒金鑰(每日 20 個生成提交)試接,升級專業後原有金鑰即時自動轉全速。

在途上限爆咗點算?

收到 429 in_flight_limit_reached 就等現有任務完成先再提交。最好係程式化管理:用佇列維持在途數量喺方案上限之下(免費 3、入門 5、專業 10、工作室 20),唔好靠撞。

圖庫聲線同設計聲線有咩分別?

圖庫聲線用英文識別碼指定,穩定而且可以長期重用;設計聲線靠性別同年齡條件逐次生成,唔會儲存做資產。要品牌聲音一致性,用圖庫聲線先至穩陣。

網頁版同 API 嘅額度係咪分開計?

唔係,兩邊共用同一筆月度配額。有人喺網頁版試聲生成,API 嗰邊嘅餘額就會同步減,做用量規劃嗰陣要當一盤數計。

聲線點揀點指定?

用 GET /v1/voices 攞目錄同試聽,揀定之後喺請求填英文識別碼(例如 sum 代表心妍)。識別碼係穩定標記,中文名只係介面顯示;建議攞真實文案逐把試讀先至寫死。

[!CTA]

用 Python 出第一段廣東話旁白

開個免費帳戶,開戶每月 5,000 字符足夠你由提交行到下載,順便試埋 SRT 字幕。

相關文章