snowboy+kaldi nouvelle génération (k2-fsa) sherpa-onnx réalise la reconnaissance vocale hors ligne [assistant vocal]

arrière-plan

L'objectif principal de cette série est de compléter dans un premier temps les fonctions de base d'un haut-parleur intelligent, notamment le réveil vocal, la reconnaissance vocale (parole en texte), le traitement des demandes des utilisateurs (telles que la vérification de la météo, etc., principalement réalisés grâce au système propre à Rasa. intention définie), synthèse vocale (texte à parole) )Fonction.

La reconnaissance vocale et la synthèse vocale sont mises en œuvre hors ligne.

La reconnaissance vocale utilise Sherpa-onnx, qui peut réaliser une reconnaissance vocale hors ligne en chinois et en anglais.

Certains des packages d'installation utilisés dans cet article ont été partiellement construits dans les conditions nécessaires de l'article Snowboy. Une fois l'installation de la reconnaissance vocale hors ligne terminée, le code correspondant sera écrit dans le projet Snowboy. Une fois la voix réveillée, la parole la reconnaissance est appelée à traduire ce que dit l’utilisateur.

Adresse de l'article sur le réveil vocal :

Snowboy personnalise les mots de réveil pour réaliser le réveil vocal [Assistant vocal]_Blog de Yin Changqing-Blog CSDN

Article de référence

