iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
AI & Data

雲端情人 - AI 愛系列 第 18

DAY 18|讓 her「聽你說」:語音訊息 → 轉文字 → AI 回覆(FastAPI + LINE SDK + Whisper)

  • 分享至 

  • xImage
  •  

DAY 18|讓 LINE Bot「聽你說」:語音訊息 → 轉文字 → AI 回覆(FastAPI + LINE SDK + Whisper)

今天把主題換成「語音互動」:使用者在 LINE 傳錄音訊息(語音訊息 / AudioMessage),Bot 自動下載音檔 → 語音轉文字(STT,Speech-to-Text) → 把逐字稿丟給對話模型 → 產生回覆。整條鏈做完,Her 就真的會「聽你說」啦。

你會得到什麼
• 支援 LINE 語音訊息(m4a)的一鍵流程
• 兩段式 AI:Whisper 語音轉文字 + 對話模型產生回覆
• 鐵人賽可複用的錯誤保護(即使 AI Key 缺失也能穩定啟動)
• 範例程式片段可直接貼進你現有的 app_fastapi.py

成果示意(文字流程)
1. 使用者在 LINE 傳一段錄音(按住麥克風講話)。
2. Bot 收到 AudioMessage → 下載音檔(m4a)到暫存目錄。
3. 呼叫 STT(OpenAI Whisper 或 Groq Whisper-large-v3)拿到逐字稿。
4. 把逐字稿丟進聊天模型(Groq / OpenAI),回一段暖心的文字。
5. (選配)你也能把文字丟進 TTS 產生語音回傳,但本文先做文字回覆。

必備環境變數

變數 說明
BASE_URL 你的公開網址(Render 主 URL)
CHANNEL_ACCESS_TOKEN LINE Messaging API token
CHANNEL_SECRET LINE Channel Secret
GROQ_API_KEY (選)Groq 金鑰:用於聊天與/或 Whisper
OPENAI_API_KEY (選)OpenAI 金鑰:Whisper 與聊天皆可用

兩家金鑰任選其一即可。沒有就降級為純規則訊息(服務仍會啟動)。

requirements.txt(語音版與你目前相容)

Web & server

fastapi
uvicorn

LINE Bot

line-bot-sdk>=3.0.0

AI model clients

groq
openai

Crawler & utilities

requests
pandas
beautifulsoup4
lxml
html5lib

Optional features

taiwanlottery
yfinance

不強制安裝 pydub / ffmpeg。Whisper API 可直接吃 m4a,上雲端最省事。

關鍵程式片段

把下面三段貼入你的 app_fastapi.py(都與你現有架構相容):

  1. 工具函式:把 LINE 語音抓下來並轉文字

import tempfile
from linebot.models import AudioMessage

def _has(value: str) -> bool:
return bool(value and value.strip())

def stt_transcribe(file_path: str) -> str:
"""
依序嘗試:
1) OpenAI Whisper (audio.transcriptions.create)
2) Groq Whisper-large-v3
任一成功就回逐字稿;都失敗回空字串。
"""
# OpenAI Whisper
if openai_client:
try:
with open(file_path, "rb") as f:
tx = openai_client.audio.transcriptions.create(
model="whisper-1",
file=f,
response_format="text", # 直接回純文字
temperature=0
)
if _has(tx):
return tx.strip()
except Exception as e:
logger.warning(f"OpenAI Whisper 失敗:{e}")

# Groq Whisper-large-v3
if sync_groq_client:
    try:
        # Groq 的 Python SDK 也支援音訊轉錄端點
        with open(file_path, "rb") as f:
            tx = sync_groq_client.audio.transcriptions.create(
                model="whisper-large-v3",
                file=f,
                response_format="text",
                temperature=0
            )
        if _has(tx):
            return tx.strip()
    except Exception as e:
        logger.warning(f"Groq Whisper 失敗:{e}")

return ""
  1. 在訊息處理器裡抓 AudioMessage

在你的 handle_message_async 最前面解析完 event 與 msg_raw 後,加入這段判斷(放在「命令 & 功能觸發」前也行):

