funasr的服务部署

本文最后更新于 2024年5月30日 早上

funasr是一个语音识别工具包,提供多种功能,包括语音识别(ASR)、语音端点检测(VAD)、标点恢复、语言模型、说话人验证、说话人分离和多人对话语音识别等,本文是对它地使用记录

1 本地使用

1.1 安装与测试

安装funasr包

1
pip install -U funasr

测试:

1
funasr ++model=paraformer-zh ++vad_model="fsmn-vad" ++punc_model="ct-punc" ++input=asr_example_zh.wav

目前我使用地版本来看,会遇到No module named 'torchaudio',就安装下

1
pip install torchaudio

然后上面的测试命令也是默认使用modelscope而不是huggingface,所以还需要要安装

1
pip install -U modelscope

输出

1
2
3
4
5
rtf_avg: 0.063: 100%|████████████████████████████████████| 1/1 [00:00<00:00,  4.81it/s]
rtf_avg: 0.413: 100%|████████████████████████████████████| 1/1 [00:01<00:00, 1.34s/it]
rtf_avg: -0.034: 100%|███████████████████████████████████| 1/1 [00:00<00:00, 28.28it/s]
rtf_avg: 0.425, time_speech: 3.257, time_escape: 1.383: 100%|█| 1/1 [00:01<00:00, 1.3
[{'key': 'SPEAKER_05_209652_212909', 'text': '不要再说你在那个世界,我在这个世界这种花 了。', 'timestamp': [[50, 150], [150, 350], [350, 450], [450, 630], [630, 730], [730, 870], [870, 1030], [1030, 1130], [1130, 1270], [1270, 1510], [1770, 1970], [1970, 2110], [2110, 2270], [2270, 2350], [2350, 2430], [2430, 2570], [2570, 2670], [2670, 2790], [2790, 3030], [3030, 3175]]}]

1.2 代码调用

下列只记录我可能用到的,更详细的请参考官方说明

模型加载的相关参数

1
model = AutoModel(model=[str], device=[str], ncpu=[int], output_dir=[str], batch_size=[int], hub=[str], **kwargs)
  • model(str): 模型仓库 中的模型名称,或本地磁盘中的模型路径
  • device(str): cuda:0(默认gpu0),使用 GPU 进行推理,指定。如果为cpu,则使用 CPU 进行推理
  • ncpu(int): 4 (默认),设置用于 CPU 内部操作并行性的线程数
  • output_dir(str): None (默认),如果设置,输出结果的输出路径
  • batch_size(int): 1 (默认),解码时的批处理,样本个数
  • hub(str):ms(默认),从modelscope下载模型。如果为hf,从huggingface下载模型。
  • **kwargs(dict): 所有在config.yaml中参数,均可以直接在此处指定,例如,vad模型中最大切割长度 max_single_segment_time=6000 (毫秒)。

1.2.1 非实时语音识别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from funasr import AutoModel
model = AutoModel(model="paraformer-zh", # 语音识别,带时间戳输出,非实时
vad_model="fsmn-vad", # 语音端点检测,实时
vad_kwargs={"max_single_segment_time":60000}, # 最大切割音频时长, 单位是毫秒ms
punc_model="ct-punc", # 标点恢复模型
spk_model="cam++" # 说话人确认/分割
)
wav_file = "SPEAKER_05_209652_212909.wav"

# batch_size_s 表示采用动态batch,batch中总音频时长,单位为秒s。
# batch_size_threshold_s: 表示vad_model切割后音频片段时长超过 batch_size_threshold_s阈值时,将batch_size数设置为1, 单位为秒s.
res = model.generate(input=wav_file, batch_size_s=300, batch_size_threshold_s=60, hotword='这种话')
print(res)

输出

1
[{'key': 'SPEAKER_05_209652_212909', 'text': '不要再说你在那个世界,我在这个世界这种话 了。', 'timestamp': [[50, 150], [150, 350], [350, 450], [450, 630], [630, 730], [730, 870], [870, 1030], [1030, 1130], [1130, 1270], [1270, 1510], [1770, 1970], [1970, 2110], [2110, 2270], [2270, 2350], [2350, 2430], [2430, 2570], [2570, 2670], [2670, 2790], [2790, 3030], [3030, 3175]], 'sentence_info': [{'text': '不要再说你在那个世界,', 'start': 50, 'end': 1510, 'timestamp': [[50, 150], [150, 350], [350, 450], [450, 630], [630, 730], [730, 870], [870, 1030], [1030, 1130], [1130, 1270], [1270, 1510]], 'spk': 0}, {'text': '我在这个世界这种话了。', 'start': 1510, 'end': 3175, 'timestamp': [[1770, 1970], [1970, 2110], [2110, 2270], [2270, 2350], [2350, 2430], [2430, 2570], [2570, 2670], [2670, 2790], [2790, 3030], [3030, 3175]], 'spk': 0}]}]

1.2.2 标点恢复

看之后是否能用在我那个字幕提取工具上

1
2
3
4
from funasr import AutoModel
model = AutoModel(model="ct-punc")
res = model.generate(input="不要再说你在那个世界我在这个世界这种话了")
print(res)

输出

1
[{'key': 'rand_key_2yW4Acq9GFz6Y', 'text': '不要再说你在那个世界,我在这个世界这种话了 。', 'punc_array': tensor([1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3])}]

2 服务器部署

2.1 中文离线文件转写服务(CPU版本)

docker安装

1
2
curl -O https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/shell/install_docker.sh;
sudo bash install_docker.sh

镜像启动

1
2
3
4
5
6
7
# 拉去镜像,下列镜像发布于2024/5/15
sudo docker pull \
registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.5

sudo docker run -p 10095:10095 -it --privileged=true --name funasr \
-v /home/server/AI/models/:/workspace/models \
registry.cn-hangzhou.aliyuncs.com/funasr_repo/funasr:funasr-runtime-sdk-cpu-0.4.5

运行后会自动进入容器

启动服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cd FunASR/runtime
nohup bash run_server.sh \
--download-model-dir /workspace/models \
--vad-dir damo/speech_fsmn_vad_zh-cn-16k-common-onnx \
--model-dir damo/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-onnx \
--punc-dir damo/punc_ct-transformer_cn-en-common-vocab471067-large-onnx \
--lm-dir damo/speech_ngram_lm_zh-cn-ai-wesp-fst \
--itn-dir thuduj12/fst_itn_zh \
--hotword /workspace/models/hotwords.txt > log.txt 2>&1 &
--certfile 0

# 如果您想关闭ssl,增加参数:--certfile 0
# 如果您想使用时间戳或者nn热词模型进行部署,请设置--model-dir为对应模型:
# damo/speech_paraformer-large-vad-punc_asr_nat-zh-cn-16k-common-vocab8404-onnx(时间戳)
# damo/speech_paraformer-large-contextual_asr_nat-zh-cn-16k-common-vocab8404-onnx(nn热词)
# 如果您想在服务端加载热词,请在宿主机文件./funasr-runtime-resources/models/hotwords.txt配置热词(docker映射地址为/workspace/models/hotwords.txt):
# 每行一个热词,格式(热词 权重):阿里巴巴 20(注:热词理论上无限制,但为了兼顾性能和效果,建议热词长度不超过10,个数不超过1k,权重1~100)

官方给的测试脚本

该脚本需要的环境

1
2
apt install ffmpeg
pip install websockets ffmpeg-python

下载脚本

1
2
3
4
5
wget https://isv-data.oss-cn-hangzhou.aliyuncs.com/ics/MaaS/ASR/sample/funasr_samples.tar.gz

tar -zxvf funasr_samples.tar.gz

cd samples/python

运行脚本

1
python funasr_wss_client.py --host "127.0.0.1" --port 10095 --mode offline --audio_in "./test.wav" --ssl 0 

输出

1
2
3
4
5
Namespace(host='127.0.0.1', port=10095, chunk_size=[5, 10, 5], chunk_interval=10, hotword='', audio_in='./test.wav', audio_fs=16000, send_without_sleep=True, thread_num=1, words_max_print=10000, output_dir=None, ssl=0, use_itn=1, mode='offline')
connect to ws://127.0.0.1:10095
pid0_0: demo: 不要再说你在那个世界,我在这个世界这种花了。 timestamp: [[50,150],[150,350],[350,450],[450,630],[630,730],[730,870],[870,1030],[1030,1130],[1130,1270],[1270,1810],[1810,1970],[1970,2110],[2110,2270],[2270,2350],[2350,2430],[2430,2550],[2550,2670],[2670,2790],[2790,3030],[3030,3175]]
Exception: sent 1000 (OK); then received 1000 (OK)
end

该脚本的其他参数:

1
2
3
4
5
6
7
8
9
--host 为FunASR runtime-SDK服务部署机器ip,默认为本机ip(127.0.0.1),如果client与服务不在同一台服务器,
需要改为部署机器ip
--port 10095 部署端口号
--mode offline表示离线文件转写
--audio_in 需要进行转写的音频文件,支持文件路径,文件列表wav.scp
--thread_num 设置并发发送线程数,默认为1
--ssl 设置是否开启ssl证书校验,默认1开启,设置为0关闭
--hotword 热词文件,每行一个热词,格式(热词 权重):阿里巴巴 20
--use_itn 设置是否使用itn,默认1开启,设置为0关闭

裁切后的示例代码

官方提供的示例功能多,所以内容也多,我实际上也就使用单音频的离线转换,所以下列示例就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import websockets
import asyncio
import wave
import json

async def ws_client():
    url = "ws://127.0.0.1:20002"
    async with websockets.connect(url, subprotocols=["binary"], ping_interval=None) as websocket:
        wav_path = "../audio/asr_example.wav"
        with wave.open(wav_path, "rb") as wav_file:
            params = wav_file.getparams()
            sample_rate = wav_file.getframerate()
            frames = wav_file.readframes(wav_file.getnframes())
            audio_bytes = bytes(frames)

        message = json.dumps ({"mode": "offline", "chunk_size": [5, 10, 5], "chunk_interval": 10, "audio_fs": sample_rate, "wav_name": "demo", "is_speaking": True, "hotwords": "", "itn": True})
        await websocket.send(message)
        # 分包发送
        chunk_interval = 10
        chunk_size = 10
        stride = int(60 * chunk_size / chunk_interval / 1000 * 16000 * 2)
        chunk_num = (len(audio_bytes) - 1) // stride + 1
        print("chunk_num :{}".format(chunk_num))
        print("stride :{}".format(stride))
        for i in range(chunk_num):
            beg = i * stride
            data = audio_bytes[beg:beg + stride]
            message = data
            await websocket.send(message)
            # 传输结束
            if i == chunk_num - 1:
                is_speaking = False
                message = json.dumps({"is_speaking": is_speaking})
                await websocket.send(message)
            await asyncio.sleep(0.001)
        response = await websocket.recv()
        print(f"Received: {response}")

asyncio.get_event_loop().run_until_complete(ws_client())

kuonasr仓库

将上述代码添加到kuonasr仓库中,修改配置选择funasr,填写url后即可通过下列方式使用。

1
2
3
4
5
6
7
from kuonasr import ASR
asr = ASR()
try:
result = asr.convert("./kuonasr/audio/asr_example.wav")
print(result)
except Exception as e:
print(e)

输出

1
2
3
python .\example.py
2024-05-30 14:16:46.220 | INFO | kuonasr:__init__:27 - asr init : funasr , 耗时:0.06
2024-05-30 14:16:46.812 | INFO | kuonasr:convert:53 - asr over. 文件 ./kuonasr/audio/test2.wav ,转换耗时:0.57,结果:你好,很高兴认识你。

funasr的服务部署
https://blog.kala.love/posts/cbe699d7/
作者
久远·卡拉
发布于
2023年10月26日
许可协议