Python使用OpenAI API文字轉語音(Text To Speech, TTS) : from openai import OpenAI ; client = OpenAI(api_key = api_key) ; response = client .audio .speech .create( model= “tts-1-hd”, input= text_content, response_format= “mp3”)

加入好友
加入社群
Python使用OpenAI API文字轉語音(Text To Speech, TTS) : from openai import OpenAI ; client = OpenAI(api_key = api_key) ; response = client .audio .speech .create( model= "tts-1-hd", input= text_content, response_format= "mp3") - 儲蓄保險王

mailer.txt的內容:
《貓頭鷹郵差與最後一封信》
在一座寧靜的森林裡,住著一隻年紀很大的貓頭鷹,大家都叫牠「歐里伯爺爺」。他不是一般的貓頭鷹,而是一位非常敬業的森林郵差。每天清晨,他都會準時展開翅膀,把信送到狐狸奶奶、小熊一家、刺蝟老師那裡。即使下雨或起霧,他也從不缺席。

森林裡的動物們都非常喜歡他送信時溫暖的笑容與溫柔的問候,有時信封裡還會夾一朵小花或一片秋天的紅葉。他的信不只傳遞消息,更傳遞了溫度。

但隨著年紀越來越大,歐里伯的飛行速度也慢了下來。終於有一天,他決定退休,讓年輕的白鴿小雪接手工作。

「我要送出最後一封信,再安心退休。」他拍拍翅膀,笑著對大家說。

那是一封沒有署名的信,信封是粉紅色的,上面只寫了一個名字:「小松鼠可可」。

「這孩子搬家好幾次,我得想辦法找到她,這封信不能遲到。」歐里伯想。

他飛過溪流、穿過老橡樹林、越過大霧山谷,一路打聽著小松鼠可可的下落。途中,他遇見了搬著堅果的小老鼠,摘蘋果的野兔,還有躲雨的山羊,每個人都幫他出了一點力。

終於,在一棵長滿松果的大樹下,他找到了可可。

「歐里伯爺爺!」可可開心地撲到他身上,「我以為你退休了!」

「還沒呢,這封信,是你媽媽留給你的,她半年前搬到另一片森林前託我交給你。」

可可小心地打開信,裡面寫著:

「親愛的可可,
雖然媽媽現在不在你身邊,但我一直都以你為榮。希望你每天都勇敢、快樂,記得幫助別人,因為你擁有一顆溫暖的心。
愛你的媽媽。」

讀著讀著,小松鼠的眼眶紅了。她緊緊抱著信,也抱著歐里伯。

「謝謝你,爺爺。」

那一刻,歐里伯感覺整顆心都亮了起來。他知道自己這一生最重要的事,就是把這封信送到小可可手中。

從那天起,小松鼠可可也開始幫忙做一些送信的小差事。她學著像歐里伯一樣,笑著和大家說早安,把祝福帶給每一位朋友。

森林裡的郵差換人了,但溫暖和善意,依然在森林裡飛翔著。

code:

