MichaelChou0806 commited on
Commit
c313f52
·
verified ·
1 Parent(s): 8fa55d3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -46
app.py CHANGED
@@ -4,26 +4,23 @@ import shutil
4
  from pydub import AudioSegment
5
  from openai import OpenAI
6
  import gradio as gr
7
- from fastapi import FastAPI, File, UploadFile, Form, HTTPException
8
- from fastapi.responses import JSONResponse
9
 
10
- # ======================================================
11
- # 🔐 基本設定(支援 Secrets)
12
- # ======================================================
13
- OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY")
14
- APP_PASSWORD = os.environ.get("APP_PASSWORD")
 
15
 
16
- print("===== 🚀 啟動中 =====")
17
- print(f"OPENAI_API_KEY: {'✅ 已載入' if OPENAI_API_KEY else '❌ 未載入'}")
18
- print(f"APP_PASSWORD: {'✅ 已載入' if APP_PASSWORD else '❌ 未載入'}")
19
- print(APP_PASSWORD)
20
 
21
- client = OpenAI(api_key=OPENAI_API_KEY)
22
- MAX_SIZE = 25 * 1024 * 1024
23
 
24
- # ======================================================
25
- # 🎧 音訊處理核心
26
- # ======================================================
27
  def split_audio_if_needed(path: str):
28
  size = os.path.getsize(path)
29
  if size <= MAX_SIZE:
@@ -38,56 +35,62 @@ def split_audio_if_needed(path: str):
38
  parts.append(fn)
39
  return parts
40
 
41
-
42
  def transcribe_core(path: str, model: str = "whisper-1"):
 
 
 
 
 
 
 
 
 
43
  chunks = split_audio_if_needed(path)
44
  txts = []
45
  for f in chunks:
46
  with open(f, "rb") as af:
47
- t = client.audio.transcriptions.create(model=model, file=af, response_format="text")
 
 
48
  txts.append(t)
49
  full = "\n".join(txts)
50
  summ = client.chat.completions.create(
 
 
 
 
51
  model="gpt-4o-mini",
52
  messages=[{"role": "user", "content": f"請用繁體中文摘要以下內容:\n{full}"}],
53
  temperature=0.4,
54
  ).choices[0].message.content.strip()
55
  return full, summ
56
 
57
- # ======================================================
58
- # 🌐 FastAPI 主要端點
59
- # ======================================================
60
- app = FastAPI(title="LINE Audio Transcriber")
61
-
62
- @app.get("/ping")
63
- def ping():
64
- return {"status": "ok", "key": bool(OPENAI_API_KEY), "pw": bool(APP_PASSWORD)}
65
-
66
  @app.post("/api/transcribe")
67
- async def api_transcribe(
68
- file: UploadFile = File(...),
69
- token: str = Form(default=None)
70
- ):
71
- """捷徑上傳音訊"""
72
- if APP_PASSWORD and token != APP_PASSWORD:
73
- raise HTTPException(status_code=403, detail="Forbidden: invalid token")
74
-
75
  temp = file.filename
76
  with open(temp, "wb") as f:
77
  f.write(await file.read())
78
-
79
  text, summary = transcribe_core(temp)
80
  os.remove(temp)
81
- return JSONResponse({"text": text, "summary": summary})
82
 
83
- # ======================================================
 
 
 
 
 
84
  # 💬 Gradio 介面
85
- # ======================================================
86
  def transcribe_with_pw(password, file):
87
- if APP_PASSWORD and password.strip() != APP_PASSWORD:
88
  return "❌ 密碼錯誤", "", ""
89
  if not file:
90
- return "⚠️ 未上傳音訊", "", ""
91
  text, summary = transcribe_core(file.name)
92
  return "✅ 完成", text, summary
93
 
@@ -99,10 +102,16 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
99
  s = gr.Textbox(label="狀態", interactive=False)
100
  t = gr.Textbox(label="逐字稿", lines=10)
101
  su = gr.Textbox(label="摘要", lines=8)
 
102
  run.click(transcribe_with_pw, [pw, f], [s, t, su])
103
 
