Lowking's picture
Update main.py
f1d02d3 verified
Raw
History Blame Contribute Delete
5.56 kB
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from gradio_client import Client
import base64
import os
app = FastAPI()
@app.get("/")
async def root():
return {"message": "16 族語 AI 大師雲端大腦正在運行中!請透過 Chrome 套件呼叫 API。"}
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# ==========================================
# 🔗 連結原語會 AI 實驗室 (16 族雙大腦)
# ==========================================
trans_client = Client("https://ai-labs.ilrdf.org.tw/kari-seejiq-tnpusu-ai-hmjil/")
tts_client = Client("https://ai-labs.ilrdf.org.tw/hnang-kari-ai-asi-sluhay/")
# 🛠️ 解析字典檔的小工具
def parse_dialect(dialect_result):
if isinstance(dialect_result, dict) and 'value' in dialect_result:
return dialect_result['value']
elif isinstance(dialect_result, list):
return dialect_result[0]
return dialect_result
# ==========================================
# 📚 功能 A:16 族雙向文字翻譯 (✨ 已升級支援 16 族)
# ==========================================
@app.post("/translate")
async def translate(data: dict):
source_text = data.get("text")
direction = data.get("direction", "zh2indigenous") # 改為更通用的命名
ethnicity = data.get("ethnicity", "太魯閣") # ✨ 關鍵升級:動態接收族別
try:
# 相容舊的 zh2trv 參數,確保原本的右鍵選單不會壞掉
if direction in ["zh2trv", "zh2indigenous", "中翻族"]:
# 【中翻族】
dialect_result = trans_client.predict(ethnicity=ethnicity, api_name="/lambda_1")
dialect_code = parse_dialect(dialect_result)
result = trans_client.predict(
text=source_text,
src_lang="zho_Hant",
tgt_lang=dialect_code,
api_name="/translate_1"
)
else:
# 【族翻中】
dialect_result = trans_client.predict(ethnicity=ethnicity, api_name="/lambda")
dialect_code = parse_dialect(dialect_result)
result = trans_client.predict(
text=source_text,
src_lang=dialect_code,
tgt_lang="zho_Hant",
api_name="/translate"
)
return {"result": result}
except Exception as e:
print(f"❌ {ethnicity} 翻譯發生錯誤: {e}")
return {"result": f"API 呼叫失敗: {str(e)}"}
# ==========================================
# 📋 功能 B:獲取 16 族配音員名單
# ==========================================
@app.post("/get_speakers")
async def get_speakers(data: dict):
ethnicity = data.get("ethnicity", "太魯閣")
try:
result = tts_client.predict(ethnicity=ethnicity, api_name="/lambda")
if isinstance(result, dict) and 'choices' in result:
speakers = [c[0] if isinstance(c, list) else c for c in result['choices']]
else:
speakers = result
return {"speakers": speakers}
except Exception as e:
print(f"❌ 獲取名單失敗: {e}")
return {"error": str(e)}
# ==========================================
# 🎵 功能 C:16 族核心語音合成
# ==========================================
@app.post("/synthesize")
async def synthesize(data: dict):
text = data.get("text", "")
ethnicity = data.get("ethnicity", "太魯閣")
requested_speaker = data.get("speaker", "太魯閣_男聲")
if not text:
raise HTTPException(status_code=400, detail="請提供文字")
sanitized_text = text.replace("!", "!").replace("?", "?").replace(",", ",").replace("。", ".")
sanitized_text = sanitized_text.replace(":", ":").replace("(", "(").replace(")", ")")
try:
print(f"🌍 處理族別:{ethnicity},選定:{requested_speaker}")
speaker_choices = tts_client.predict(ethnicity=ethnicity, api_name="/lambda")
full_list = [c[0] if isinstance(c, list) else c for c in speaker_choices['choices']]
if requested_speaker in full_list:
target_speaker = requested_speaker
else:
gender_keyword = "男聲" if "男聲" in requested_speaker else "女聲"
matches = [s for s in full_list if gender_keyword in s]
target_speaker = matches[0] if matches else full_list[0]
audio_filepath = tts_client.predict(
ref=target_speaker,
gen_text_input=sanitized_text[:300],
api_name="/default_speaker_tts"
)
if not os.path.exists(audio_filepath):
raise Exception("音檔生成失敗")
with open(audio_filepath, "rb") as audio_file:
encoded_audio = base64.b64encode(audio_file.read()).decode('utf-8')
try: os.remove(audio_filepath)
except: pass
return {
"audio_base64": encoded_audio,
"mime_type": "audio/wav",
"speaker_used": target_speaker
}
except Exception as e:
print(f"❌ 合成錯誤: {e}")
raise HTTPException(status_code=500, detail=str(e))
if __name__ == "__main__":
import uvicorn
port = int(os.environ.get("PORT", 8000))
print(f"🎬 正在啟動 16 族全能超級大腦 (Port {port})...")
uvicorn.run(app, host="0.0.0.0", port=port)