Lowking commited on
Commit
dbdce7b
·
verified ·
1 Parent(s): fc203a3

Update main.py

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