HK0712 commited on
Commit
414b4aa
·
1 Parent(s): 211b028

FIX: Implement robust file path handling for compatibility

Browse files
Files changed (1) hide show
  1. main.py +60 -98
main.py CHANGED
@@ -1,127 +1,89 @@
1
- # main.py (Final Corrected Version)
2
 
3
- import uvicorn
4
- from fastapi import FastAPI, File, UploadFile, Form, HTTPException
5
- from fastapi.responses import JSONResponse
6
  import os
 
 
7
  import shutil
8
- from contextlib import asynccontextmanager
9
- import asyncio
10
- import importlib.util
11
- import sys
12
- from datetime import datetime # The required import statement
13
 
14
- # Ngrok is optional, so we handle its potential absence
15
- try:
16
- from pyngrok import ngrok, conf
17
- PYNGROK_INSTALLED = True
18
- except ImportError:
19
- PYNGROK_INSTALLED = False
20
 
21
- # --- Analyzer Loading Logic ---
22
- ANALYZER_MODULES = {}
23
- SUPPORTED_LANGUAGES = ["en_us"]
 
 
 
 
 
 
24
 
25
- async def load_analyzers():
26
- print("正在預載入所有支援的分析器模型...")
27
- for lang in SUPPORTED_LANGUAGES:
28
- try:
29
- module_name = f"analyzer.ASR_{lang}"
30
- spec = importlib.util.find_spec(module_name)
31
- if spec is None:
32
- print(f"警告:找不到 {lang} 的分析器模組: {module_name}")
33
- continue
34
-
35
- analyzer_module = importlib.util.module_from_spec(spec)
36
- sys.modules[module_name] = analyzer_module
37
- spec.loader.exec_module(analyzer_module)
38
-
39
- if hasattr(analyzer_module, 'load_model'):
40
- await asyncio.to_thread(analyzer_module.load_model)
41
- ANALYZER_MODULES[lang] = analyzer_module
42
- print(f"'{lang}' 分析器載入成功。")
43
- else:
44
- print(f"警告:'{lang}' 模組中沒有找到 load_model 函數。")
45
- except Exception as e:
46
- print(f"錯誤:載入 '{lang}' 分析器時失敗: {e}")
47
 
48
- # --- FastAPI Lifespan ---
49
- @asynccontextmanager
50
- async def lifespan(app: FastAPI):
51
- print("應用程式啟動中...")
52
- await load_analyzers()
53
-
54
- if PYNGROK_INSTALLED:
55
- NGROK_AUTHTOKEN = os.environ.get("NGROK_AUTHTOKEN")
56
- if NGROK_AUTHTOKEN:
57
- conf.get_default().auth_token = NGROK_AUTHTOKEN
58
- print("正在啟動 ngrok 通道...")
59
- public_url = await asyncio.to_thread(ngrok.connect, 8000, name="pronunciation-api")
60
- print(f"Ngrok 通道已建立,公開 URL: {public_url}")
61
- else:
62
- print("警告:未設定 NGROK_AUTHTOKEN,Ngrok 將不會啟動。")
63
- else:
64
- print("警告: pyngrok 套件未安裝,Ngrok 將不會啟動。")
65
 
66
- yield
 
 
67
 
68
- print("應用程式關閉中...")
69
- if PYNGROK_INSTALLED and ngrok.get_tunnels():
70
- ngrok.disconnect()
71
- print("Ngrok 通道已關閉。")
72
-
73
- # --- FastAPI App Initialization ---
74
- app = FastAPI(lifespan=lifespan)
75
- TEMP_DIR = "temp_audio"
76
- os.makedirs(TEMP_DIR, exist_ok=True)
 
 
 
 
 
 
 
77
 
78
- # --- API Endpoint ---
79
- @app.post("/api/v1/recognize")
80
  async def recognize_speech_api(
81
- language: str = Form(...),
82
  target_sentence: str = Form(...),
83
- file: UploadFile = File(...)
84
  ):
85
- if language not in ANALYZER_MODULES:
86
- raise HTTPException(status_code=400, detail=f"不支援的語言: '{language}'。支援的語言: {list(ANALYZER_MODULES.keys())}")
87
-
88
- if not file.filename or not file.filename.lower().endswith('.wav'):
89
- raise HTTPException(status_code=400, detail="檔案格式錯誤或檔名無效,請上傳 .wav 檔案。")
90
-
91
- safe_filename = os.path.basename(file.filename)
92
- temp_file_path = os.path.join(TEMP_DIR, f"{datetime.now().strftime('%Y%m%d%H%M%S')}-{safe_filename}")
93
 
 
 
94
  try:
95
  with open(temp_file_path, "wb") as buffer:
96
  shutil.copyfileobj(file.file, buffer)
97
-
98
- analyzer_module = ANALYZER_MODULES[language]
99
- print(f"使用 '{language}' 分析器處理檔案: {file.filename}")
100
 
101
- analysis_result = await asyncio.to_thread(
102
- analyzer_module.analyze, temp_file_path, target_sentence
103
- )
104
-
105
- return JSONResponse(content=analysis_result)
106
  except Exception as e:
