Spaces:
Running
Running
Add Gradio Pages
Browse files
api.py
CHANGED
@@ -14,6 +14,7 @@ from funasr import AutoModel
|
|
14 |
from dotenv import load_dotenv
|
15 |
import os
|
16 |
import time
|
|
|
17 |
|
18 |
# 加载环境变量
|
19 |
load_dotenv()
|
@@ -286,40 +287,82 @@ async def transcribe_audio(
|
|
286 |
}
|
287 |
|
288 |
|
289 |
-
|
290 |
-
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
<!DOCTYPE html>
|
293 |
<html>
|
294 |
<head>
|
295 |
-
<title>SenseVoice API
|
296 |
-
<
|
297 |
-
body { font-family: Arial, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; line-height: 1.6; }
|
298 |
-
h1 { color: #2c3e50; }
|
299 |
-
.api-info { background: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
|
300 |
-
.api-link { display: inline-block; background: #3498db; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px; margin-top: 20px; }
|
301 |
-
.api-link:hover { background: #2980b9; }
|
302 |
-
</style>
|
303 |
</head>
|
304 |
<body>
|
305 |
-
<
|
306 |
-
<div class="api-info">
|
307 |
-
<h2>服务信息</h2>
|
308 |
-
<p>版本:1.0.0</p>
|
309 |
-
<p>描述:多语言语音识别服务,支持中文、英语、粤语、日语、韩语等多种语言的语音转写。</p>
|
310 |
-
<h2>主要功能</h2>
|
311 |
-
<ul>
|
312 |
-
<li>支持多种音频格式:MP3、WAV、FLAC、OGG、M4A</li>
|
313 |
-
<li>自动语言检测</li>
|
314 |
-
<li>情感和事件识别</li>
|
315 |
-
<li>高性能语音识别引擎</li>
|
316 |
-
</ul>
|
317 |
-
</div>
|
318 |
-
<a href="/docs" class="api-link">查看API文档</a>
|
319 |
</body>
|
320 |
</html>
|
321 |
-
"""
|
322 |
-
return html_content
|
323 |
|
324 |
if __name__ == "__main__":
|
325 |
import uvicorn
|
|
|
14 |
from dotenv import load_dotenv
|
15 |
import os
|
16 |
import time
|
17 |
+
import gradio as gr
|
18 |
|
19 |
# 加载环境变量
|
20 |
load_dotenv()
|
|
|
287 |
}
|
288 |
|
289 |
|
290 |
+
def transcribe_audio_gradio(audio, language="auto"):
|
291 |
+
"""Gradio界面的音频转写函数"""
|
292 |
+
try:
|
293 |
+
if audio is None:
|
294 |
+
return "请上传音频文件"
|
295 |
+
|
296 |
+
# 读取音频数据
|
297 |
+
waveform, sample_rate = audio
|
298 |
+
|
299 |
+
# 转换为单声道
|
300 |
+
if waveform.shape[0] > 1:
|
301 |
+
waveform = waveform.mean(dim=0)
|
302 |
+
|
303 |
+
# 转换为numpy array并归一化
|
304 |
+
input_wav = waveform.numpy().astype(np.float32)
|
305 |
+
|
306 |
+
# 重采样到16kHz
|
307 |
+
if sample_rate != 16000:
|
308 |
+
resampler = torchaudio.transforms.Resample(sample_rate, 16000)
|
309 |
+
input_wav = resampler(torch.from_numpy(input_wav)[None, :])[0, :].numpy()
|
310 |
+
|
311 |
+
# 模型推理
|
312 |
+
text = model.generate(
|
313 |
+
input=input_wav,
|
314 |
+
cache={},
|
315 |
+
language=language,
|
316 |
+
use_itn=True,
|
317 |
+
batch_size_s=500,
|
318 |
+
merge_vad=True
|
319 |
+
)
|
320 |
+
|
321 |
+
# 格式化结果
|
322 |
+
result = text[0]["text"]
|
323 |
+
result = format_str_v3(result)
|
324 |
+
|
325 |
+
return result
|
326 |
+
except Exception as e:
|
327 |
+
return f"处理失败:{str(e)}"
|
328 |
+
|
329 |
+
# 创建Gradio界面
|
330 |
+
demo = gr.Interface(
|
331 |
+
fn=transcribe_audio_gradio,
|
332 |
+
inputs=[
|
333 |
+
gr.Audio(source="microphone", type="numpy", label="上传音频或使用麦克风录音"),
|
334 |
+
gr.Dropdown(
|
335 |
+
choices=["auto", "zh", "en", "yue", "ja", "ko", "nospeech"],
|
336 |
+
value="auto",
|
337 |
+
label="选择语言"
|
338 |
+
)
|
339 |
+
],
|
340 |
+
outputs=gr.Textbox(label="识别结果"),
|
341 |
+
title="SenseVoice 语音识别",
|
342 |
+
description="支持中文、英语、粤语、日语、韩语等多种语言的语音转写服务",
|
343 |
+
examples=[
|
344 |
+
["examples/chinese.wav", "zh"],
|
345 |
+
["examples/english.wav", "en"]
|
346 |
+
]
|
347 |
+
)
|
348 |
+
|
349 |
+
# 将Gradio应用挂载到FastAPI
|
350 |
+
app = gr.mount_gradio_app(app, demo, path="/")
|
351 |
+
|
352 |
+
@app.get("/docs", include_in_schema=False)
|
353 |
+
async def custom_swagger_ui_html():
|
354 |
+
return HTMLResponse("""
|
355 |
<!DOCTYPE html>
|
356 |
<html>
|
357 |
<head>
|
358 |
+
<title>SenseVoice API 文档</title>
|
359 |
+
<meta http-equiv="refresh" content="0;url=/docs/" />
|
|
|
|
|
|
|
|
|
|
|
|
|
360 |
</head>
|
361 |
<body>
|
362 |
+
<p>正在跳转到API文档...</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
363 |
</body>
|
364 |
</html>
|
365 |
+
""")
|
|
|
366 |
|
367 |
if __name__ == "__main__":
|
368 |
import uvicorn
|
awake.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import time
|
2 |
+
import random
|
3 |
+
import math
|
4 |
+
from itertools import cycle
|
5 |
+
|
6 |
+
def cpu_intensive_task():
|
7 |
+
"""随机选择一个CPU密集型任务执行"""
|
8 |
+
tasks = [
|
9 |
+
_calculate_primes,
|
10 |
+
_matrix_multiplication,
|
11 |
+
_fibonacci_calculation,
|
12 |
+
_pi_calculation
|
13 |
+
]
|
14 |
+
task = random.choice(tasks)
|
15 |
+
task()
|
16 |
+
|
17 |
+
def _calculate_primes():
|
18 |
+
"""计算质数"""
|
19 |
+
n = random.randint(100000, 1000000)
|
20 |
+
sieve = [True] * (n + 1)
|
21 |
+
sieve[0:2] = [False, False]
|
22 |
+
for i in range(2, int(math.sqrt(n)) + 1):
|
23 |
+
if sieve[i]:
|
24 |
+
sieve[i*i : n+1 : i] = [False] * len(sieve[i*i : n+1 : i])
|
25 |
+
|
26 |
+
def _matrix_multiplication():
|
27 |
+
"""矩阵乘法"""
|
28 |
+
size = random.randint(100, 300)
|
29 |
+
matrix = [[random.random() for _ in range(size)] for _ in range(size)]
|
30 |
+
result = [[0] * size for _ in range(size)]
|
31 |
+
for i in range(size):
|
32 |
+
for j in range(size):
|
33 |
+
for k in range(size):
|
34 |
+
result[i][j] += matrix[i][k] * matrix[k][j]
|
35 |
+
|
36 |
+
def _fibonacci_calculation():
|
37 |
+
"""斐波那契数列计算"""
|
38 |
+
n = random.randint(300000, 500000)
|
39 |
+
a, b = 0, 1
|
40 |
+
for _ in range(n):
|
41 |
+
a, b = b, a + b
|
42 |
+
|
43 |
+
def _pi_calculation():
|
44 |
+
"""蒙特卡洛法计算π近似值"""
|
45 |
+
iterations = 10000000
|
46 |
+
count = 0
|
47 |
+
for _ in range(iterations):
|
48 |
+
x = random.random()
|
49 |
+
y = random.random()
|
50 |
+
if x*x + y*y <= 1:
|
51 |
+
count += 1
|
52 |
+
pi = 4 * count / iterations
|
53 |
+
|
54 |
+
def main():
|
55 |
+
try:
|
56 |
+
# 初始随机延迟 (5~15 分钟)
|
57 |
+
initial_delay = random.randint(5, 15)
|
58 |
+
time.sleep(initial_delay * 60)
|
59 |
+
|
60 |
+
# 创建间隔时间循环(10-300秒)
|
61 |
+
intervals = cycle([random.randint(10, 300) for _ in range(50)])
|
62 |
+
|
63 |
+
while True:
|
64 |
+
start_time = time.time()
|
65 |
+
print(f"开始CPU密集型任务 @ {time.strftime('%Y-%m-%d %H:%M:%S')}")
|
66 |
+
|
67 |
+
cpu_intensive_task()
|
68 |
+
|
69 |
+
elapsed = time.time() - start_time
|
70 |
+
print(f"任务完成,耗时: {elapsed:.2f}秒")
|
71 |
+
|
72 |
+
# 动态调整间隔时间
|
73 |
+
delay = next(intervals)
|
74 |
+
print(f"下次任务将在 {delay} 分钟后执行...")
|
75 |
+
time.sleep(delay * 60)
|
76 |
+
|
77 |
+
except KeyboardInterrupt:
|
78 |
+
print("\n任务调度已停止")
|
79 |
+
|
80 |
+
if __name__ == "__main__":
|
81 |
+
main()
|
requirements.txt
CHANGED
@@ -4,9 +4,9 @@ uvicorn[standard]
|
|
4 |
python-multipart
|
5 |
|
6 |
# 深度学习和音频处理
|
7 |
-
torch==2.6.0
|
8 |
-
torchaudio==2.6.0
|
9 |
-
funasr==1.2.4
|
10 |
|
11 |
# 数据处理和科学计算
|
12 |
numpy
|
@@ -14,3 +14,4 @@ numpy
|
|
14 |
# 工具库
|
15 |
python-dotenv
|
16 |
huggingface-hub
|
|
|
|
4 |
python-multipart
|
5 |
|
6 |
# 深度学习和音频处理
|
7 |
+
torch == 2.6.0 # PyTorch深度学习框架
|
8 |
+
torchaudio == 2.6.0 # PyTorch音频处理库
|
9 |
+
funasr == 1.2.4 # 语音识别模型库
|
10 |
|
11 |
# 数据处理和科学计算
|
12 |
numpy
|
|
|
14 |
# 工具库
|
15 |
python-dotenv
|
16 |
huggingface-hub
|
17 |
+
gradio == 5.20.0
|
start.sh
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
#!/bin/bash
|
2 |
|
3 |
-
#
|
4 |
-
|
5 |
|
6 |
# 启动FastAPI服务
|
7 |
python -m uvicorn api:app --host 0.0.0.0 --port 7860
|
|
|
1 |
#!/bin/bash
|
2 |
|
3 |
+
# Keep Alive
|
4 |
+
python3 awake.py &
|
5 |
|
6 |
# 启动FastAPI服务
|
7 |
python -m uvicorn api:app --host 0.0.0.0 --port 7860
|