import os
import json
from openai import OpenAI
from pathlib import Path
import time
text_file="mailer.txt"
def openai_text_to_speech(text_file=text_file, output_file=f"{os.path.splitext(text_file)[0]}.mp3"):
    """
    使用 OpenAI TTS API 將文字轉換為語
    
    優勢:
    - 最高品質的語音合成
    - 多種語音選擇
    - 支援多語言
    - 語音自然度極佳
    """
    
    try:
        # 讀取 API Key
        with open(r"D:\user\Python\GPT\json\api_key.json", "r") as f:
            api_key = json.load(f)["api_key"]
        
        # 初始化 OpenAI 客戶端
        client = OpenAI(api_key=api_key)
        
        # 讀取文字內容
        if not os.path.exists(text_file):
            # 建立故事文字檔
            story_text = """《貓頭鷹郵差與最後一封信
在一座寧靜的森林裡住著一隻年紀很大的貓頭鷹大家都叫牠歐里伯爺爺」。他不是一般的貓頭鷹而是一位非常敬業的森林郵差每天清晨他都會準時展開翅膀把信送到狐狸奶奶小熊一家刺蝟老師那裡即使下雨或起霧他也從不缺席

森林裡的動物們都非常喜歡他送信時溫暖的笑容與溫柔的問候有時信封裡還會夾一朵小花或一片秋天的紅葉他的信不只傳遞消息更傳遞了溫度

但隨著年紀越來越大歐里伯的飛行速度也慢了下來終於有一天他決定退休讓年輕的白鴿小雪接手工作

我要送出最後一封信再安心退休。」他拍拍翅膀笑著對大家說

那是一封沒有署名的信信封是粉紅色的上面只寫了一個名字:「小松鼠可可」。

這孩子搬家好幾次我得想辦法找到她這封信不能遲到。」歐里伯想

他飛過溪流穿過老橡樹林越過大霧山谷一路打聽著小松鼠可可的下落途中他遇見了搬著堅果的小老鼠摘蘋果的野兔還有躲雨的山羊每個人都幫他出了一點力

終於在一棵長滿松果的大樹下他找到了可可

歐里伯爺爺!」可可開心地撲到他身上,「我以為你退休了!」

還沒呢這封信是你媽媽留給你的她半年前搬到另一片森林前託我交給你。」

可可小心地打開信裡面寫著

親愛的可可
雖然媽媽現在不在你身邊但我一直都以你為榮希望你每天都勇敢快樂記得幫助別人因為你擁有一顆溫暖的心
愛你的媽媽。」

讀著讀著小松鼠的眼眶紅了她緊緊抱著信也抱著歐里伯

謝謝你爺爺。」

那一刻歐里伯感覺整顆心都亮了起來他知道自己這一生最重要的事就是把這封信送到小可可手中

從那天起小松鼠可可也開始幫忙做一些送信的小差事她學著像歐里伯一樣笑著和大家說早安把祝福帶給每一位朋友

森林裡的郵差換人了但溫暖和善意依然在森林裡飛翔著"""
            
            with open(text_file, "w", encoding="utf-8") as f:
                f.write(story_text)
            print(f"✅ 已建立文字檔: {text_file}")
        
        with open(text_file, "r", encoding="utf-8") as f:
            text_content = f.read()
        
        print(f"📖 讀取檔案: {text_file}")
        print(f"📝 文字長度: {len(text_content)} 字元")
        
        # OpenAI TTS 語音選項
        voices = {
            "1": "alloy",    # 中性平衡
            "2": "echo",     # 男性深沉
            "3": "fable",    # 英式優雅
            "4": "onyx",     # 男性深沉
            "5": "nova",     # 女性年輕
            "6": "shimmer"   # 女性溫暖
        }
        
        print("🎤 可用語音:")
        for key, voice in voices.items():
            print(f"  {key}. {voice}")
        
        voice_choice = input("選擇語音 (1-6, 預設為 alloy): ") or "1"
        selected_voice = voices.get(voice_choice, "alloy")
        
        print(f"🎵 使用語音: {selected_voice}")
        print("🔄 正在生成語音...")
        
        start_time = time.time()
        
        # 呼叫 OpenAI TTS API
        response = client.audio.speech.create(
            model="tts-1-hd",  # 使用高品質模型 (tts-1 為標準模型)
            voice=selected_voice,
            input=text_content,
            response_format="mp3"  # 可選: mp3, opus, aac, flac
        )
        
        # 儲存音檔
        response.stream_to_file(output_file)
        
        end_time = time.time()
        process_time = end_time - start_time
        
        print(f"✅ 語音檔案已生成: {output_file}")
        print(f"⏱️  處理時間: {process_time:.2f} 秒")
        
        # 顯示檔案資訊
        file_size = os.path.getsize(output_file) / (1024 * 1024)
        print(f"📁 檔案大小: {file_size:.2f} MB")
        
        # 計算成本 (估算)
        char_count = len(text_content)
        estimated_cost = char_count * 0.000015  # $0.015 per 1K characters
        print(f"💰 預估費用: ${estimated_cost:.4f} USD")
        
        return True
        
    except Exception as e:
        print(f"❌ 生成失敗: {e}")
        return False

