Flutter语音识别插件vosk_flutter_2的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter语音识别插件vosk_flutter_2的使用

Vosk Flutter Plugin

Flutter plugin for Vosk speech recognition.

平台支持

Android iOS MacOS Web Linux Windows

使用方法

配置

请遵循安装页面上的指示进行操作。

Android

android/app/proguard-rules.pro文件中添加以下pro guard规则(如果该文件不存在,请创建它):

-keep class com.sun.jna.* { *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }

如果你想使用麦克风输入,将麦克风权限添加到你的AndroidManifest.xml

<uses-permission android:name="android.permission.RECORD_AUDIO" />
加载模型

pubspec.yaml中添加:

flutter:
  assets:
    - assets/models/

加载模型:

final vosk = VoskFlutterPlugin.instance();
final enSmallModelPath = await ModelLoader()
    .loadFromAssets('assets/models/vosk-model-small-en-us-0.15.zip');
创建识别器
final recognizer = await vosk.createRecognizer(
    model: model,
    sampleRate: sampleRate,
);
final recognizerWithGrammar = await vosk.createRecognizer(
    model: model,
    sampleRate: sampleRate,
    grammar: ['one', 'two', 'three'],
);
识别音频数据
Uint8List audioBytes = ...; // 音频数据为PCM 16位单声道格式
List<String> results = [];
int chunkSize = 8192;
int pos = 0;

while (pos + chunkSize < audioBytes.length) {
    final resultReady = await recognizer.acceptWaveformBytes(
      Uint8List.fromList(audioBytes.getRange(pos, pos + chunkSize).toList()));
    pos += chunkSize;

    if (resultReady) {
      print(await recognizer.getResult());
    } else {
      print(await recognizer.getPartialResult());
    }
}
await recognizer.acceptWaveformBytes(
  Uint8List.fromList(audioBytes.getRange(pos, audioBytes.length).toList()));
print(await recognizer.getFinalResult());
识别麦克风数据
Android
final speechService = await vosk.initSpeechService(recognizer);
speechService.onPartial().forEach((partial) => print(partial));
speechService.onResult().forEach((result) => print(result));
await speechService.start();

完整示例代码

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:record/record.dart';
import 'package:vosk_flutter_2/vosk_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: VoskFlutterDemo(),
    );
  }
}

class VoskFlutterDemo extends StatefulWidget {
  const VoskFlutterDemo({Key? key}) : super(key: key);

  [@override](/user/override)
  State<VoskFlutterDemo> createState() => _VoskFlutterDemoState();
}

class _VoskFlutterDemoState extends State<VoskFlutterDemo> {
  static const _textStyle = TextStyle(fontSize: 30, color: Colors.black);
  static const _modelName = 'vosk-model-small-en-us-0.15';
  static const _sampleRate = 16000;

  final _vosk = VoskFlutterPlugin.instance();
  final _modelLoader = ModelLoader();
  final _recorder = Record();

  String? _fileRecognitionResult;
  String? _error;
  Model? _model;
  Recognizer? _recognizer;
  SpeechService? _speechService;

  bool _recognitionStarted = false;