---- 處理 LINE 語音訊息 ----

if isinstance(event.message, AudioMessage):
try:
# 下載語音
content = await run_in_threadpool(line_bot_api.get_message_content, event.message.id)
with tempfile.NamedTemporaryFile(suffix=".m4a", delete=False) as tmp:
for chunk in content.iter_content(1024):
if chunk:
tmp.write(chunk)
tmp_path = tmp.name

    # STT
    transcript = await run_in_threadpool(stt_transcribe, tmp_path)
    if not _has(transcript):
        return reply_with_quick_bar(
            reply_token,
            "我有收到你的語音,但現在聽不太清楚(或轉錄服務忙碌)。能再傳一次嗎?🙏"
        )

    # 丟給聊天模型(用你現有的 groq_chat_async)
    sys_prompt = build_persona_prompt(chat_id, await analyze_sentiment(transcript))
    messages = [
        {"role": "system", "content": sys_prompt},
        {"role": "user", "content": f"(以下是使用者語音逐字稿)\n{transcript}"}
    ]
    ai_reply = await groq_chat_async(messages)

    return reply_with_quick_bar(
        reply_token,
        f"🗣️ 你說:\n{transcript}\n\n——\n{ai_reply}"
    )
except Exception as e:
    logger.error(f"處理語音訊息失敗:{e}", exc_info=True)
    return reply_with_quick_bar(reply_token, "我剛剛耳機斷訊了 😅 你可以再試一次音訊嗎?")

這段會把語音逐字稿也一起回給使用者,方便「聽寫確認」。

  1. 安全降級(你已經有):

若 OPENAI_API_KEY / GROQ_API_KEY 缺失,服務依舊啟動、其他功能不受影響。
建議保留我們前一次提供的 環境變數不毀損啟動、/diagz 診斷端點與 get_analysis_reply() 降級邏輯。

本地/雲端測試
1. LINE Developer Console → Messaging API → Webhook → 指到 {BASE_URL}/callback
2. 手機對 Bot 按住麥克風錄一段話
3. 期待 Bot 回覆:
• 第一段:逐字稿(你剛剛說的文字)
• 第二段:AI 回覆(走你設定的人設口吻)

常見錯誤與排除
• Cause of failure could not be determined
多半是匯入期就 raise 導致 Uvicorn沒綁定 $PORT。用我們的「延後檢查+/diagz」能避免。
• InvalidSignatureError
請確認 CHANNEL_SECRET 正確、/callback 路由存在、Render URL 有更新到 LINE 後台。
• 轉錄空白 / 失敗
可能是音檔太短、背景噪音大、API 一時超時。建議回覆「請再說一次」並做重試(上面已加溫和提示)。
• 沒有 ffmpeg
本教學路線直接把 m4a 丟進 API,不需要 ffmpeg;除非你要做離線轉檔。

進階延伸
• 回語音(TTS):把 AI 文字丟到 TTS,輸出 mp3/m4a,使用 LINE 的 AudioSendMessage 回傳。
• 語音指令:以關鍵詞觸發「查股價 / 金價 / 匯率 / 翻譯」。
• 多語辨識:Whisper 支援自動偵測語言;偵測後自動切換回覆語系。
• 長語音摘要:超過 30 秒先做摘要,再追問。

文末小結

今天完成「語音 → 文字 → AI 回覆」的閉環,Her 不只會看文字、也開始聽得懂你。把這套接回你的股票 / 金價 / 匯率模組,用一句話就能查資料,體驗會更貼近真實助理。明天我們可以把TTS 回語音也串上,讓整個對話完全「說話就好」。


上一篇
Day 17 HER會幫我理財看股市小助理: 增加輸入股號的的相容相性—台股 ETF 代碼正規化、金價雙來源回退、新聞 API 防呆
下一篇
Day 19 讓HEE「說給你聽」:文字轉語音 (TTS) + 語音回覆(延伸自語音→文字)
系列文
雲端情人 - AI 愛21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言