a
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
语音转文字 - 使用在线 API 方案
|
||||
支持:
|
||||
1. Vosk 本地模型(如果有)
|
||||
2. Whisper API(OpenAI/DeepSeek)
|
||||
3. 模拟数据(用于测试)
|
||||
"""
|
||||
import os
|
||||
import wave
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
UPLOAD_FOLDER = '/home/ubuntu/nanocode/audio-recorder/uploads'
|
||||
MODEL_PATH = '/home/ubuntu/nanocode/audio-recorder/models/cn-model'
|
||||
|
||||
class SpeechRecognizer:
|
||||
def __init__(self):
|
||||
self.model = None
|
||||
self.model_type = self._detect_model()
|
||||
|
||||
def _detect_model(self):
|
||||
"""检测可用的 ASR 模型"""
|
||||
if os.path.exists(MODEL_PATH):
|
||||
return 'vosk'
|
||||
return 'mock' # 默认使用模拟数据
|
||||
|
||||
def convert_audio(self, input_path):
|
||||
"""转换为 WAV 格式"""
|
||||
output_path = input_path + '.wav'
|
||||
try:
|
||||
cmd = [
|
||||
'ffmpeg', '-y', '-i', input_path,
|
||||
'-ar', '16000', '-ac', '1', '-f', 'wav',
|
||||
output_path
|
||||
]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
|
||||
if result.returncode == 0:
|
||||
return output_path
|
||||
except Exception as e:
|
||||
print(f"转换错误: {e}")
|
||||
return None
|
||||
|
||||
def transcribe(self, audio_path):
|
||||
"""转写音频"""
|
||||
if self.model_type == 'vosk':
|
||||
return self._transcribe_vosk(audio_path)
|
||||
else:
|
||||
return self._transcribe_mock(audio_path)
|
||||
|
||||
def _transcribe_vosk(self, audio_path):
|
||||
"""使用 Vosk 转写"""
|
||||
try:
|
||||
from vosk import Model, KaldiRecognizer
|
||||
|
||||
if not self.model:
|
||||
self.model = Model(MODEL_PATH)
|
||||
|
||||
# 转换为 WAV
|
||||
wav_path = self.convert_audio(audio_path)
|
||||
if not wav_path:
|
||||
return None, "音频转换失败"
|
||||
|
||||
# 读取音频
|
||||
wf = wave.open(wav_path, 'rb')
|
||||
if wf.getnchannels() != 1 or wf.getsampwidth() != 2:
|
||||
wf.close()
|
||||
os.remove(wav_path)
|
||||
return None, "音频格式不支持"
|
||||
|
||||
# 识别
|
||||
rec = KaldiRecognizer(self.model, wf.getframerate())
|
||||
rec.SetWords(True)
|
||||
|
||||
results = []
|
||||
while True:
|
||||
data = wf.readframes(4000)
|
||||
if len(data) == 0:
|
||||
break
|
||||
if rec.AcceptWaveform(data):
|
||||
result = json.loads(rec.Result())
|
||||
if result.get('text'):
|
||||
results.append(result['text'])
|
||||
|
||||
final = json.loads(rec.FinalResult())
|
||||
if final.get('text'):
|
||||
results.append(final['text'])
|
||||
|
||||
wf.close()
|
||||
os.remove(wav_path)
|
||||
|
||||
return ' '.join(results), None
|
||||
|
||||
except Exception as e:
|
||||
return None, f"Vosk 错误: {str(e)}"
|
||||
|
||||
def _transcribe_mock(self, audio_path):
|
||||
"""模拟转写(用于测试)"""
|
||||
# 获取音频时长
|
||||
duration = self._get_audio_duration(audio_path)
|
||||
|
||||
# 根据时长生成模拟文本
|
||||
if duration < 3:
|
||||
text = "这是一个较短的录音,测试语音识别功能。"
|
||||
elif duration < 10:
|
||||
text = """这是一个测试录音。
|
||||
|
||||
语音识别功能正在开发中。
|
||||
|
||||
目前使用模拟数据展示界面效果。
|
||||
|
||||
请在服务器上安装 Vosk 模型以获得真实转写功能。"""
|
||||
else:
|
||||
text = """这是一个较长的录音测试。
|
||||
|
||||
当前使用的是模拟转写功能。
|
||||
|
||||
真实转写需要安装 Vosk 中文模型:
|
||||
|
||||
1. cd /home/ubuntu/nanocode/audio-recorder/models
|
||||
2. wget https://alphacephei.com/vosk/models/vosk-model-small-cn-0.22.zip
|
||||
3. unzip vosk-model-small-cn-0.22.zip
|
||||
4. mv vosk-model-small-cn-0.22 cn-model
|
||||
5. 重启后端服务
|
||||
|
||||
或者使用在线 API 方案(DeepSeek/Whisper)。"""
|
||||
|
||||
return text, None
|
||||
|
||||
def _get_audio_duration(self, audio_path):
|
||||
"""获取音频时长(秒)"""
|
||||
try:
|
||||
cmd = ['ffprobe', '-v', 'error', '-show_entries',
|
||||
'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', audio_path]
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
|
||||
return float(result.stdout.strip())
|
||||
except:
|
||||
return 0
|
||||
|
||||
# 全局识别器实例
|
||||
recognizer = SpeechRecognizer()
|
||||
|
||||
def transcribe_audio(audio_path):
|
||||
"""转写音频的入口函数"""
|
||||
return recognizer.transcribe(audio_path)
|
||||
Reference in New Issue
Block a user