  [@override](/user/override)
  void initState() {
    super.initState();

    _modelLoader
        .loadModelsList()
        .then((modelsList) =>
            modelsList.firstWhere((model) => model.name == _modelName))
        .then((modelDescription) =>
            _modelLoader.loadFromNetwork(modelDescription.url)) // 加载模型
        .then((modelPath) => _vosk.createModel(modelPath)) // 创建模型对象
        .then((model) => setState(() => _model = model))
        .then((_) => _vosk.createRecognizer(
            model: _model!, sampleRate: _sampleRate)) // 创建识别器
        .then((value) => _recognizer = value)
        .then((recognizer) {
      if (Platform.isAndroid) {
        _vosk
            .initSpeechService(_recognizer!) // 初始化语音服务
            .then((speechService) =>
                setState(() => _speechService = speechService))
            .catchError((e) => setState(() => _error = e.toString()));
      }
    }).catchError((e) {
      setState(() => _error = e.toString());
      return null;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    if (_error != null) {
      return Scaffold(
          body: Center(child: Text("错误: $_error", style: _textStyle)));
    } else if (_model == null) {
      return const Scaffold(
          body: Center(child: Text("正在加载模型...", style: _textStyle)));
    } else if (Platform.isAndroid && _speechService == null) {
      return const Scaffold(
        body: Center(
          child: Text("正在初始化语音服务...", style: _textStyle),
        ),
      );
    } else {
      return Platform.isAndroid ? _androidExample() : _commonExample();
    }
  }

  Widget _androidExample() {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () async {
                  if (_recognitionStarted) {
                    await _speechService!.stop();
                  } else {
                    await _speechService!.start();
                  }
                  setState(() => _recognitionStarted = !_recognitionStarted);
                },
                child: Text(_recognitionStarted
                    ? "停止识别"
                    : "开始识别")),
            StreamBuilder(
                stream: _speechService!.onPartial(),
                builder: (context, snapshot) => Text(
                    "部分结果: ${snapshot.data.toString()}",
                    style: _textStyle)),
            StreamBuilder(
                stream: _speechService!.onResult(),
                builder: (context, snapshot) => Text(
                    "最终结果: ${snapshot.data.toString()}",
                    style: _textStyle)),
          ],
        ),
      ),
    );
  }

  Widget _commonExample() {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
                onPressed: () async {
                  if (_recognitionStarted) {
                    await _stopRecording();
                  } else {
                    await _recordAudio();
                  }
                  setState(() => _recognitionStarted = !_recognitionStarted);
                },
                child: Text(
                    _recognitionStarted ? "停止录音" : "开始录音")),
            Text("最终识别结果: $_fileRecognitionResult",
                style: _textStyle),
          ],
        ),
      ),
    );
  }

  Future<void> _recordAudio() async {
    try {
      await _recorder.start(
          samplingRate: 16000, encoder: AudioEncoder.wav, numChannels: 1);
    } catch (e) {
      _error = e.toString() +
          '\n\n 确保 fmedia 已安装在 Linux 上';
    }
  }

  Future<void> _stopRecording() async {
    try {
      final filePath = await _recorder.stop();
      if (filePath != null) {
        final bytes = File(filePath).readAsBytesSync();
        _recognizer!.acceptWaveformBytes(bytes);
        _fileRecognitionResult = await _recognizer!.getFinalResult();
      }
    } catch (e) {
      _error = e.toString() +
          '\n\n 确保 fmedia 已安装在 Linux 上';
    }
  }
}

更多关于Flutter语音识别插件vosk_flutter_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter语音识别插件vosk_flutter_2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用vosk_flutter_2插件进行语音识别的代码示例。这个插件利用了Vosk语音识别引擎来实现语音识别功能。

首先,确保你已经在pubspec.yaml文件中添加了vosk_flutter_2依赖:

dependencies:
  flutter:
    sdk: flutter
  vosk_flutter_2: ^最新版本号  # 请替换为实际最新版本号

然后运行flutter pub get来安装依赖。

接下来,是具体的代码实现步骤:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:vosk_flutter_2/vosk_flutter_2.dart';
  1. 创建语音识别页面
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Voice Recognition with Vosk'),
        ),
        body: VoiceRecognitionPage(),
      ),
    );
  }
}

class VoiceRecognitionPage extends StatefulWidget {
  @override
  _VoiceRecognitionPageState createState() => _VoiceRecognitionPageState();
}

class _VoiceRecognitionPageState extends State<VoiceRecognitionPage> {
  late VoskRecognizer _recognizer;
  late RecognitionResult _result;
  bool _isListening = false;

  @override
  void initState() {
    super.initState();
    _initRecognizer();
  }

  Future<void> _initRecognizer() async {
    _recognizer = await VoskRecognizer.create(
      modelPath: 'path/to/your/model',  // 替换为你的模型路径
      sampleRate: 16000,  // 根据你的模型要求设置采样率
    );
  }

  Future<void> _startListening() async {
    setState(() {
      _isListening = true;
    });

    _result = await _recognizer.listen(onPartialResult: (result) {
      // 处理部分识别结果
      print('Partial result: $result');
    }, onError: (error) {
      // 处理错误
      print('Error: $error');
    });

    setState(() {
      _isListening = false;
    });

    // 处理最终识别结果
    print('Final result: ${_result.hypotheses.first.transcript}');
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(_isListening ? 'Listening...' : 'Tap to start listening'),
          SizedBox(height: 20),
          ElevatedButton(
            onPressed: _isListening ? null : _startListening,
            child: Text(_isListening ? 'Listening...' : 'Start Listening'),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    _recognizer.dispose();
    super.dispose();
  }
}
  1. 注意事项
  • modelPath:需要替换为你的Vosk语音识别模型的实际路径。你可以从Vosk Model Zoo下载合适的模型。
  • sampleRate:确保采样率与你的模型匹配。
  • 错误处理:在实际应用中,你可能需要更详细的错误处理逻辑。
  • 资源释放:在dispose方法中释放_recognizer资源,避免内存泄漏。

这个示例展示了如何使用vosk_flutter_2插件进行基本的语音识别。你可以根据实际需求进一步扩展和优化代码,比如添加UI反馈、处理不同的识别结果等。

回到顶部