MichaelChou0806's picture
Update app.py
cf686cb verified
raw
history blame
4.27 kB
import os
import time
import shutil
from pydub import AudioSegment
from openai import OpenAI
import gradio as gr
from fastapi import HTTPException
# ======================================================
# 🔐 設定區
# ======================================================
PASSWORD = os.getenv("APP_PASSWORD", "defaultpass")
MAX_SIZE = 25 * 1024 * 1024
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
print("===== 🚀 啟動中 =====")
print(f"APP_PASSWORD: {'✅ 已載入' if PASSWORD else '❌ 未載入'}")
print(f"目前密碼內容:{PASSWORD}")
# ======================================================
# 🎧 音訊轉錄核心
# ======================================================
def split_audio_if_needed(path):
size = os.path.getsize(path)
if size <= MAX_SIZE:
return [path]
audio = AudioSegment.from_file(path)
num = int(size / MAX_SIZE) + 1
chunk_ms = len(audio) / num
files = []
for i in range(num):
start, end = int(i * chunk_ms), int((i + 1) * chunk_ms)
chunk = audio[start:end]
fn = f"chunk_{i+1}.wav"
chunk.export(fn, format="wav")
files.append(fn)
return files
def transcribe_core(path, model="whisper-1"):
if path and path.lower().endswith(".mp4"):
fixed_path = path[:-4] + ".m4a"
try:
shutil.copy(path, fixed_path)
path = fixed_path
print("🔧 已自動修正 mp4 → m4a")
except Exception as e:
print(f"⚠️ mp4→m4a 轉檔失敗:{e}")
chunks = split_audio_if_needed(path)
raw_parts = []
for f in chunks:
with open(f, "rb") as af:
res = client.audio.transcriptions.create(
model=model,
file=af,
response_format="text"
)
raw_parts.append(res)
full_raw = "\n".join(raw_parts)
# 簡轉繁
conv_prompt = (
"請將以下內容完整轉換為「繁體中文(台灣用語)」:\n"
"規則:1) 僅做簡→繁字形轉換;2) 不要意譯或改寫;3) 不要添加任何前後綴。\n"
"-----\n" + full_raw
)
trad_resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是嚴格的繁體中文轉換器,只進行字形轉換。"},
{"role": "user", "content": conv_prompt}
],
temperature=0.0,
)
full_trad = trad_resp.choices[0].message.content.strip()
# 摘要
sum_prompt = (
"請用台灣繁體中文撰寫摘要。若內容資訊多,可條列出重點;若內容簡短,請用一句話概述即可。\n\n"
+ full_trad
)
sum_resp = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "你是一位精準且嚴格使用台灣繁體中文的摘要助手。"},
{"role": "user", "content": sum_prompt}
],
temperature=0.2,
)
summ = sum_resp.choices[0].message.content.strip()
return full_trad, summ
# ======================================================
# 💬 Gradio 介面
# ======================================================
def transcribe_with_password(password, file):
if password.strip() != PASSWORD:
raise HTTPException(status_code=403, detail="密碼錯誤 ❌")
if not file:
return "⚠️ 未選擇檔案", "", ""
text, summary = transcribe_core(file.name)
return "✅ 完成", text, summary
with gr.Blocks(theme=gr.themes.Soft()) as demo:
gr.Markdown("## 🎧 LINE 語音轉錄與摘要(支援 .m4a / .mp4)")
pw = gr.Textbox(label="輸入密碼", type="password")
f = gr.File(label="上傳音訊檔")
run = gr.Button("開始轉錄 🚀")
s = gr.Textbox(label="狀態", interactive=False)
t = gr.Textbox(label="轉錄結果", lines=10)
su = gr.Textbox(label="AI 摘要", lines=8)
run.click(transcribe_with_password, [pw, f], [s, t, su])
# ======================================================
# 🚀 啟動
# ======================================================
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
else:
demo.launch()