Tutoriel sherpa-onnx (fortement recommandé d'installer selon les étapes sur le site officiel) :

Installation — documentation sherpa 1.3

Modèles précompilés pour sherpa-onnx

Modèles pré-entraînés — documentation sherpa 1.3

pratique

Téléchargez et installez sherpa-onnx

cd /home/test

git clone https://github.com/k2-fsa/sherpa-onnx
cd sherpa-onnx
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j6

Une fois l'installation terminée, le fichier exécutable de sherpa-onnx se trouvera dans le répertoire bin.

Télécharger des modèles précompilés

J'ai choisi la version paraformer hors ligne du modèle car elle prend en charge la reconnaissance hors ligne en chinois et en anglais. Cette reconnaissance hors ligne est basée sur des fichiers vidéo wav, qui répondent tout simplement aux exigences.

Adresse du site officiel de référence :

Modèles Paraformer — documentation sherpa 1.3

Voici les étapes :

cd /home/test/sherpa-onnx

GIT_LFS_SKIP_SMUDGE=1 git clone https://huggingface.co/csukuangfj/sherpa-onnx-paraformer-zh-2023-03-28
cd sherpa-onnx-paraformer-zh-2023-03-28
git lfs pull --include "*.onnx"

Vérifiez si le téléchargement a réussi et faites attention à la taille du fichier modèle.

sherpa-onnx-paraformer-zh-2023-03-28$ ls -lh *.onnx
-rw-r--r-- 1 kuangfangjun root 214M Apr  1 07:28 model.int8.onnx
-rw-r--r-- 1 kuangfangjun root 824M Apr  1 07:28 model.onnx

Vous pouvez voir deux fichiers de modèle. Lorsqu'ils sont testés localement, la différence entre les deux modèles n'est pas trop grande. J'ai choisi la version int8.

Tester la reconnaissance vocale

Testez l'effet de reconnaissance vocale suivant

cd /home/test/sherpa-onnx

./build/bin/sherpa-onnx-offline \
  --tokens=./sherpa-onnx-paraformer-zh-2023-03-28/tokens.txt \
  --paraformer=./sherpa-onnx-paraformer-zh-2023-03-28/model.int8.onnx \
  ./sherpa-onnx-paraformer-zh-2023-03-28/test_wavs/0.wav

Lorsque l'impression correcte correspondante apparaît, cela signifie que la préparation à la reconnaissance vocale est terminée.

Intégré à Snowboy

Tout d'abord, il y a l'API Python sous python-api-examples dans le répertoire sherpa-onnx. Ce dont nous avons besoin est le fichier offline-decode-files.py, dans lequel la méthode main() est utilisée pour identifier un fichier wav hors ligne.

Ensuite, nous modifions un peu le fichier, principalement pour configurer les paramètres par défaut du modèle, puis revenons au contenu de la reconnaissance une fois la reconnaissance terminée.

décoder hors ligne.py

Renommez le fichier offline-decode-files.py en offlinedecode.py ou créez un nouveau fichier offlinedecode.py

touch offlinedecode.py

vim offlinedecode.py

Modifier le contenu du fichier

#!/usr/bin/env python3
#
# Copyright (c)  2023 by manyeyes

"""
This file demonstrates how to use sherpa-onnx Python API to transcribe
file(s) with a non-streaming model.
Please refer to
https://k2-fsa.github.io/sherpa/onnx/index.html
to install sherpa-onnx and to download the pre-trained models
used in this file.
"""
import time
import wave
from typing import List, Tuple

import numpy as np
import sherpa_onnx


class Constants:
    encoder="" # or 如果用zipformer模型需要修改成zipformer的 encoder-epoch-12-avg-4.int8.onnx
    decoder="" # or 如果用zipformer模型需要修改成zipformer的decoder-epoch-12-avg-4.int8.onnx
    joiner="" # or 如果用zipformer模型需要修改成zipformer的joiner-epoch-12-avg-4.int8.onnx
    tokens="/home/test/sherpa-onnx/sherpa-onnx-paraformer-zh-2023-03-28/tokens.txt" # 如果用zipformer模型需要修改成zipformer的tokens.txt
    num_threads=1
    sample_rate=16000
    feature_dim=80
    decoding_method="greedy_search" # Or modified_ Beam_ Search, only used when the encoder is not empty
    contexts="" # 关键词微调,只在modified_ Beam_ Search模式下有用
    context_score=1.5
    debug=False
    modeling_unit="char"
    paraformer="/home/test/sherpa-onnx/sherpa-onnx-paraformer-zh-2023-03-28/model.int8.onnx" # 实际上使用的是该模型

global args,contexts_list,recognizer
args = Constants()

def encode_contexts(args, contexts: List[str]) -> List[List[int]]:
    tokens = {}
    with open(args.tokens, "r", encoding="utf-8") as f:
        for line in f:
            toks = line.strip().split()
            tokens[toks[0]] = int(toks[1])
    return sherpa_onnx.encode_contexts(
        modeling_unit=args.modeling_unit, contexts=contexts, sp=None, tokens_table=tokens
    )


def read_wave(wave_filename: str) -> Tuple[np.ndarray, int]:
    """
    Args:
      wave_filename:
        Path to a wave file. It should be single channel and each sample should
        be 16-bit. Its sample rate does not need to be 16kHz.
    Returns:
      Return a tuple containing:
       - A 1-D array of dtype np.float32 containing the samples, which are
       normalized to the range [-1, 1].
       - sample rate of the wave file
    """

    with wave.open(wave_filename) as f:
        assert f.getnchannels() == 1, f.getnchannels()
        assert f.getsampwidth() == 2, f.getsampwidth()  # it is in bytes
        num_samples = f.getnframes()
        samples = f.readframes(num_samples)
        samples_int16 = np.frombuffer(samples, dtype=np.int16)
        samples_float32 = samples_int16.astype(np.float32)

        samples_float32 = samples_float32 / 32768
        return samples_float32, f.getframerate()

# 初始化(因为用到的是paraformer,所以实际上初始化的是paraformer的识别)
def init():
    global args
    global recognizer
    global contexts_list
    contexts_list=[]
    if args.encoder:
        contexts = [x.strip().upper() for x in args.contexts.split("/") if x.strip()]
        if contexts:
            print(f"Contexts list: {contexts}")
        contexts_list = encode_contexts(args, contexts)

        recognizer = sherpa_onnx.OfflineRecognizer.from_transducer(
            encoder=args.encoder,
            decoder=args.decoder,
            joiner=args.joiner,
            tokens=args.tokens,
            num_threads=args.num_threads,
            sample_rate=args.sample_rate,
            feature_dim=args.feature_dim,
            decoding_method=args.decoding_method,
            context_score=args.context_score,
            debug=args.debug,
        )
    elif args.paraformer:
        recognizer = sherpa_onnx.OfflineRecognizer.from_paraformer(
            paraformer=args.paraformer,
            tokens=args.tokens,
            num_threads=args.num_threads,
            sample_rate=args.sample_rate,
            feature_dim=args.feature_dim,
            decoding_method=args.decoding_method,
            debug=args.debug,
        )

# 语音识别
# *sound_files 要识别的音频路径
# return 识别后的结果
def asr(*sound_files):
    global args
    global recognizer
    global contexts_list
    start_time = time.time()

    streams = []
    total_duration = 0
    for wave_filename in sound_files:
        samples, sample_rate = read_wave(wave_filename)
        duration = len(samples) / sample_rate
        total_duration += duration
        if contexts_list:
            s = recognizer.create_stream(contexts_list=contexts_list)
        else:
            s = recognizer.create_stream()
        s.accept_waveform(sample_rate, samples)

        streams.append(s)

    recognizer.decode_streams(streams)
    results = [s.result.text for s in streams]
    end_time = time.time()

    for wave_filename, result in zip(sound_files, results):
        return f"{result}"

Une fois l'édition terminée et enregistrée, déplacez le fichier vers le répertoire Python3 de snowboy.

mv offlinedecode.py /home/test/snowboy/examples/Python3/

démo.py

Modifier le fichier demo.py de Snowboy

cd /home/test/snowboy/examples/Python3/

vim demo.py

La principale modification est qu'une fois que Snowboy a réveillé l'appareil, il commence à enregistrer. Lorsque l'enregistrement se termine, il appelle sherpa-onnx pour reconnaître le contenu vocal. Modifiez demo.py avec le contenu suivant

import snowboydecoder
import signal
import os
import offlinedecode

interrupted = False

def signal_handler(signal, frame):
    global interrupted
    interrupted = True

def interrupt_callback():
    global interrupted
    return interrupted


# 初始化语音识别
offlinedecode.init()

# 唤醒词模型文件
model = '../../model/hotword.pmdl'

# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)

detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')

# 录音之后的回调
# fname 音频文件路径
def audio_recorder_callback(fname):
    text = offlinedecode.asr(fname)
    # 打印识别内容
    print(text)
    # 删除录音文件
    if isinstance(fname, str) and os.path.exists(fname):
        if os.path.isfile(fname):
            os.remove(fname)


# main loop
detector.start(detected_callback=snowboydecoder.play_audio_file,
               audio_recorder_callback=audio_recorder_callback,
               interrupt_check=interrupt_callback,
               sleep_time=0.03)

detector.terminate()

Une fois l'édition terminée, enregistrez-la, puis testez si la reconnaissance est réussie.

Tester l'effet d'intégration

cd /home/test/snowboy/examples/Python3/

python demo.py

Après succès, le contenu de reconnaissance sera imprimé et le fichier d'enregistrement local sera supprimé.

Je suppose que tu aimes

Origine blog.csdn.net/anshichuxuezhe/article/details/132151456
conseillé
Classement