Loading

python部署funasr非实时识别服务高并发问题

部署了一个funasr的中文音频非实时识别的服务接口,出现以下几种情况:

  1. 多次请求时接口未响应
  2. 音频文件135(1h)时响应很慢
  3. 用135M的音频文件请求接口,要一分钟后接口才收到请求

测试用例如下:

1. 单例

asr_example(1 min/2M)
山路.mp3(1.34h/135M)

import time
import requests


import socket
import urllib3


def allowed_gai_family():
    return socket.AF_INET

# 用于取消ipv6请求
urllib3.util.connection.allowed_gai_family = allowed_gai_family

audio_file=r"D:\pycharm_project\ai-meeting-assistant\example\asr_example.wav"
audio_file=r"D:\pycharm_project\ai-meeting-assistant\example\山路.mp3"
funasr_url="http://xxx:11111/recognition"
with open(audio_file, 'rb') as file:
    audio_data = file.read()  # 读取整个文件的二进制数据
form_data={
    'audio': ('asr_example.wav',audio_data,'audio/wav')
}
start_time=time.time()

response=requests.post(funasr_url,files=form_data)
audio_text=response.json()['text']

end_time=time.time()
print("耗时",end_time-start_time)
audio_text

大文件请求结果

(.venv) (base) PS E:\asr\test> python .\single_test.py
耗时 217.44692373275757
(.venv) (base) PS E:\asr\test> python .\single_test.py
耗时 210.00433087348938

服务构建:
runtime/python/http/server.py


2026.6.15

场景: 会议转录,一般1h+、100MB+的时长,且多家门店同时调用该转录工作流,asr节点超时限制最高600s。

第一版:
runtime/python/http/server.py
使用sdk funasr来加载模型
根据官方说明,使用python构建服务时起三个实例,python + fastapi + ngnix + docker 。当多个超长超大音频等待处理时,就会出现排队的情况,甚至出现超时。
c0cf0728ecf2959fa327c52704653a9d

services:
  funasr-server1:
    image: funasr-server-custom
    container_name: funasr-api-1
    volumes:
      - ./temp_dir:/app/temp_dir
      - ./logs/server1:/app/logs
    environment:
      - TZ=Asia/Shanghai
      - KEEP_TEMP_FILES=false
      - CUDA_VISIBLE_DEVICES=0
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]
    restart: unless-stopped

  nginx:
    image: nginx:latest
    container_name: funasr-nginx
    ports:
      - "10098:10098"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs/nginx:/var/log/nginx
      - ./nginx/temp:/tmp/nginx  # 添加临时目录挂载
    depends_on:
      - funasr-server1
      - funasr-server2
      - funasr-server3
    restart: unless-stopped
	

ngnix.conf

user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;

events {
    worker_connections 2048;
    use epoll;
    multi_accept on;
}

http {
    include /etc/nginx/conf.d/*.conf;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;

    # 优化大文件传输
    client_max_body_size 200M;
    proxy_connect_timeout 3600s;        # 设置与后端建立连接的超时时间为 3600 秒
    proxy_send_timeout 3600s;           # 设置向后端发送请求的超时时间为 3600 秒
    proxy_read_timeout 3600s;           # 设置从后端读取响应的超时时间为 3600 秒
    send_timeout 3600s;                 # 设置客户端与 Nginx 之间的超时时间为 3600 秒

    upstream funasr_backend {
        # 最少连接算法
        least_conn;
        server funasr-server1:10095;
    }

    server {
        listen 10098;

        location / {
            proxy_pass http://funasr_backend;
        }
    }
}

server.py 添加中间件,查看文件上传速度

class UploadProgressMiddleware:
    async def __call__(self, request: Request, call_next):
        if request.url.path == "/recognition":
            content_length = request.headers.get("content-length")
            if content_length:
                start_time = time.time()
                total_size = int(content_length)
                logger.info(f"[{time.strftime('%H:%M:%S')}] 开始接收文件上传请求")
                logger.info(f"文件大小: {total_size / 1024 / 1024:.2f}MB")

                original_receive = request.receive
                uploaded_size = 0
                last_log_time = time.time()  # 添加上次日志时间记录

                async def receive_wrapper():
                    nonlocal uploaded_size, last_log_time
                    message = await original_receive()

                    if message["type"] == "http.request":
                        chunk = message.get("body", b"")
                        uploaded_size += len(chunk)
                        current_time = time.time()
                        elapsed = current_time - start_time

                        # 每秒最多打印一次日志
                        if current_time - last_log_time >= 1.0:
                            speed = uploaded_size / elapsed / 1024 / 1024
                            progress = uploaded_size / total_size * 100

                            logger.info(
                                f"[{time.strftime('%H:%M:%S')}] "
                                f"上传进度: {progress:.1f}%, "
                                f"已接收: {uploaded_size / 1024 / 1024:.1f}MB, "
                                f"速度: {speed:.2f}MB/s"
                            )
                            last_log_time = current_time

                        if message.get("more_body", False) is False:
                            # 只在最后打印一次完成信息
                            total_time = time.time() - start_time
                            logger.info(
                                f"[{time.strftime('%H:%M:%S')}] "
                                f"文件接收完成,总耗时: {total_time:.1f}秒, "
                                f"平均速度: {total_size / total_time / 1024 / 1024:.2f}MB/s"
                            )

                    return message

                request._receive = receive_wrapper

        try:
            response = await call_next(request)
            return response
        except Exception as e:
            logger.error(f"请求处理发生错误: {e}")
            raise


app.middleware("http")(UploadProgressMiddleware())

当前官方群提供了QA文档,说明主要维护grpc
234f7fdf-5423-43f2-974f-15729fddfd72

第二版:
runtime/http
使用源码便衣

第三版:
拉取c++版本离线文件转写服务的镜像

sudo docker pull \
  registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.7
mkdir -p ./funasr-runtime-resources/models
sudo docker run -p 10095:10095 -it --privileged=true \
  -v $PWD/funasr-runtime-resources/models:/workspace/models \
  registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.7

ab757ed4-d75c-4dd9-8629-6436c88e08e9
简单测试:

python3 python/websocket/funasr_wss_client.py --host "127.0.0.1" --port 10095 --mode offline --audio_in "./funasr_api/asr_example.wav"

06294afc-6ed6-472f-8138-5fb8b8cceca0

离线和实时的区别主要在于,实时边上传边识别,减少了上传文件的延时
image

image

posted @ 2024-12-05 21:50  踩坑大王的日记  阅读(766)  评论(0)    收藏  举报