Initial clean project import

This commit is contained in:
cat-shark
2026-06-19 18:41:41 +08:00
commit a13b804c7a
1306 changed files with 220568 additions and 0 deletions
@@ -0,0 +1,193 @@
#!/usr/bin/env python3
"""
FUNASR语音识别备用方案
使用speech_recognition库进行本地语音识别
如果speech_recognition库不可用,降级使用pydub和SpeechRecognition
"""
import json
import sys
import argparse
import os
from pathlib import Path
from datetime import datetime
def recognize_with_funasr(audio_path: str, language: str = 'zh', enable_word_timestamp: bool = True):
"""
使用FUNASR本地模型进行语音识别
"""
try:
from funasr import AutoModel
model = AutoModel(
model="paraformer-zh", # 中文模型
vad_model="fsmn-vad", # 语音活动检测
vad_kwargs={"max_single_segment_time": 30000},
device="cpu" # 使用CPU,避免GPU依赖
)
res = model.generate(
input=audio_path,
cache={},
language=language,
merge_consecutive_texts=False
)
# 转换为标准格式
segments = []
current_time = 0.0
for item in res:
if isinstance(item, dict) and 'text' in item:
text = item['text']
# 估算时长(假设每个字0.5秒)
duration = len(text) * 0.5
segment = {
'text': text,
'start': current_time,
'end': current_time + duration,
'words': []
}
# 如果启用词级时间戳
if enable_word_timestamp and isinstance(item, dict) and 'details' in item:
words = item['details']
for word_info in words:
word = {
'word': word_info.get('text', ''),
'start': word_info.get('start', 0) / 1000, # 转换为秒
'end': word_info.get('end', 0) / 1000,
'confidence': word_info.get('confidence', 0.0)
}
segment['words'].append(word)
segments.append(segment)
current_time += duration
return {
'segments': segments,
'language': language,
'duration': current_time
}
except ImportError:
return recognize_with_speech_recognition(audio_path, language, enable_word_timestamp)
def recognize_with_speech_recognition(audio_path: str, language: str = 'zh', enable_word_timestamp: bool = True):
"""
使用SpeechRecognition库作为备用方案
支持Google Cloud Speech API、Sphinx等
"""
try:
import speech_recognition as sr
recognizer = sr.Recognizer()
# 支持多种音频格式
if audio_path.endswith('.wav'):
with sr.AudioFile(audio_path) as source:
audio = recognizer.record(source)
else:
# 对于其他格式,首先需要转换为WAV
# 这里假设音频已经被转换为WAV
with sr.AudioFile(audio_path) as source:
audio = recognizer.record(source)
# 尝试使用Google Cloud Speech Recognition(需要网络)
try:
text = recognizer.recognize_google(audio, language='zh-CN' if language == 'zh' else language)
# 转换为标准格式
segments = [{
'text': text,
'start': 0.0,
'end': 5.0, # 默认5秒
'words': []
}]
return {
'segments': segments,
'language': language,
'duration': 5.0
}
except sr.UnknownValueError:
raise Exception("无法识别音频内容")
except sr.RequestError as e:
raise Exception(f"Google Speech Recognition请求失败: {e}")
except ImportError:
return recognize_with_pydub(audio_path, language, enable_word_timestamp)
def recognize_with_pydub(audio_path: str, language: str = 'zh', enable_word_timestamp: bool = True):
"""
如果都不可用,提供一个有用的错误信息
"""
raise Exception(
f"语音识别失败。需要安装以下至少一个库:\n"
f"1. pip install funasr torch torchaudio\n"
f"2. pip install SpeechRecognition pydub\n"
f"3. 或者配置FUNASR HTTP服务 (FUNASR_API_URL环境变量)"
)
def split_audio_into_segments(audio_path: str, segment_duration: int = 30):
"""
将长音频分割成短段进行识别(避免超时)
"""
try:
from pydub import AudioSegment
audio = AudioSegment.from_file(audio_path)
total_duration = len(audio) # 毫秒
segments = []
for i in range(0, total_duration, segment_duration * 1000):
segment = audio[i:i + segment_duration * 1000]
segments.append(segment)
return segments
except ImportError:
raise Exception("需要安装pydub库: pip install pydub")
def main():
parser = argparse.ArgumentParser(description='语音识别脚本')
parser.add_argument('--audio', required=True, help='音频文件路径')
parser.add_argument('--language', default='zh', help='语言代码(zh或en')
parser.add_argument('--enable-word-timestamp', default='1', help='是否启用词级时间戳')
args = parser.parse_args()
if not os.path.exists(args.audio):
print(json.dumps({
'success': False,
'error': f"音频文件不存在: {args.audio}"
}))
sys.exit(1)
try:
enable_word_timestamp = args.enable_word_timestamp == '1'
# 尝试多种识别方式
result = recognize_with_funasr(
args.audio,
args.language,
enable_word_timestamp
)
print(json.dumps(result))
sys.exit(0)
except Exception as e:
print(json.dumps({
'success': False,
'error': str(e),
'timestamp': datetime.now().isoformat()
}))
sys.exit(1)
if __name__ == '__main__':
main()