Lowking commited on
Commit
265ef70
·
verified ·
1 Parent(s): 337d809

Upload 2 files

Browse files
Files changed (2) hide show
  1. main.py +144 -0
  2. requirements.txt +4 -0
main.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from gradio_client import Client
4
+ import base64
5
+ import os
6
+
7
+ app = FastAPI()
8
+
9
+ app.add_middleware(
10
+ CORSMiddleware,
11
+ allow_origins=["*"],
12
+ allow_methods=["*"],
13
+ allow_headers=["*"],
14
+ )
15
+
16
+ # ==========================================
17
+ # 🔗 連結原語會 AI 實驗室 (16 族雙大腦)
18
+ # ==========================================
19
+ trans_client = Client("https://ai-labs.ilrdf.org.tw/kari-seejiq-tnpusu-ai-hmjil/")
20
+ tts_client = Client("https://ai-labs.ilrdf.org.tw/hnang-kari-ai-asi-sluhay/")
21
+
22
+ # 🛠️ 解析字典檔的小工具
23
+ def parse_dialect(dialect_result):
24
+ if isinstance(dialect_result, dict) and 'value' in dialect_result:
25
+ return dialect_result['value']
26
+ elif isinstance(dialect_result, list):
27
+ return dialect_result[0]
28
+ return dialect_result
29
+
30
+ # ==========================================
31
+ # 📚 功能 A:16 族雙向文字翻譯 (✨ 已升級支援 16 族)
32
+ # ==========================================
33
+ @app.post("/translate")
34
+ async def translate(data: dict):
35
+ source_text = data.get("text")
36
+ direction = data.get("direction", "zh2indigenous") # 改為更通用的命名
37
+ ethnicity = data.get("ethnicity", "太魯閣") # ✨ 關鍵升級:動態接收族別
38
+
39
+ try:
40
+ # 相容舊的 zh2trv 參數,確保原本的右鍵選單不會壞掉
41
+ if direction in ["zh2trv", "zh2indigenous", "中翻族"]:
42
+ # 【中翻族】
43
+ dialect_result = trans_client.predict(ethnicity=ethnicity, api_name="/lambda_1")
44
+ dialect_code = parse_dialect(dialect_result)
45
+
46
+ result = trans_client.predict(
47
+ text=source_text,
48
+ src_lang="zho_Hant",
49
+ tgt_lang=dialect_code,
50
+ api_name="/translate_1"
51
+ )
52
+ else:
53
+ # 【族翻中】
54
+ dialect_result = trans_client.predict(ethnicity=ethnicity, api_name="/lambda")
55
+ dialect_code = parse_dialect(dialect_result)
56
+
57
+ result = trans_client.predict(
58
+ text=source_text,
59
+ src_lang=dialect_code,
60
+ tgt_lang="zho_Hant",
61
+ api_name="/translate"
62
+ )
63
+
64
+ return {"result": result}
65
+
66
+ except Exception as e:
67
+ print(f"❌ {ethnicity} 翻譯發生錯誤: {e}")
68
+ return {"result": f"API 呼叫失敗: {str(e)}"}
69
+
70
+ # ==========================================
71
+ # 📋 功能 B:獲取 16 族配音員名單
72
+ # ==========================================
73
+ @app.post("/get_speakers")
74
+ async def get_speakers(data: dict):
75
+ ethnicity = data.get("ethnicity", "太魯閣")
76
+ try:
77
+ result = tts_client.predict(ethnicity=ethnicity, api_name="/lambda")
78
+ if isinstance(result, dict) and 'choices' in result:
79
+ speakers = [c[0] if isinstance(c, list) else c for c in result['choices']]
80
+ else:
81
+ speakers = result
82
+ return {"speakers": speakers}
83
+ except Exception as e:
84
+ print(f"❌ 獲取名單失敗: {e}")
85
+ return {"error": str(e)}
86
+
87
+ # ==========================================
88
+ # 🎵 功能 C:16 族核心語音合成
89
+ # ==========================================
90
+ @app.post("/synthesize")
91
+ async def synthesize(data: dict):
92
+ text = data.get("text", "")
93
+ ethnicity = data.get("ethnicity", "太魯閣")
94
+ requested_speaker = data.get("speaker", "太魯閣_男聲")
95
+
96
+ if not text:
97
+ raise HTTPException(status_code=400, detail="請提供文字")
98
+
99
+ sanitized_text = text.replace("!", "!").replace("?", "?").replace(",", ",").replace("。", ".")
100
+ sanitized_text = sanitized_text.replace(":", ":").replace("(", "(").replace(")", ")")
101
+
102
+ try:
103
+ print(f"🌍 處理族別:{ethnicity},選定:{requested_speaker}")
104
+
105
+ speaker_choices = tts_client.predict(ethnicity=ethnicity, api_name="/lambda")
106
+ full_list = [c[0] if isinstance(c, list) else c for c in speaker_choices['choices']]
107
+
108
+ if requested_speaker in full_list:
109
+ target_speaker = requested_speaker
110
+ else:
111
+ gender_keyword = "男聲" if "男聲" in requested_speaker else "女聲"
112
+ matches = [s for s in full_list if gender_keyword in s]
113
+ target_speaker = matches[0] if matches else full_list[0]
114
+
115
+ audio_filepath = tts_client.predict(
116
+ ref=target_speaker,
117
+ gen_text_input=sanitized_text[:300],
118
+ api_name="/default_speaker_tts"
119
+ )
120
+
121
+ if not os.path.exists(audio_filepath):
122
+ raise Exception("音檔生成失敗")
123
+
124
+ with open(audio_filepath, "rb") as audio_file:
125
+ encoded_audio = base64.b64encode(audio_file.read()).decode('utf-8')
126
+
127
+ try: os.remove(audio_filepath)
128
+ except: pass
129
+
130
+ return {
131
+ "audio_base64": encoded_audio,
132
+ "mime_type": "audio/wav",
133
+ "speaker_used": target_speaker
134
+ }
135
+
136
+ except Exception as e:
137
+ print(f"❌ 合成錯誤: {e}")
138
+ raise HTTPException(status_code=500, detail=str(e))
139
+
140
+ if __name__ == "__main__":
141
+ import uvicorn
142
+ port = int(os.environ.get("PORT", 8000))
143
+ print(f"🎬 正在啟動 16 族全能超級大腦 (Port {port})...")
144
+ uvicorn.run(app, host="0.0.0.0", port=port)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ gradio_client
4
+ python-multipart