MichaelChou0806 commited on
Commit
b2e700d
·
verified ·
1 Parent(s): d4a2e9a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -59
app.py CHANGED
@@ -1,17 +1,15 @@
1
  import os
2
  import time
3
  import shutil
4
- import threading
5
  from pydub import AudioSegment
6
  from openai import OpenAI
7
  import gradio as gr
8
- from fastapi import FastAPI, UploadFile, File, Form
9
- import uvicorn
10
 
11
  # ======================================================
12
  # 🔐 設定區
13
  # ======================================================
14
- PASSWORD = os.getenv("APP_PASSWORD", "chou")
15
  MAX_SIZE = 25 * 1024 * 1024
16
  client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
17
 
@@ -27,72 +25,77 @@ def split_audio_if_needed(path):
27
  if size <= MAX_SIZE:
28
  return [path]
29
  audio = AudioSegment.from_file(path)
30
- n = int(size / MAX_SIZE) + 1
31
- chunk_ms = len(audio) / n
32
- parts = []
33
- for i in range(n):
 
 
34
  fn = f"chunk_{i+1}.wav"
35
- audio[int(i * chunk_ms):int((i + 1) * chunk_ms)].export(fn, format="wav")
36
- parts.append(fn)
37
- return parts
38
 
39
  def transcribe_core(path, model="whisper-1"):
40
- if path.lower().endswith(".mp4"):
41
- fixed = path[:-4] + ".m4a"
42
  try:
43
- shutil.copy(path, fixed)
44
- path = fixed
45
  print("🔧 已自動修正 mp4 → m4a")
46
  except Exception as e:
47
  print(f"⚠️ mp4→m4a 轉檔失敗:{e}")
48
 
49
- # Whisper 轉錄
50
  chunks = split_audio_if_needed(path)
51
- txts = []
52
  for f in chunks:
53
  with open(f, "rb") as af:
54
  res = client.audio.transcriptions.create(
55
- model=model, file=af, response_format="text"
 
 
56
  )
57
- txts.append(res)
58
- raw = "\n".join(txts)
59
 
60
- # 簡→繁
61
  conv_prompt = (
62
  "請將以下內容完整轉換為「繁體中文(台灣用語)」:\n"
63
- "規則:1) 僅做簡→繁字形轉換;2) 不要意譯或改寫;3) 不要添加任何前後綴。\n-----\n" + raw
 
64
  )
65
- trad = client.chat.completions.create(
66
  model="gpt-4o-mini",
67
  messages=[
68
- {"role": "system", "content": "你是嚴格的繁體中文轉換器。"},
69
  {"role": "user", "content": conv_prompt}
70
  ],
71
  temperature=0.0,
72
- ).choices[0].message.content.strip()
 
73
 
74
  # 摘要
75
  sum_prompt = (
76
- "請用台灣繁體中文撰寫摘要。若內容資訊多,可條列出重點;"
77
- "若內容簡短,請用一句話概述即可。\n\n" + trad
78
  )
79
- summ = client.chat.completions.create(
80
  model="gpt-4o-mini",
81
  messages=[
82
  {"role": "system", "content": "你是一位精準且嚴格使用台灣繁體中文的摘要助手。"},
83
  {"role": "user", "content": sum_prompt}
84
  ],
85
  temperature=0.2,
86
- ).choices[0].message.content.strip()
87
-
88
- return trad, summ
89
 
90
  # ======================================================
91
  # 💬 Gradio 介面
92
  # ======================================================
93
  def transcribe_with_password(password, file):
94
  if password.strip() != PASSWORD:
95
- return "❌ 密碼錯誤", "", ""
96
  if not file:
97
  return "⚠️ 未選擇檔案", "", ""
98
  text, summary = transcribe_core(file.name)
@@ -109,33 +112,9 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
109
  run.click(transcribe_with_password, [pw, f], [s, t, su])
110
 
111
  # ======================================================
112
- # 🌐 FastAPI for 捷徑
113
- # ======================================================
114
- api_app = FastAPI(title="LINE Transcription API")
115
-
116
- @api_app.post("/api/transcribe")
117
- async def api_transcribe(file: UploadFile = File(...), token: str = Form(...)):
118
- if token != PASSWORD:
119
- return {"error": "Invalid token"}
120
- temp = file.filename
121
- with open(temp, "wb") as f:
122
- f.write(await file.read())
123
- text, summary = transcribe_core(temp)
124
- os.remove(temp)
125
- return {"text": text, "summary": summary}
126
-
127
- @api_app.get("/api/health")
128
- def health():
129
- return {"status": "ok", "time": int(time.time())}
130
-
131
- # ======================================================
132
- # 🚀 啟動設定(Gradio 為主入口,FastAPI 背景執行)
133
  # ======================================================
