Flutter嵌入式JavaScript引擎插件rhino_flutter的使用

Flutter嵌入式JavaScript引擎插件rhino_flutter的使用

Rhino Speech-to-Intent引擎

由加拿大温哥华的Picovoice制作。

Rhino是Picovoice的Speech-to-Intent引擎。它可以直接从给定上下文内的口语命令中推断出意图,并实时返回结果。例如,给定一个口语命令“Can I have a small double-shot espresso?”(我可以要一杯小杯双份意式浓缩咖啡吗?),Rhino会推断用户想要点一杯饮料,并发出以下推理结果:

{
  "type": "espresso",
  "size": "small",
  "numberOfShots": "2"
}

Rhino的特点包括:

  • 准确性高
  • 使用在现实世界环境中训练的深度神经网络。
  • 紧凑且计算效率高,非常适合物联网应用。
  • 自服务。开发人员和设计师可以使用Picovoice控制台训练自定义模型。

兼容性

该绑定适用于运行在以下平台上的Flutter 2.8.1+:

  • Android 5.0+ (API 21+)
  • iOS 13.0+

安装

首先,你需要在系统上安装Flutter SDK。安装完成后,你可以运行flutter doctor来确定是否有其他缺失的要求。

要将Rhino插件添加到你的应用项目中,你可以在pub.yaml文件中引用它:

dependencies:
  rhino_flutter: ^<版本号>

如果你更喜欢克隆仓库并在本地使用,首先运行copy_resources.sh注意:在Windows上,需要Git Bash或其他bash shell,否则你必须手动将库复制到项目中)。然后你可以引用本地绑定位置:

dependencies:
  rhino_flutter:
    path: /路径/到/rhino/flutter/绑定

AccessKey

Rhino初始化时需要有效的Picovoice AccessKeyAccessKey作为你在使用Rhino SDK时的凭证。你可以免费获得AccessKey。务必保密你的AccessKey。 注册或登录到Picovoice控制台以获取你的AccessKey

权限

要启用硬件麦克风的录音功能,你必须确保在iOS和Android上都启用了正确的权限。

在iOS上,打开你的Info.plist文件并添加以下行:

<key>NSMicrophoneUsageDescription</key>
<string>[权限说明]</string>

在Android上,打开你的AndroidManifest.xml文件并添加以下行:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

注意:当为iOS发布归档时,你可能需要更改项目的构建设置,以防止Rhino库被剥离。为此,在XCode中打开Runner项目并将部署设置中的Strip Style更改为’非全局符号’。

使用

该模块为你提供了两种级别的API供选择,具体取决于你的需求。

高级API

RhinoManager 提供了一个高级API,处理音频录制。这是快速开始的最简单方式。

RhinoManager.create 构造函数将使用传递给它的上下文文件创建一个RhinoManager实例。

import 'package:rhino/rhino_manager.dart';
import 'package:rhino/rhino_error.dart';

final String accessKey = '{ACCESS_KEY}';  // 从Picovoice控制台(https://console.picovoice.ai/)获得的AccessKey

void createRhinoManager() async {
    try {
        _rhinoManager = await RhinoManager.create(
            '/路径/到/上下文文件.rhn',
            _inferenceCallback);
    } on RhinoException catch (err) {
        // 处理Rhino初始化错误
    }
}

注意:调用是异步的,因此应该在一个异步块中使用try/catch。

inferenceCallback 参数是一个函数,当你需要执行Rhino做出推理时调用该函数。该函数应接受一个代表推理结果的RhinoInference实例。

void _inferenceCallback(RhinoInference inference) {
    if(inference.isUnderstood!){
        String intent = inference.intent!
        Map<String, String> slots = inference.slots!
        // 添加代码根据推断的意图和槽值采取行动
    }
    else {
        // 添加代码处理不支持的命令
    }
}

Rhino接受以下可选参数:

  • sensitivity: 覆盖默认的推理敏感度。
  • processErrorCallback: 如果在处理音频时遇到问题,则调用此回调。
  • endpointDurationSec: 设置语音命令后的静音时间。
  • requireEndpoint: 表示Rhino是否应在返回推理之前等待静默。
final String accessKey = '{ACCESS_KEY}'; // 从Picovoice控制台(https://console.picovoice.ai/)获得的AccessKey

_rhinoManager = await RhinoManager.create(
    accessCallback
    '/路径/到/上下文文件.rhn',
    _inferenceCallback,
    modelPath: '路径/到/模型文件.pv',
    sensitivity: 0.75,
    endpointDurationSec: 1.5,
    requireEndpoint: false,
    processErrorCallback: _errorCallback);

void _errorCallback(PvError error){
    // 处理错误
}

一旦你实例化了RhinoManager,你可以通过调用process()函数开始音频捕获和意图推理。 一旦通过推理回调返回推理结果,音频捕获停止并且Rhino重置。

try {
    await _rhinoManager.process();
} on RhinoException catch (ex) {
    // 处理音频异常
}

一旦你的应用程序不再使用RhinoManager,确保显式地释放分配给它的资源:

await _rhinoManager.delete();

无需处理音频捕获即可启用RhinoManager的推理。 这是因为它使用我们的flutter_voice_processor插件来捕获音频帧并自动将其传递给语音到意图引擎。

低级API

Rhino 提供对推理引擎的低级访问,适合那些希望将语音到意图集成到现有音频处理管道中的用户。

通过向其静态构造函数create传递上下文文件来创建Rhino

import 'package:rhino/rhino_manager.dart';
import 'package:rhino/rhino_error.dart';

final String accessKey = '{ACCESS_KEY}'; // 从Picovoice控制台(https://console.picovoice.ai/)获得的AccessKey