def test_voice_samples():
    """測試不同語音樣本"""
    test_text = "你好,這是語音測試。歡迎來到我們的 AI 工作坊。"
    
    with open(r"D:\user\Python\GPT\json\api_key.json", "r") as f:
        api_key = json.load(f)["api_key"]
    
    client = OpenAI(api_key=api_key)
    
    voices = ["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
    
    print("🎤 生成語音樣本...")
    
    for voice in voices:
        try:
            response = client.audio.speech.create(
                model="tts-1",
                voice=voice,
                input=test_text
            )
            
            sample_file = f"sample_{voice}.mp3"
            response.stream_to_file(sample_file)
            print(f"✅ {voice}: {sample_file}")
            
        except Exception as e:
            print(f"❌ {voice} 失敗: {e}")

if __name__ == "__main__":
    print("🎙️ OpenAI TTS 語音合成")
    print("=" * 50)
    
    # 詢問是否要測試語音樣本
    test_samples = input("🎵 是否先生成語音樣本?(y/n): ")
    if test_samples.lower() == 'y':
        test_voice_samples()
        print()
    
    # 生成完整故事語音
    success = openai_text_to_speech()
    
    if success:
        print("🎉 OpenAI TTS 轉換完成!")
        print(f"🎧 現在可以播放 {os.path.splitext(text_file)[0]}.mp3")

code:

Python使用OpenAI API文字轉語音(Text To Speech, TTS) : from openai import OpenAI ; client = OpenAI(api_key = api_key) ; response = client .audio .speech .create( model= "tts-1-hd", input= text_content, response_format= "mp3") - 儲蓄保險王

📖 程式碼詳解

1. 匯入套件

import os          # 檔案系統操作
import json        # JSON 檔案處理
from openai import OpenAI    # OpenAI 客戶端
from pathlib import Path     # 路徑處理
import time        # 時間計算

2. 函數定義與參數

text_file="mailer.txt"  # 預設輸入檔案
def openai_text_to_speech(
    text_file=text_file, 
    output_file=f"{os.path.splitext(text_file)[0]}.mp3"
):

參數說明:

  • text_file: 輸入的文字檔案名稱
  • output_file: 輸出的 MP3 檔案名稱(自動從文字檔名生成)

3. API Key 讀取

# 讀取 API Key
with open(r"D:\user\Python\GPT\json\api_key.json", "r") as f:
    api_key = json.load(f)["api_key"]

# 初始化 OpenAI 客戶端
client = OpenAI(api_key=api_key)

重要提醒:

  • 請修改路徑為你的實際 API Key 檔案路徑
  • 確保檔案格式為 UTF-8 編碼

4. 文字檔案處理

# 檢查檔案是否存在
if not os.path.exists(text_file):
    # 如果不存在建立預設故事文字檔
    story_text = """故事內容..."""
    
    with open(text_file, "w", encoding="utf-8") as f:
        f.write(story_text)
    print(f"✅ 已建立文字檔: {text_file}")

# 讀取文字內容
with open(text_file, "r", encoding="utf-8") as f:
    text_content = f.read()

編碼重點:

  • 使用 encoding="utf-8" 確保中文字元正確處理
  • 自動建立預設文字檔案,方便測試

5. 語音選擇系統

# OpenAI TTS 語音選項
voices = {
    "1": "alloy",    # 中性、平衡
    "2": "echo",     # 男性、深沉
    "3": "fable",    # 英式、優雅
    "4": "onyx",     # 男性、深沉
    "5": "nova",     # 女性、年輕
    "6": "shimmer"   # 女性溫暖
}

# 使用者選擇
voice_choice = input("選擇語音 (1-6, 預設為 alloy): ") or "1"
selected_voice = voices.get(voice_choice, "alloy")

voice_choice = input(“選擇語音 (1-6, 預設為 alloy): “) or “1”

🧠 運作邏輯

  1. input() 執行 → 使用者輸入或按 Enter(獲得空字串,視為False)
  2. 真值判斷 → Python 檢查輸入值是否為「真」
  3. or 運算 → 如果左邊為「假」,返回右邊的值

語音特色:

  • alloy: 平衡中性,適合多數用途
  • echo: 男性聲音,適合正式內容
  • nova: 女性聲音,適合親切內容
  • shimmer: 溫暖女聲,適合故事朗讀

6. OpenAI TTS API 調用

# 計時開始
start_time = time.time()

# 呼叫 OpenAI TTS API
response = client.audio.speech.create(
    model="tts-1-hd",        # 高品質模型
    voice=selected_voice,    # 選擇的語音
    input=text_content,      # 輸入文字
    response_format="mp3"    # 輸出格式
)

# 儲存音檔
response.stream_to_file(output_file)

# 計時結束
end_time = time.time()

模型選擇:

  • tts-1: 標準模型,較快且便宜
  • tts-1-hd: 高品質模型,音質更佳但較貴

輸出格式選項:

  • mp3: 最常用,檔案小
  • opus: 適合即時應用
  • aac: Apple 生態系統
  • flac: 無損音質質
  • 7. 結果報告
# 處理時間
process_time = end_time - start_time
print(f"⏱️  處理時間: {process_time:.2f} 秒")

# 檔案大小
file_size = os.path.getsize(output_file) / (1024 * 1024)
print(f"📁 檔案大小: {file_size:.2f} MB")

# 費用估算
char_count = len(text_content)
estimated_cost = char_count * 0.000015  # $0.015 per 1K characters
print(f"💰 預估費用: ${estimated_cost:.4f} USD")

輸出的mp3檔:

Python使用OpenAI API文字轉語音(Text To Speech, TTS) : from openai import OpenAI ; client = OpenAI(api_key = api_key) ; response = client .audio .speech .create( model= "tts-1-hd", input= text_content, response_format= "mp3") - 儲蓄保險王

推薦hahow線上學習python: https://igrape.net/30afN

Google Text-to-Speech (gTTS)

簡介

  • 一款基於 Google Translate 的開源 Python 庫,支持多語言文字轉語音。
  • 非常輕量、易用,適合快速生成語音文件。

特點

  • 支持語言:100+ 種語言,包括中文。
  • 免費:僅需網路連線即可使用。
  • 輸出格式:生成 .mp3 文件。

安裝

pip install gtts

使用範例

from gtts import gTTS

text = "你好,歡迎使用文字轉語音工具!"
tts = gTTS(text, lang='zh')
tts.save("output.mp3")

優勢

  • 簡單易用,快速生成語音文件。
  • 無需本地計算資源,適合低性能設備。

限制

  • 需要穩定的網路連線。
  • 語音自然度稍低,適合基礎 TTS 需求。

推薦hahow線上學習python: https://igrape.net/30afN

Edge-TTS(推薦)

  • Microsoft Edge 瀏覽器的 TTS
  • Python 套件:edge-tts
  • 音質優秀,完全免費
  • 支援 SSML 標記
# 安裝pip install edge-tts
import edge_tts
import asyncio

async def main():
    text = "你好,這是測試"
    voice = "zh-TW-HsiaoChenNeural"
    
    communicate = edge_tts.Communicate(text, voice)
    await communicate.save("output.mp3")

asyncio.run(main())

程式碼詳細解釋:

1. 安裝套件

# 安裝pip install edge-tts
  • 這是在終端機/命令提示字元中執行的指令
  • 安裝 Microsoft Edge 瀏覽器的 TTS 引擎 Python 套件

2. 導入必要模組

import edge_tts    # Edge TTS 主要功能
import asyncio     # Python 的非同步程式設計模組

3. 非同步函數定義

async def main():
  • async def 定義一個非同步函數
  • 非同步函數可以使用 await 關鍵字
  • 必須在特殊環境(event loop)中執行

4. 設定參數

text = "你好,這是測試"                # 要轉換的文字
voice = "zh-TW-HsiaoChenNeural"      # 語音角色台灣女聲

5. 建立通訊物件

communicate = edge_tts.Communicate(text, voice)
  • 創建一個 Communicate 物件
  • 負責與 Edge TTS 服務通訊

6. 儲存音檔

await communicate.save("output.mp3")
  • await 等待非同步操作完成
  • 將語音儲存為 output.mp3

7. 執行主程式

asyncio.run(main())
  • 創建新的 event loop 並執行 main()
  • 這裡是問題所在!

為什麼會出錯?

Event Loop 概念圖解:

正常 Python 環境
┌─────────────────┐
Python Script
│                 │
asyncio.run() ──┼──> 創建新 Event Loop
│                 │
└─────────────────┘

Jupyter/IPython 環境
┌─────────────────────┐
Jupyter Notebook
│                     │
已有 Event Loop 運行<── 這裡已經有了
│                     │
asyncio.run() ──────┼──> 試圖創建新 Loop ✗ (錯誤!)
│                     │
└─────────────────────┘

什麼是 Event Loop?

想像一個餐廳:

  • 同步程式 = 一個服務生,一次只服務一桌
  • 非同步程式 = 一個服務生,同時處理多桌
  • Event Loop = 服務生的工作流程管理系統
# 同步方式傳統
def 點餐():
    顧客A點餐()  #  A 點完
    顧客B點餐()  # 再等 B 點完
    顧客C點餐()  # 最後等 C

# 非同步方式edge-tts 使用
async def 點餐():
    await 顧客A點餐()  # A 在想的時候
    await 顧客B點餐()  # 可以先問 B
    await 顧客C點餐()  # 也可以處理 C

正確的使用方式:

選項 1:純 Python 腳本(原始寫法正確)

# script.py
import edge_tts
import asyncio

async def main():
    text = "你好,這是測試"
    voice = "zh-TW-HsiaoChenNeural"
    
    communicate = edge_tts.Communicate(text, voice)
    await communicate.save("output.mp3")
    print("語音檔案已生成:output.mp3")

# 在終端機執行python script.py
if __name__ == "__main__":
    asyncio.run(main())  # ✓ 這裡正確

選項 2:Jupyter Notebook 中使用

#  Jupyter cell 
import edge_tts

text = "你好,這是測試"
voice = "zh-TW-HsiaoChenNeural"

communicate = edge_tts.Communicate(text, voice)
await communicate.save("output.mp3")  # 直接 await不用 asyncio.run()

選項 3:通用解決方案

import edge_tts
import asyncio
import nest_asyncio

# 允許巢狀 event loop
nest_asyncio.apply()

async def text_to_speech(text, filename="output.mp3"):
    """
    將文字轉換為語音檔
    
    參數:
        text: 要轉換的文字
        filename: 輸出檔案名稱
    """
    voice = "zh-TW-HsiaoChenNeural"
    
    print(f"正在生成語音:{text[:20]}...")
    communicate = edge_tts.Communicate(text, voice)
    await communicate.save(filename)
    print(f"完成!檔案儲存為:{filename}")

# 這樣在任何環境都能用
asyncio.run(text_to_speech("歡迎使用語音合成系統"))

簡單類比解釋:

同步 vs 非同步

同步(傳統方式):

下載檔案A (等3秒) ━━━━━━━━━━
下載檔案B (等2秒)          ━━━━━━
下載檔案C (等1秒)                ━━
總時間:6

非同步(edge-tts方式):

下載檔案A ━━━━━━━━━━
下載檔案B ━━━━━━
下載檔案C ━━
總時間:3同時進行

完整實用範例:

# tts_helper.py
import edge_tts
import asyncio
import os

class SimpleTTS:
    """簡單的 TTS 工具類"""
    
    def __init__(self):
        # 設定預設語音
        self.default_voice = "zh-TW-HsiaoChenNeural"
        
    def create_speech(self, text, output_file="speech.mp3", voice=None):
        """
        同步方法:生成語音檔
        """
        async def _async_create():
            voice_to_use = voice or self.default_voice
            communicate = edge_tts.Communicate(text, voice_to_use)
            await communicate.save(output_file)
        
        # 智慧判斷如何執行
        try:
            # 嘗試取得現有的 event loop
            loop = asyncio.get_running_loop()
            # 如果成功表示在 Jupyter 等環境
            import nest_asyncio
            nest_asyncio.apply()
            loop.run_until_complete(_async_create())
        except RuntimeError:
            # 如果失敗表示在一般 Python 環境
            asyncio.run(_async_create())
        
        print(f"✅ 語音已儲存至:{output_file}")
        return output_file

# 使用方式
tts = SimpleTTS()
tts.create_speech("這是一個測試")
tts.create_speech("Hello World", "english.mp3", "en-US-AriaNeural")

重點整理:

  1. edge-tts 使用非同步設計是為了效能(可同時處理多個請求)
  2. asyncio.run() 會創建新的 event loop
  3. Jupyter 已有 event loop,所以不能再創建
  4. 解決方式
    • 純 Python:直接用原始寫法
    • Jupyter:用 await 不用 asyncio.run()
    • 通用:用 nest_asyncio

推薦hahow線上學習python: https://igrape.net/30afN

加入好友
加入社群
Python使用OpenAI API文字轉語音(Text To Speech, TTS) : from openai import OpenAI ; client = OpenAI(api_key = api_key) ; response = client .audio .speech .create( model= "tts-1-hd", input= text_content, response_format= "mp3") - 儲蓄保險王

儲蓄保險王

儲蓄險是板主最喜愛的儲蓄工具,最喜愛的投資理財工具則是ETF,最喜愛的省錢工具則是信用卡

You may also like...

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *