vosk实时语音识别

vosk介绍以及安装,参考地址:https://blog.csdn.net/qq_35385687/article/details/119209189?spm=1001.2014.3001.5501

文章目录

*
命令行方式直接转写
websoket实现实时转写
前端获取pcm实时传输至后台
完整项目地址

命令行方式直接转写


import argparse
import os
import queue
import sounddevice as sd
import sys
import vosk

q = queue.Queue()

def int_or_str(text):
    """Helper function for argument parsing."""
    try:
        return int(text)
    except ValueError:
        return text

def callback(indata, frames, time, status):
    """This is called (from a separate thread) for each audio block."""
    if status:
        print(status, file=sys.stderr)
    q.put(bytes(indata))

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
    '-l', '--list-devices', action='store_true',
    help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
    print(sd.query_devices())
    parser.exit(0)
parser = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter,
    parents=[parser])
parser.add_argument(
    '-f', '--filename', type=str, metavar='FILENAME',
    help='audio file to store recording to')
parser.add_argument(
    '-m', '--model', type=str, metavar='MODEL_PATH',
    help='Path to the model')
parser.add_argument(
    '-d', '--device', type=int_or_str,
    help='input device (numeric ID or substring)')
parser.add_argument(
    '-r', '--samplerate', type=int, help='sampling rate')
args = parser.parse_args(remaining)

try:
    if args.model is None:
        args.model = "model"
    if not os.path.exists(args.model):
        print("Please download a model for your language from https://alphacephei.com/vosk/models")
        print("and unpack as 'model' in the current folder.")
        parser.exit(0)
    if args.samplerate is None:
        device_info = sd.query_devices(args.device, 'input')

        args.samplerate = int(device_info['default_samplerate'])

    model = vosk.Model(args.model)

    if args.filename:
        dump_fn = open(args.filename, "wb")
    else:
        dump_fn = None

    with sd.RawInputStream(samplerate=args.samplerate, blocksize=16000, device=args.device, dtype='int16',
                           channels=1, callback=callback):
        print('#' * 80)
        print('Press Ctrl+C to stop the recording')
        print('#' * 80)

        rec = vosk.KaldiRecognizer(model, args.samplerate)
        while True:
            data = q.get()
            if rec.AcceptWaveform(data):
                print(rec.Result())
            else:
                print(rec.PartialResult())
            if dump_fn is not None:
                dump_fn.write(data)

except KeyboardInterrupt:
    print('\nDone')
    parser.exit(0)
except Exception as e:
    parser.exit(type(e).__name__ + ': ' + str(e))

websoket实现实时转写


import argparse
import os
import queue
import sounddevice as sd
import sys
import vosk

q = queue.Queue()

def int_or_str(text):
    """Helper function for argument parsing."""
    try:
        return int(text)
    except ValueError:
        return text

def callback(indata, frames, time, status):
    """This is called (from a separate thread) for each audio block."""
    if status:
        print(status, file=sys.stderr)
    q.put(bytes(indata))

parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
    '-l', '--list-devices', action='store_true',
    help='show list of audio devices and exit')
args, remaining = parser.parse_known_args()
if args.list_devices:
    print(sd.query_devices())
    parser.exit(0)
parser = argparse.ArgumentParser(
    description=__doc__,
    formatter_class=argparse.RawDescriptionHelpFormatter,
    parents=[parser])
parser.add_argument(
    '-f', '--filename', type=str, metavar='FILENAME',
    help='audio file to store recording to')
parser.add_argument(
    '-m', '--model', type=str, metavar='MODEL_PATH',
    help='Path to the model')
parser.add_argument(
    '-d', '--device', type=int_or_str,
    help='input device (numeric ID or substring)')
parser.add_argument(
    '-r', '--samplerate', type=int, help='sampling rate')
args = parser.parse_args(remaining)

try:
    if args.model is None:
        args.model = "model"
    if not os.path.exists(args.model):
        print("Please download a model for your language from https://alphacephei.com/vosk/models")
        print("and unpack as 'model' in the current folder.")
        parser.exit(0)
    if args.samplerate is None:
        device_info = sd.query_devices(args.device, 'input')

        args.samplerate = int(device_info['default_samplerate'])

    model = vosk.Model(args.model)

    if args.filename:
        dump_fn = open(args.filename, "wb")
    else:
        dump_fn = None

    with sd.RawInputStream(samplerate=args.samplerate, blocksize=16000, device=args.device, dtype='int16',
                           channels=1, callback=callback):
        print('#' * 80)
        print('Press Ctrl+C to stop the recording')
        print('#' * 80)

        rec = vosk.KaldiRecognizer(model, args.samplerate)
        while True:
            data = q.get()
            if rec.AcceptWaveform(data):
                print(rec.Result())
            else:
                print(rec.PartialResult())
            if dump_fn is not None:
                dump_fn.write(data)

except KeyboardInterrupt:
    print('\nDone')
    parser.exit(0)
