Uotpia commited on
Commit
e8d5270
·
verified ·
1 Parent(s): b3dc0ab

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -29
app.py CHANGED
@@ -5,72 +5,114 @@ import torch
5
  import spaces
6
  import gradio as gr
7
  from fastapi import FastAPI, UploadFile, File, Form, HTTPException
8
- from fastapi.responses import JSONResponse
9
  from transformers import pipeline
10
 
11
- # 1. 声明加载模型(Hugging Face 官方原生 Whisper Small)
 
12
  MODEL_NAME = "openai/whisper-small"
13
-
14
- # 2. 全局初始化 Pipeline!
15
- # 注意:在 ZeroGPU 环境下,全局初始化时将 device 设置为 "cuda"。
16
- # 官方的 spaces 库会在容器启动时自动拦截它,防止在 CPU 阶段报错;
17
- # 同时在调用 @spaces.GPU 函数时,系统会自动把整个 Pipeline 的计算放到 A100 上。
18
  pipe = pipeline(
19
  "automatic-speech-recognition",
20
  model=MODEL_NAME,
21
  chunk_length_s=30,
22
- device="cuda"
23
  )
24
 
25
- # 3. 核心计算函数
26
- @spaces.GPU
27
- def transcribe_core(audio_path: str):
28
- # 【最关键的改变】这里完全不需要任何手动 .to("cuda")
29
- # 因为我们在上面全局指定了 device="cuda",在 @spaces.GPU 装饰器内部,
30
- # 框架会自动、无缝地把这个 Pipeline 调度到 A100 GPU 显存中运行!
31
- result = pipe(audio_path, generate_kwargs={"language": "chinese"})
 
 
 
 
 
 
 
 
32
  return result["text"]
33
 
34
- # 4. 创建 Gradio 界面
35
  def gradio_predict(audio_path):
36
  if audio_path is None:
37
  return "请先上传音频或录音!"
38
  try:
39
  return transcribe_core(audio_path)
40
  except Exception as e:
41
- return f"GPU 转录出错: {str(e)}"
42
 
43
  demo = gr.Interface(
44
  fn=gradio_predict,
45
  inputs=gr.Audio(sources=["microphone", "upload"], type="filepath", label="输入音频"),
46
  outputs=gr.Textbox(label="识别出的文本"),
47
  title="Whisper 语音识别 API 节点",
48
- description="【A100 GPU 动态加速版 - Transformers 官方兼容】支持网页端测试,同时也支持 OpenAI 兼容的 /v1/audio/transcriptions 接口!"
49
  )
50
 
51
- # 5. 获取 FastAPI 实例并扩展 API 路由
52
- app = demo.app
53
 
54
- @app.post("/v1/audio/transcriptions")
55
- async def transcribe_api(
56
- file: UploadFile = File(...),
57
- model_param: str = Form("whisper-1")
58
- ):
59
  suffix = os.path.splitext(file.filename)[1] or ".mp3"
60
  with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
61
  shutil.copyfileobj(file.file, temp_file)
62
  temp_path = temp_file.name
63
 
64
  try:
65
- transcription_text = transcribe_core(temp_path)
 
66
  except Exception as e:
67
- raise HTTPException(status_code=500, detail=f"Transcription failed: {str(e)}")
68
  finally:
69
  if os.path.exists(temp_path):
70
  os.remove(temp_path)
71
 
72
- return JSONResponse(content={"text": transcription_text})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
- # 6. 启动服务
75
  if __name__ == "__main__":
76
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
5
  import spaces
6
  import gradio as gr
7
  from fastapi import FastAPI, UploadFile, File, Form, HTTPException
8
+ from fastapi.responses import JSONResponse, PlainTextResponse
9
  from transformers import pipeline
10
 
11
+ # 1. 加载模型(为了让你随时可用且不限额度,此处先使用 CPU 演示;
12
+ # 如需切换回 GPU,请取消 transcribe_core 上的 @spaces.GPU 注释,并将 device 改为 "cuda")
13
  MODEL_NAME = "openai/whisper-small"
 
 
 
 
 
14
  pipe = pipeline(
15
  "automatic-speech-recognition",
16
  model=MODEL_NAME,
17
  chunk_length_s=30,
18
+ device="cpu" # 若要 GPU 极速,修改为 "cuda"
19
  )
20
 