void createRhino() async {
    try {
        _rhino = await Rhino.create(accessKey, '/路径/到/上下文文件.rhn');
    } on PvError catch (err) {
        // 处理Rhino初始化错误
    }
}

要向Rhino发送音频数据,必须将其帧传递给它的process函数。 每次调用process都会返回一个包含以下变量的RhinoInference实例:

  • isFinalized - 如果Rhino已做出推理,则为true,否则为false。
  • isUnderstood - 如果isFinalized为false,则为null,否则如果Rhino基于上下文理解听到的内容,则为true,否则为false。
  • intent - 如果isUnderstood不为真,则为null,否则为推断出的意图名称。
  • slots - 如果isUnderstood不为真,则为null,否则为推断出的槽键和值的字典。
List<int> buffer = getAudioFrame();

try {
    RhinoInference inference = await _rhino.process(buffer);
    if (inference.isFinalized) {
        if (inference.isUnderstood!) {
            String intent = inference.intent!;
            Map<String, String> = inference.slots!;
            // 添加代码根据推断的意图和槽值采取行动
        }
    }
} on RhinoException catch (error) {
    // 处理错误
}

为了使process正确工作,音频数据必须符合Picovoice所需的音频格式。 所需的音频格式可以通过调用.sampleRate获取所需采样率,通过调用.frameLength获取所需帧大小。 音频必须是单声道且16位线性编码。

最后,一旦不再需要语音到意图引擎,确保显式释放分配给Rhino的资源:

_rhino.delete();

自定义上下文集成

要在你的Flutter应用中添加自定义上下文,首先将.rhn文件添加到项目目录中的assets文件夹。然后在你的pubspec.yaml中添加它们:

flutter:
  assets:
    - assets/上下文.rhn

然后你可以直接将它传递给Rhino的create构造函数:

final String accessKey = '{ACCESS_KEY}'; // 从Picovoice控制台(https://console.picovoice.ai/)获得的AccessKey

String contextAsset = 'assets/上下文.rhn';
try {
    _rhino = await Rhino.create(accessKey, contextAsset);
} on RhinoException catch (err) {
    // 处理Rhino初始化错误
}

更多关于Flutter嵌入式JavaScript引擎插件rhino_flutter的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter嵌入式JavaScript引擎插件rhino_flutter的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


rhino_flutter 是一个 Flutter 插件,允许开发者将 JavaScript 引擎 Rhino 嵌入到 Flutter 应用中。Rhino 是一个由 Mozilla 开发的 JavaScript 引擎,通常用于 Java 应用中执行 JavaScript 代码。通过 rhino_flutter 插件,开发者可以在 Flutter 应用中执行 JavaScript 代码,从而实现跨平台的脚本功能。

使用 rhino_flutter 的步骤

  1. 添加依赖 首先,你需要在 pubspec.yaml 文件中添加 rhino_flutter 插件的依赖。

    dependencies:
      flutter:
        sdk: flutter
      rhino_flutter: ^1.0.0  # 请根据实际版本号填写
    
  2. 安装依赖 运行 flutter pub get 来安装依赖。

    flutter pub get
    
  3. 导入插件 在你的 Dart 文件中导入 rhino_flutter 插件。

    import 'package:rhino_flutter/rhino_flutter.dart';
    
  4. 初始化 Rhino 引擎 在使用 Rhino 引擎之前,你需要先初始化它。

    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await RhinoFlutter.init();
      runApp(MyApp());
    }
    
  5. 执行 JavaScript 代码 你可以使用 RhinoFlutter.eval 方法来执行 JavaScript 代码。

    void executeJavaScript() async {
      String jsCode = '''
        function add(a, b) {
          return a + b;
        }
        add(2, 3);
      ''';
      var result = await RhinoFlutter.eval(jsCode);
      print('Result: $result');  // 输出: Result: 5
    }
    
  6. 处理 JavaScript 和 Dart 之间的通信 你可以通过 RhinoFlutter 插件在 JavaScript 和 Dart 之间传递数据。通常,你可以将数据作为参数传递给 JavaScript 函数,或者从 JavaScript 函数中返回值。

    void communicateWithJavaScript() async {
      String jsCode = '''
        function greet(name) {
          return "Hello, " + name + "!";
        }
      ''';
      await RhinoFlutter.eval(jsCode);
      var result = await RhinoFlutter.callFunction('greet', ['World']);
      print('Result: $result');  // 输出: Result: Hello, World!
    }
    
  7. 异常处理 在执行 JavaScript 代码时,可能会遇到异常。你可以使用 try-catch 块来捕获并处理这些异常。

    void handleJavaScriptError() async {
      String jsCode = '''
        undefinedFunction();
      ''';
      try {
        await RhinoFlutter.eval(jsCode);
      } catch (e) {
        print('JavaScript Error: $e');
      }
    }
    

示例应用

以下是一个简单的 Flutter 应用,展示如何使用 rhino_flutter 插件执行 JavaScript 代码。

import 'package:flutter/material.dart';
import 'package:rhino_flutter/rhino_flutter.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await RhinoFlutter.init();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Rhino Flutter Example')),
        body: Center(
          child: ElevatedButton(
            onPressed: executeJavaScript,
            child: Text('Execute JavaScript'),
          ),
        ),
      ),
    );
  }

  void executeJavaScript() async {
    String jsCode = '''
      function add(a, b) {
        return a + b;
      }
      add(2, 3);
    ''';
    var result = await RhinoFlutter.eval(jsCode);
    print('Result: $result');  // 输出: Result: 5
  }
}
回到顶部