except Exception as e:
    parser.exit(type(e).__name__ + ': ' + str(e))

前端获取pcm实时传输至后台

<html>

<head>
    <meta charset="UTF-8">
    <title>Simple Recorder.js demo with record, stop and pausetitle>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <style type="text/css">
        .comments {
            width: 100%;
            overflow: auto;
            word-break: break-all;

        }
    style>
head>

<body>
<div id="controls">
    <button id="recordButton">Recordbutton>
    <button id="stopButton">Stopbutton>
div>

<textarea id="textResult" class="comments" rows="10" cols="10">textarea>

body>
<script type="text/javascript" src="./js/recorder3.js">script>
<script>

    var ws = null;

    var interval;

    let recorder = new Recorder({
        sampleBits: 16,
        sampleRate: 16000,
        numChannels: 1,

        compiling: true
    });

    var recordButton = document.getElementById("recordButton");
    var stopButton = document.getElementById("stopButton");
    var textResult = document.getElementById("textResult");

    recordButton.addEventListener("click", startRecording);
    stopButton.addEventListener("click", stopRecording);

    function startRecording() {
        console.log("recordButton clicked");
        recorder.start().then(() => {

            useWebSocket();
        }, (error) => {

            console.log(出错了);
        });

    }

    function stopRecording() {
        console.log("stopButton clicked", recorder.getPCMBlob());

        recorder.stop();

        if (ws) {
            ws.close();
        }

        clearInterval(interval);

        textResult.innerText = '';

    }

    function useWebSocket() {

        ws = new WebSocket("ws://localhost:5678");

        ws.binaryType = 'arraybuffer';
        ws.onopen = function () {
            console.log('握手成功');
            if (ws.readyState === 1) {
                interval = setInterval(() => {

                    ws.send(recorder.getNextData());
                }, 500)

            }

        };

        ws.onmessage = function (msg) {
            var jsonStr = msg.data;
            console.info(jsonStr);
            textResult.innerText = jsonStr;
            autoTextarea(document.getElementById("textResult"));
        };

        ws.onerror = function (err) {
            console.error(err);
            textResult.innerText = '';
        };

        ws.onclose = function (msg) {
            console.info(msg);
            textResult.innerText = '';
        };

    }

    var autoTextarea = function (elem, extra, maxHeight) {

        if (elem.length > 0) {
            for (var i = 0; i < elem.length; i++) {
                e(elem[i]);
            }
        } else {
            e(elem);
        }

        function e(elem) {
            extra = extra || 0;
            var isFirefox = !!document.getBoxObjectFor || 'mozInnerScreenX' in window,
                isOpera = !!window.opera && !!window.opera.toString().indexOf('Opera'),
                addEvent = function (type, callback) {
                    elem.addEventListener ?
                        elem.addEventListener(type, callback, false) :
                        elem.attachEvent('on' + type, callback);
                },
                getStyle = elem.currentStyle ? function (name) {
                    var val = elem.currentStyle[name];

                    if (name === 'height' && val.search(/px/i) !== 1) {
                        var rect = elem.getBoundingClientRect();
                        return rect.bottom - rect.top -
                            parseFloat(getStyle('paddingTop')) -
                            parseFloat(getStyle('paddingBottom')) + 'px';
                    }
                    ;

                    return val;
                } : function (name) {
                    return getComputedStyle(elem, null)[name];
                },
                minHeight = parseFloat(getStyle('height'));

            elem.style.resize = 'none';

            var change = function () {
                var scrollTop, height,
                    padding = 0,
                    style = elem.style;

                if (elem._length === elem.value.length) return;
                elem._length = elem.value.length;

                if (!isFirefox && !isOpera) {
                    padding = parseInt(getStyle('paddingTop')) + parseInt(getStyle('paddingBottom'));
                }
                ;
                scrollTop = document.body.scrollTop || document.documentElement.scrollTop;

                elem.style.height = minHeight + 'px';
                if (elem.scrollHeight > minHeight) {
                    if (maxHeight && elem.scrollHeight > maxHeight) {
                        height = maxHeight - padding;
                        style.overflowY = 'auto';
                    } else {
                        height = elem.scrollHeight - padding;
                        style.overflowY = 'hidden';
                    }
                    ;
                    style.height = height + extra + 'px';
                    scrollTop += parseInt(style.height) - elem.currHeight;
                    document.body.scrollTop = scrollTop;
                    document.documentElement.scrollTop = scrollTop;
                    elem.currHeight = parseInt(style.height);
                }
                ;
            };

            addEvent('propertychange', change);
            addEvent('input', change);
            addEvent('focus', change);
            change();
        }
    };

script>
html>

完整项目地址

https://gitee.com/yzdyzdyzd/speechToText

Original: https://blog.csdn.net/qq_35385687/article/details/119357825
Author: 阳宗德
Title: vosk实时语音识别

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/512303/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球