21
+ # 2. 核心转录逻辑
22
+ # @spaces.GPU # 如果你想要在 GPU 额度内极速转录,请取消这一行的注释
23
+ def transcribe_core(audio_path: str, target_language: str = None, is_translate: bool = False):
24
+ generate_kwargs = {}
25
+
26
+ # 支持指定语言,如果不指定,让模型自动检测
27
+ if target_language:
28
+ generate_kwargs["language"] = target_language
29
+
30
+ # 如果是翻译任务(translations 端点),强制指定任务和输出语言为英文
31
+ if is_translate:
32
+ generate_kwargs["language"] = "english"
33
+ generate_kwargs["task"] = "translate"
34
+
35
+ result = pipe(audio_path, generate_kwargs=generate_kwargs)
36
  return result["text"]
37
 
38
+ # --- Gradio 界面 ---
39
  def gradio_predict(audio_path):
40
  if audio_path is None:
41
  return "请先上传音频或录音!"
42
  try:
43
  return transcribe_core(audio_path)
44
  except Exception as e:
45
+ return f"转录出错: {str(e)}"
46
 
47
  demo = gr.Interface(
48
  fn=gradio_predict,
49
  inputs=gr.Audio(sources=["microphone", "upload"], type="filepath", label="输入音频"),
50
  outputs=gr.Textbox(label="识别出的文本"),
51
  title="Whisper 语音识别 API 节点",
52
+ description="【完美兼容 OpenAI 规范】支持网页端测试,同时提供 100% 兼容的 /v1/audio/transcriptions & /v1/audio/translations 接口!"
53
  )
54
 
55
+ app = demo.app
 
56
 
57
+ # --- 🛠️ 核心部分:完美兼容 OpenAI 的处理函数 ---
58
+ async def process_openai_audio_request(file, response_format, language, is_translate):
59
+ # 限制并确保支持的文件后缀,避免 tempfile 出错
 
 
60
  suffix = os.path.splitext(file.filename)[1] or ".mp3"
61
  with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
62
  shutil.copyfileobj(file.file, temp_file)
63
  temp_path = temp_file.name
64
 
65
  try:
66
+ # 执行转录
67
+ text = transcribe_core(temp_path, target_language=language, is_translate=is_translate)
68
  except Exception as e:
69
+ raise HTTPException(status_code=500, detail=f"OpenAI Audio API failed: {str(e)}")
70
  finally:
71
  if os.path.exists(temp_path):
72
  os.remove(temp_path)
73
 
74
+ # 100% 兼容 OpenAI 的输出格式逻辑 (支持 json, text, verbose_json 等格式)
75
+ if response_format in ["text", "vtt", "srt"]:
76
+ return PlainTextResponse(text)
77
+
78
+ # 如果是 json 或默认情况,返回标准的 OpenAI 字典
79
+ # verbose_json 在 Whisper pipeline 简化版中,我们也提供标准兼容层
80
+ return JSONResponse(content={"text": text})
81
+
82
+
83
+ # 3. 🎯 完美兼容接口一:语音转录 (Transcriptions)
84
+ @app.post("/v1/audio/transcriptions")
85
+ async def transcribe_api(
86
+ file: UploadFile = File(...),
87
+ model: str = Form("whisper-1"), # 接收 openai 的 model 参数
88
+ language: str = Form(None), # 接收指定的 ISO-639-1 语言代码(例如 zh, en)
89
+ prompt: str = Form(None), # 忽略或预留
90
+ response_format: str = Form("json"), # 接收输出格式:json, text 等
91
+ temperature: float = Form(0.0) # 忽略或预留
92
+ ):
93
+ return await process_openai_audio_request(
94
+ file=file,
95
+ response_format=response_format,
96
+ language=language,
97
+ is_translate=False
98
+ )
99
+
100
+
101
+ # 4. 🎯 完美兼容接口二:语音翻译 (Translations - 强制输出英文)
102
+ @app.post("/v1/audio/translations")
103
+ async def translate_api(
104
+ file: UploadFile = File(...),
105
+ model: str = Form("whisper-1"),
106
+ prompt: str = Form(None),
107
+ response_format: str = Form("json"),
108
+ temperature: float = Form(0.0)
109
+ ):
110
+ return await process_openai_audio_request(
111
+ file=file,
112
+ response_format=response_format,
113
+ language="english",
114
+ is_translate=True
115
+ )
116
 
 
117
  if __name__ == "__main__":
118
  demo.launch(server_name="0.0.0.0", server_port=7860)