134
- def run_api():
135
- uvicorn.run(api_app, host="0.0.0.0", port=7861, log_level="info")
136
-
137
- threading.Thread(target=run_api, daemon=True).start()
138
- app = demo # 讓 Hugging Face 正確掛載主頁
139
-
140
  if __name__ == "__main__":
141
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
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 HTTPException
 
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
 
 
25
  if size <= MAX_SIZE:
26
  return [path]
27
  audio = AudioSegment.from_file(path)
28
+ num = int(size / MAX_SIZE) + 1
29
+ chunk_ms = len(audio) / num
30
+ files = []
31
+ for i in range(num):
32
+ start, end = int(i * chunk_ms), int((i + 1) * chunk_ms)
33
+ chunk = audio[start:end]
34
  fn = f"chunk_{i+1}.wav"
35
+ chunk.export(fn, format="wav")
36
+ files.append(fn)
37
+ return files
38
 
39
  def transcribe_core(path, model="whisper-1"):
40
+ if path and path.lower().endswith(".mp4"):
41
+ fixed_path = path[:-4] + ".m4a"
42
  try:
43
+ shutil.copy(path, fixed_path)
44
+ path = fixed_path
45
  print("🔧 已自動修正 mp4 → m4a")
46
  except Exception as e:
47
  print(f"⚠️ mp4→m4a 轉檔失敗:{e}")
48
 
 
49
  chunks = split_audio_if_needed(path)
50
+ raw_parts = []
51
  for f in chunks:
52
  with open(f, "rb") as af:
53
  res = client.audio.transcriptions.create(
54
+ model=model,
55
+ file=af,
56
+ response_format="text"
57
  )
58
+ raw_parts.append(res)
59
+ full_raw = "\n".join(raw_parts)
60
 
61
+ # 簡轉繁
62
  conv_prompt = (
63
  "請將以下內容完整轉換為「繁體中文(台灣用語)」:\n"
64
+ "規則:1) 僅做簡→繁字形轉換;2) 不要意譯或改寫;3) 不要添加任何前後綴。\n"
65
+ "-----\n" + full_raw
66
  )
67
+ trad_resp = client.chat.completions.create(
68
  model="gpt-4o-mini",
69
  messages=[
70
+ {"role": "system", "content": "你是嚴格的繁體中文轉換器,只進行字形轉換。"},
71
  {"role": "user", "content": conv_prompt}
72
  ],
73
  temperature=0.0,
74
+ )
75
+ full_trad = trad_resp.choices[0].message.content.strip()
76
 
77
  # 摘要
78
  sum_prompt = (
79
+ "請用台灣繁體中文撰寫摘要。若內容資訊多,可條列出重點;若內容簡短,請用一句話概述即可。\n\n"
80
+ + full_trad
81
  )
82
+ sum_resp = client.chat.completions.create(
83
  model="gpt-4o-mini",
84
  messages=[
85
  {"role": "system", "content": "你是一位精準且嚴格使用台灣繁體中文的摘要助手。"},
86
  {"role": "user", "content": sum_prompt}
87
  ],
88
  temperature=0.2,
89
+ )
90
+ summ = sum_resp.choices[0].message.content.strip()
91
+ return full_trad, summ
92
 
93
  # ======================================================
94
  # 💬 Gradio 介面
95
  # ======================================================
96
  def transcribe_with_password(password, file):
97
  if password.strip() != PASSWORD:
98
+ raise HTTPException(status_code=403, detail="密碼錯誤 ")
99
  if not file:
100
  return "⚠️ 未選擇檔案", "", ""
101
  text, summary = transcribe_core(file.name)
 
112
  run.click(transcribe_with_password, [pw, f], [s, t, su])
113
 
114
  # ======================================================
115
+ # 🚀 啟動
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  # ======================================================
 
 
 
 
 
 
117
  if __name__ == "__main__":
118
  demo.launch(server_name="0.0.0.0", server_port=7860)
119
+ else:
120
+ demo.launch()