MichaelChou0806 commited on
Commit
bcd946f
·
verified ·
1 Parent(s): 2c881ff

Update app.py

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