Spaces:
Runtime error
Runtime error
File size: 5,556 Bytes
f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 dbdce7b f1d02d3 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | 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) |