| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- from core.router import Parser
- from models.result import ParseResult
- from utils.logger import log
- from utils.ffmpeg_wrapper import FFmpegWrapper
- import os
- import tempfile
- import requests
- class AudioParser(Parser):
- """音频文件解析器"""
-
- def __init__(self):
- self.ffmpeg = FFmpegWrapper()
- # Qwen3-ASR模型配置 - 使用专门的音频转录端点
- self.qwen_asr_api_url = "http://10.192.72.13:7283/v1/audio/transcriptions"
- log.info("音频解析器初始化完成,使用本地部署的Qwen3-ASR模型")
-
- async def parse(self, file_path: str) -> ParseResult:
- """
- 解析音频文件
-
- Args:
- file_path: 文件路径
-
- Returns:
- ParseResult: 解析结果
- """
- log.info(f"开始解析音频文件: {file_path}")
- temp_wav_path = None
- try:
- # 1. 预处理:转换为16k/16bit/mono wav
- with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_file:
- temp_wav_path = temp_file.name
-
- log.info(f"创建临时文件: {temp_wav_path}")
- self.ffmpeg.convert_audio(file_path, temp_wav_path)
- log.info(f"音频转换完成: {temp_wav_path}")
-
- # 2. 使用Qwen3-ASR进行语音识别
- log.info("开始使用Qwen3-ASR进行语音识别...")
- log.info(f"使用的API地址: {self.qwen_asr_api_url}")
-
- content = []
- result = None
- try:
- # 检查文件大小
- file_size = os.path.getsize(temp_wav_path)
- log.info(f"音频文件大小: {file_size / (1024 * 1024):.2f} MB")
-
- # 使用专门的音频转录端点,支持文件上传
- log.info("准备使用文件上传方式进行语音识别...")
-
- # 构建请求数据
- session = requests.Session()
- session.trust_env = False # 禁用环境变量中的代理设置
-
- # 使用multipart/form-data上传文件
- files = {
- 'file': ('audio.wav', open(temp_wav_path, 'rb'), 'audio/wav')
- }
- data = {
- 'model': '/data/shared/Qwen3-ASR/qwen/Qwen3-ASR-1.7B',
- 'language': 'zh',
- 'response_format': 'json'
- }
-
- # 发送请求
- log.info("开始发送请求...")
- # 增加超时时间,音频处理可能需要更长时间
- response = session.post(self.qwen_asr_api_url, files=files, data=data, timeout=600)
- log.info(f"请求完成,状态码: {response.status_code}")
-
- # 打印响应内容以进行调试
- if response.status_code != 200:
- log.warning(f"响应内容: {response.text}")
-
- response.raise_for_status()
- result = response.json()
-
- log.info("Qwen3-ASR语音识别完成")
- log.info(f"识别结果: {result}")
-
- # 3. 构建解析结果
- if result and 'text' in result:
- full_text = result['text']
- # 清理识别结果中的标记
- clean_text = full_text.replace('language Chinese<asr_text>', '').strip()
- content.append(f"完整文本: {clean_text}")
- else:
- log.warning("解析失败:未获取到有效结果")
- content.append("解析失败:未获取到有效结果")
-
- log.info(f"构建完成,内容长度: {len(content)}")
- except requests.exceptions.Timeout as e:
- log.error(f"Qwen3-ASR语音识别超时: {str(e)}")
- content.append("语音识别超时,请检查服务是否正常运行")
- except requests.exceptions.ConnectionError as e:
- log.error(f"Qwen3-ASR语音识别连接错误: {str(e)}")
- content.append("语音识别连接错误,请检查服务地址是否正确")
- except Exception as e:
- log.error(f"Qwen3-ASR语音识别失败: {str(e)}")
- import traceback
- log.error(f"异常堆栈: {traceback.format_exc()}")
- # 即使失败,也尝试返回一个基本结果
- content.append("语音识别失败,但文件已成功处理")
-
- # 清理临时文件
- if temp_wav_path and os.path.exists(temp_wav_path):
- os.remove(temp_wav_path)
- log.info(f"临时文件已清理: {temp_wav_path}")
-
- return ParseResult(
- content="\n".join(content),
- metadata={
- "parser": "Qwen3-ASR",
- "file_size": os.path.getsize(file_path),
- "api_url": self.qwen_asr_api_url
- },
- file_type="audio"
- )
- except Exception as e:
- log.error(f"音频文件解析失败: {str(e)}")
- import traceback
- log.error(f"异常堆栈: {traceback.format_exc()}")
- # 清理临时文件
- if temp_wav_path and os.path.exists(temp_wav_path):
- try:
- os.remove(temp_wav_path)
- log.info(f"临时文件已清理: {temp_wav_path}")
- except:
- pass
- return ParseResult(
- content="",
- metadata={"error": str(e)},
- file_type="audio"
- )
|