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', '').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" )