104
- # ======================================================
105
- # 🚀 關鍵啟動(讓 HF 正確偵測
106
- # ======================================================
107
- from gradio.routes import mount_gradio_app
108
- application = mount_gradio_app(app, demo, path="/")
 
 
 
 
 
 
4
  from pydub import AudioSegment
5
  from openai import OpenAI
6
  import gradio as gr
7
+ from fastapi import FastAPI, File, UploadFile
 
8
 
9
+ # ========================
10
+ # 🔐 基本設定
11
+ # ========================
12
+ PASSWORD = os.getenv("APP_PASSWORD", "defaultpass")
13
+ MAX_SIZE = 25 * 1024 * 1024
14
+ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
15
 
16
+ print(PASSWORD)
 
 
 
17
 
18
+ # FastAPI App for捷徑 API
19
+ app = FastAPI()
20
 
21
+ # ========================
22
+ # 🎧 音訊轉錄核心
23
+ # ========================
24
  def split_audio_if_needed(path: str):
25
  size = os.path.getsize(path)
26
  if size <= MAX_SIZE:
 
35
  parts.append(fn)
36
  return parts
37
 
 
38
  def transcribe_core(path: str, model: str = "whisper-1"):
39
+ if path.lower().endswith(".mp4"):
40
+ fixed = path[:-4] + ".m4a"
41
+ try:
42
+ shutil.copy(path, fixed)
43
+ path = fixed
44
+ print("🔧 已自動修正 mp4 → m4a")
45
+ except Exception as e:
46
+ print(f"⚠️ mp4→m4a 轉檔失敗:{e}")
47
+
48
  chunks = split_audio_if_needed(path)
49
  txts = []
50
  for f in chunks:
51
  with open(f, "rb") as af:
52
+ t = client.audio.transcriptions.create(
53
+ model=model, file=af, response_format="text"
54
+ )
55
  txts.append(t)
56
  full = "\n".join(txts)
57
  summ = client.chat.completions.create(
58
+
59
+
60
+
61
+
62
  model="gpt-4o-mini",
63
  messages=[{"role": "user", "content": f"請用繁體中文摘要以下內容:\n{full}"}],
64
  temperature=0.4,
65
  ).choices[0].message.content.strip()
66
  return full, summ
67
 
68
+ # ========================
69
+ # 🌐 FastAPI 端點(捷徑用)
70
+ # ========================
 
 
 
 
 
 
71
  @app.post("/api/transcribe")
72
+ async def api_transcribe(file: UploadFile = File(...)):
73
+ """供 iPhone 捷徑上傳音訊並取得 JSON"""
 
 
 
 
 
 
74
  temp = file.filename
75
  with open(temp, "wb") as f:
76
  f.write(await file.read())
 
77
  text, summary = transcribe_core(temp)
78
  os.remove(temp)
79
+ return {"text": text, "summary": summary}
80
 
81
+ @app.get("/health")
82
+ def health():
83
+ """捷徑可先 ping 這個確認服務運作中"""
84
+ return {"status": "ok", "time": int(time.time())}
85
+
86
+ # ========================
87
  # 💬 Gradio 介面
88
+ # ========================
89
  def transcribe_with_pw(password, file):
90
+ if password.strip() != PASSWORD:
91
  return "❌ 密碼錯誤", "", ""
92
  if not file:
93
+ return "⚠️ 未選擇檔案", "", ""
94
  text, summary = transcribe_core(file.name)
95
  return "✅ 完成", text, summary
96
 
 
102
  s = gr.Textbox(label="狀態", interactive=False)
103
  t = gr.Textbox(label="逐字稿", lines=10)
104
  su = gr.Textbox(label="摘要", lines=8)
105
+
106
  run.click(transcribe_with_pw, [pw, f], [s, t, su])
107
 
108
+ # ========================
109
+ # 🚀 啟動(單一埠
110
+ # ========================
111
+ # Gradio 介面掛載到 FastAPI
112
+ gr.mount_gradio_app(app, demo, path="/")
113
+
114
+ # Hugging Face 自動綁定 port=7860,不用手動設定
115
+ if __name__ == "__main__":
116
+ import uvicorn
117
+ uvicorn.run(app, host="0.0.0.0", port=7860)