funasr_integration_analysis.md 6.07 KB

AIfeng/2025-01-27

FunASR集成分析与优化方案

问题分析

1. 当前状况

  • ASR_server.py: 实际启动的是WebSocket服务,而非gRPC服务(注释中的"grpc server port"是误导性的)
  • 服务协议: 使用websockets库提供WebSocket接口,监听指定host:port
  • 依赖缺失: funasr.pyali_nls.py引用的coreutils模块在当前项目中不存在

2. 技术架构分析

ASR_server.py实现要点

# WebSocket服务器,非gRPC
server = await websockets.serve(ws_serve, args.host, args.port, ping_interval=10)

# 模型初始化
asr_model = AutoModel(
    model="paraformer-zh", model_revision="v2.0.4",
    vad_model="fsmn-vad", vad_model_revision="v2.0.4", 
    punc_model="ct-punc-c", punc_model_revision="v2.0.4",
    device=f"cuda:{args.gpu_id}" if args.ngpu else "cpu"
)

连接方式

  • 协议: WebSocket (ws://)
  • 默认端口: 10197
  • 消息格式: JSON + 二进制音频数据
  • 处理模式: 异步队列处理音频文件

集成方案

方案一:简化集成(推荐)

创建独立的FunASR客户端,避免依赖缺失问题:

# funasr_simple_client.py
import asyncio
import websockets
import json
import wave
import threading
from queue import Queue

class SimpleFunASRClient:
    def __init__(self, host="127.0.0.1", port=10197):
        self.host = host
        self.port = port
        self.websocket = None
        self.result_queue = Queue()
        self.connected = False

    async def connect(self):
        uri = f"ws://{self.host}:{self.port}"
        try:
            self.websocket = await websockets.connect(uri)
            self.connected = True
            # 启动消息接收线程
            threading.Thread(target=self._receive_messages, daemon=True).start()
            return True
        except Exception as e:
            print(f"连接失败: {e}")
            return False

    def _receive_messages(self):
        async def receive():
            try:
                async for message in self.websocket:
                    if isinstance(message, str):
                        self.result_queue.put(message)
            except Exception as e:
                print(f"接收消息错误: {e}")
                self.connected = False

        asyncio.run(receive())

    async def recognize_file(self, wav_path):
        if not self.connected:
            return None

        # 发送文件路径进行识别
        message = {"url": wav_path}
        await self.websocket.send(json.dumps(message))

        # 等待结果
        try:
            result = self.result_queue.get(timeout=10)
            return result
        except:
            return None

    async def close(self):
        if self.websocket:
            await self.websocket.close()
            self.connected = False

方案二:修复现有代码

创建缺失的配置模块:

# config_util.py
class Config:
    # ASR配置
    local_asr_ip = "127.0.0.1"
    local_asr_port = 10197

    # 阿里云NLS配置
    key_ali_nls_key_id = "your_key_id"
    key_ali_nls_key_secret = "your_key_secret"
    key_ali_nls_app_key = "your_app_key"

# 创建配置实例
config = Config()

# 为了兼容原代码的导入方式
local_asr_ip = config.local_asr_ip
local_asr_port = config.local_asr_port
key_ali_nls_key_id = config.key_ali_nls_key_id
key_ali_nls_key_secret = config.key_ali_nls_key_secret
key_ali_nls_app_key = config.key_ali_nls_app_key

连接验证

测试连接脚本

# test_funasr_connection.py
import asyncio
import websockets
import json

async def test_connection():
    uri = "ws://127.0.0.1:10197"
    try:
        async with websockets.connect(uri) as websocket:
            print("✅ FunASR服务连接成功")

            # 测试发送消息
            test_message = {"url": "test.wav"}
            await websocket.send(json.dumps(test_message))
            print("✅ 消息发送成功")

            # 等待响应
            try:
                response = await asyncio.wait_for(websocket.recv(), timeout=5)
                print(f"✅ 收到响应: {response}")
            except asyncio.TimeoutError:
                print("⚠️ 未收到响应(可能因为测试文件不存在)")

    except ConnectionRefusedError:
        print("❌ 连接被拒绝,请确认FunASR服务已启动")
    except Exception as e:
        print(f"❌ 连接失败: {e}")

if __name__ == "__main__":
    asyncio.run(test_connection())

部署建议

1. 服务启动

# CPU模式
python -u ASR_server.py --host "127.0.0.1" --port 10197 --ngpu 0

# GPU模式
python -u ASR_server.py --host "127.0.0.1" --port 10197 --ngpu 1 --gpu_id 0

2. 依赖安装

pip install torch modelscope websockets FunASR torchaudio

3. 热词配置

创建data/hotword.txt文件,每行一个热词:

数字人
语音识别
实时对话

性能优化

1. 模型优化

  • 量化: 使用INT8量化减少内存占用
  • 批处理: 支持批量音频处理
  • 缓存: 模型预加载和结果缓存

2. 网络优化

  • 连接池: 维护WebSocket连接池
  • 重连机制: 自动重连和错误恢复
  • 负载均衡: 多实例部署

3. 监控指标

  • 连接数量
  • 处理延迟
  • 识别准确率
  • 资源使用率

技术债务

  1. 依赖管理: 原有代码依赖外部模块,需要重构或补全
  2. 错误处理: 缺少完善的异常处理和重连机制
  3. 配置管理: 硬编码配置需要外部化
  4. 日志系统: 缺少结构化日志记录
  5. 测试覆盖: 需要添加单元测试和集成测试

实施建议

  1. 短期: 使用简化客户端快速集成
  2. 中期: 修复依赖问题,完善错误处理
  3. 长期: 重构为微服务架构,支持多模型切换

结论

FunASR服务使用WebSocket协议,可以正常连接。主要问题是现有集成代码缺少依赖模块。建议采用简化集成方案快速解决连接问题,后续逐步完善架构。