107
  print(f"處理請求時發生未預期的錯誤: {e}")
108
- raise HTTPException(status_code=500, detail=f"伺服器內部錯誤: {str(e)}")
109
  finally:
110
  if os.path.exists(temp_file_path):
111
  os.remove(temp_file_path)
112
- if file:
113
- await file.close()
114
 
115
- @app.get("/")
116
- def read_root():
117
- return {"message": "發音分析 API 已啟動。請使用 POST /api/v1/recognize 端點。"}
118
 
119
- # --- Server Execution ---
120
  if __name__ == "__main__":
121
  print("="*60)
122
- if PYNGROK_INSTALLED:
123
- print("請確保已設定 NGROK_AUTHTOKEN 環境變數以便 ngrok 正常運作。")
124
- else:
125
- print("pyngrok 未安裝,服務僅在本地運行。")
126
  print("="*60)
127
  uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
 
1
+ # main.py (Final, Typo-Fixed Version)
2
 
 
 
 
3
  import os
4
+ import importlib
5
+ import uvicorn
6
  import shutil
7
+ from datetime import datetime
8
+ from fastapi import FastAPI, File, UploadFile, Form, HTTPException, APIRouter # 確保 APIRouter 被正確匯入
9
+ from fastapi.middleware.cors import CORSMiddleware
 
 
10
 
11
+ # --- 應用程式設定 ---
12
+ app = FastAPI(title="Pronunciation Analysis API")
13
+ # 【【【【【 拼 寫 修 正 在 這 裡 】】】】】
14
+ api_router = APIRouter(prefix="/api/v1") # 將 APouter 改為 APIRouter
 
 
15
 
16
+ # --- CORS 設定 (保持不變) ---
17
+ origins = ["*"]
18
+ app.add_middleware(
19
+ CORSMiddleware,
20
+ allow_origins=origins,
21
+ allow_credentials=True,
22
+ allow_methods=["*"],
23
+ allow_headers=["*"],
24
+ )
25
 
26
+ # --- 全域變數和初始化邏輯 (保持不變) ---
27
+ TEMP_DIR = "./temp_audio"
28
+ ANALYZERS = {}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
+ if not os.path.exists(TEMP_DIR):
31
+ os.makedirs(TEMP_DIR)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
+ def get_analyzer_module(language: str):
34
+ if language in ANALYZERS:
35
+ return ANALYZERS[language]
36
 
37
+ try:
38
+ print(f"首次請求 '{language}',正在動態載入模組...")
39
+ analyzer_module = importlib.import_module(f"analyzer.ASR_{language}")
40
+
41
+ print(f"正在呼叫 analyzer.ASR_{language}.load_model()...")
42
+ analyzer_module.load_model()
43
+
44
+ ANALYZERS[language] = analyzer_module
45
+ print(f"'{language}' 分析器模組載入成功並快取。")
46
+ return analyzer_module
47
+ except ImportError:
48
+ print(f"錯誤:找不到 '{language}' 的分析器模組 (analyzer.ASR_{language}.py)。")
49
+ raise HTTPException(status_code=400, detail=f"不支援的語言: {language}")
50
+ except Exception as e:
51
+ print(f"錯誤:載入語言 '{language}' 的模型時發生嚴重錯誤: {e}")
52
+ raise HTTPException(status_code=500, detail=f"載入語言 '{language}' 的模型失敗。")
53
 
54
+ # --- API 端點 (保持不變) ---
55
+ @api_router.post("/recognize")
56
  async def recognize_speech_api(
57
+ file: UploadFile = File(...),
58
  target_sentence: str = Form(...),
59
+ language: str = Form(...)
60
  ):
61
+ analyzer_module = get_analyzer_module(language)
62
+
63
+ base_filename = os.path.basename(file.filename)
64
+ temp_file_path = os.path.join(TEMP_DIR, f"{datetime.now().strftime('%Y%m%d%H%M%S')}-{base_filename}")
 
 
 
 
65
 
66
+ print(f"使用 '{language}' 分析器處理檔案: {temp_file_path}")
67
+
68
  try:
69
  with open(temp_file_path, "wb") as buffer:
70
  shutil.copyfileobj(file.file, buffer)
 
 
 
71
 
72
+ result = analyzer_module.analyze(temp_file_path, target_sentence)
73
+ return result
 
 
 
74
  except Exception as e:
75
  print(f"處理請求時發生未預期的錯誤: {e}")
76
+ raise HTTPException(status_code=500, detail=str(e))
77
  finally:
78
  if os.path.exists(temp_file_path):
79
  os.remove(temp_file_path)
 
 
80
 
81
+ app.include_router(api_router)
 
 
82
 
83
+ # --- 主程式入口 (保持不變) ---
84
  if __name__ == "__main__":
85
  print("="*60)
86
+ print("啟動 FastAPI 伺服器 (http://localhost:8000 )...")
87
+ print("請手動運行 ngrok: ngrok http 8000" )
 
 
88
  print("="*60)
89
  uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)