正在显示
17 个修改的文件
包含
513 行增加
和
0 行删除
| @@ -108,6 +108,7 @@ jobs: | @@ -108,6 +108,7 @@ jobs: | ||
| 108 | cp scripts/dart/non-streaming-asr-pubspec.yaml dart-api-examples/non-streaming-asr/pubspec.yaml | 108 | cp scripts/dart/non-streaming-asr-pubspec.yaml dart-api-examples/non-streaming-asr/pubspec.yaml |
| 109 | cp scripts/dart/streaming-asr-pubspec.yaml dart-api-examples/streaming-asr/pubspec.yaml | 109 | cp scripts/dart/streaming-asr-pubspec.yaml dart-api-examples/streaming-asr/pubspec.yaml |
| 110 | cp scripts/dart/tts-pubspec.yaml dart-api-examples/tts/pubspec.yaml | 110 | cp scripts/dart/tts-pubspec.yaml dart-api-examples/tts/pubspec.yaml |
| 111 | + cp scripts/dart/kws-pubspec.yaml dart-api-examples/keyword-spotter/pubspec.yaml | ||
| 111 | cp scripts/dart/sherpa-onnx-pubspec.yaml flutter/sherpa_onnx/pubspec.yaml | 112 | cp scripts/dart/sherpa-onnx-pubspec.yaml flutter/sherpa_onnx/pubspec.yaml |
| 112 | 113 | ||
| 113 | .github/scripts/test-dart.sh | 114 | .github/scripts/test-dart.sh |
| 1 | !run*.sh | 1 | !run*.sh |
| 2 | +# See https://www.dartlang.org/guides/libraries/private-files | ||
| 3 | + | ||
| 4 | +# Files and directories created by pub | ||
| 5 | +.dart_tool/ | ||
| 6 | +.packages | ||
| 7 | +build/ | ||
| 8 | +# If you're building an application, you may want to check-in your pubspec.lock | ||
| 9 | +pubspec.lock | ||
| 10 | + | ||
| 11 | +# Directory created by dartdoc | ||
| 12 | +# If you don't generate documentation locally you can remove this line. | ||
| 13 | +doc/api/ | ||
| 14 | + | ||
| 15 | +# dotenv environment variables file | ||
| 16 | +.env* | ||
| 17 | + | ||
| 18 | +# Avoid committing generated Javascript files: | ||
| 19 | +*.dart.js | ||
| 20 | +*.info.json # Produced by the --dump-info flag. | ||
| 21 | +*.js # When generated by dart2js. Don't specify *.js if your | ||
| 22 | + # project includes source files written in JavaScript. | ||
| 23 | +*.js_ | ||
| 24 | +*.js.deps | ||
| 25 | +*.js.map | ||
| 26 | + | ||
| 27 | +.flutter-plugins | ||
| 28 | +.flutter-plugins-dependencies |
dart-api-examples/keyword-spotter/.gitignore
0 → 100644
dart-api-examples/keyword-spotter/README.md
0 → 100644
| 1 | +# This file configures the static analysis results for your project (errors, | ||
| 2 | +# warnings, and lints). | ||
| 3 | +# | ||
| 4 | +# This enables the 'recommended' set of lints from `package:lints`. | ||
| 5 | +# This set helps identify many issues that may lead to problems when running | ||
| 6 | +# or consuming Dart code, and enforces writing Dart using a single, idiomatic | ||
| 7 | +# style and format. | ||
| 8 | +# | ||
| 9 | +# If you want a smaller set of lints you can change this to specify | ||
| 10 | +# 'package:lints/core.yaml'. These are just the most critical lints | ||
| 11 | +# (the recommended set includes the core lints). | ||
| 12 | +# The core lints are also what is used by pub.dev for scoring packages. | ||
| 13 | + | ||
| 14 | +include: package:lints/recommended.yaml | ||
| 15 | + | ||
| 16 | +# Uncomment the following section to specify additional rules. | ||
| 17 | + | ||
| 18 | +# linter: | ||
| 19 | +# rules: | ||
| 20 | +# - camel_case_types | ||
| 21 | + | ||
| 22 | +# analyzer: | ||
| 23 | +# exclude: | ||
| 24 | +# - path/to/excluded/files/** | ||
| 25 | + | ||
| 26 | +# For more information about the core and recommended set of lints, see | ||
| 27 | +# https://dart.dev/go/core-lints | ||
| 28 | + | ||
| 29 | +# For additional information about configuring this file, see | ||
| 30 | +# https://dart.dev/guides/language/analysis-options |
| 1 | +../../vad/bin/init.dart |
| 1 | +// Copyright (c) 2024 Xiaomi Corporation | ||
| 2 | +import 'dart:io'; | ||
| 3 | +import 'dart:typed_data'; | ||
| 4 | + | ||
| 5 | +import 'package:args/args.dart'; | ||
| 6 | +import 'package:sherpa_onnx/sherpa_onnx.dart' as sherpa_onnx; | ||
| 7 | + | ||
| 8 | +import './init.dart'; | ||
| 9 | + | ||
| 10 | +void main(List<String> arguments) async { | ||
| 11 | + await initSherpaOnnx(); | ||
| 12 | + | ||
| 13 | + final parser = ArgParser() | ||
| 14 | + ..addOption('encoder', help: 'Path to the encoder model') | ||
| 15 | + ..addOption('decoder', help: 'Path to decoder model') | ||
| 16 | + ..addOption('joiner', help: 'Path to joiner model') | ||
| 17 | + ..addOption('tokens', help: 'Path to tokens.txt') | ||
| 18 | + ..addOption('keywords-file', help: 'Path to keywords.txt') | ||
| 19 | + ..addOption('input-wav', help: 'Path to input.wav to transcribe'); | ||
| 20 | + | ||
| 21 | + final res = parser.parse(arguments); | ||
| 22 | + if (res['encoder'] == null || | ||
| 23 | + res['decoder'] == null || | ||
| 24 | + res['joiner'] == null || | ||
| 25 | + res['tokens'] == null || | ||
| 26 | + res['keywords-file'] == null || | ||
| 27 | + res['input-wav'] == null) { | ||
| 28 | + print(parser.usage); | ||
| 29 | + exit(1); | ||
| 30 | + } | ||
| 31 | + | ||
| 32 | + final encoder = res['encoder'] as String; | ||
| 33 | + final decoder = res['decoder'] as String; | ||
| 34 | + final joiner = res['joiner'] as String; | ||
| 35 | + final tokens = res['tokens'] as String; | ||
| 36 | + final keywordsFile = res['keywords-file'] as String; | ||
| 37 | + final inputWav = res['input-wav'] as String; | ||
| 38 | + | ||
| 39 | + final transducer = sherpa_onnx.OnlineTransducerModelConfig( | ||
| 40 | + encoder: encoder, | ||
| 41 | + decoder: decoder, | ||
| 42 | + joiner: joiner, | ||
| 43 | + ); | ||
| 44 | + | ||
| 45 | + final modelConfig = sherpa_onnx.OnlineModelConfig( | ||
| 46 | + transducer: transducer, | ||
| 47 | + tokens: tokens, | ||
| 48 | + debug: true, | ||
| 49 | + numThreads: 1, | ||
| 50 | + ); | ||
| 51 | + final config = sherpa_onnx.KeywordSpotterConfig( | ||
| 52 | + model: modelConfig, | ||
| 53 | + keywordsFile: keywordsFile, | ||
| 54 | + ); | ||
| 55 | + final spotter = sherpa_onnx.KeywordSpotter(config); | ||
| 56 | + | ||
| 57 | + final waveData = sherpa_onnx.readWave(inputWav); | ||
| 58 | + var stream = spotter.createStream(); | ||
| 59 | + | ||
| 60 | + // simulate streaming. You can choose an arbitrary chunk size. | ||
| 61 | + // chunkSize of a single sample is also ok, i.e, chunkSize = 1 | ||
| 62 | + final chunkSize = 1600; // 0.1 second for 16kHz | ||
| 63 | + final numChunks = waveData.samples.length ~/ chunkSize; | ||
| 64 | + | ||
| 65 | + for (int i = 0; i != numChunks; ++i) { | ||
| 66 | + int start = i * chunkSize; | ||
| 67 | + stream.acceptWaveform( | ||
| 68 | + samples: | ||
| 69 | + Float32List.sublistView(waveData.samples, start, start + chunkSize), | ||
| 70 | + sampleRate: waveData.sampleRate, | ||
| 71 | + ); | ||
| 72 | + while (spotter.isReady(stream)) { | ||
| 73 | + spotter.decode(stream); | ||
| 74 | + final result = spotter.getResult(stream); | ||
| 75 | + if (result.keyword != '') { | ||
| 76 | + print('Detected: ${result.keyword}'); | ||
| 77 | + } | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + | ||
| 81 | + // 0.5 seconds, assume sampleRate is 16kHz | ||
| 82 | + final tailPaddings = Float32List(8000); | ||
| 83 | + stream.acceptWaveform( | ||
| 84 | + samples: tailPaddings, | ||
| 85 | + sampleRate: waveData.sampleRate, | ||
| 86 | + ); | ||
| 87 | + | ||
| 88 | + while (spotter.isReady(stream)) { | ||
| 89 | + spotter.decode(stream); | ||
| 90 | + final result = spotter.getResult(stream); | ||
| 91 | + if (result.keyword != '') { | ||
| 92 | + print('Detected: ${result.keyword}'); | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + stream.free(); | ||
| 97 | + spotter.free(); | ||
| 98 | +} |
| 1 | +name: keyword_spotter | ||
| 2 | + | ||
| 3 | +description: > | ||
| 4 | + This example demonstrates how to use the Dart API for keyword spotting | ||
| 5 | + | ||
| 6 | +version: 1.0.0 | ||
| 7 | + | ||
| 8 | +environment: | ||
| 9 | + sdk: ^3.4.0 | ||
| 10 | + | ||
| 11 | +dependencies: | ||
| 12 | + sherpa_onnx: ^1.10.17 | ||
| 13 | + # sherpa_onnx: | ||
| 14 | + # path: ../../flutter/sherpa_onnx | ||
| 15 | + path: ^1.9.0 | ||
| 16 | + args: ^2.5.0 | ||
| 17 | + | ||
| 18 | +dev_dependencies: | ||
| 19 | + lints: ^3.0.0 |
dart-api-examples/keyword-spotter/run-zh.sh
0 → 100755
| 1 | +#!/usr/bin/env bash | ||
| 2 | + | ||
| 3 | +set -ex | ||
| 4 | + | ||
| 5 | +dart pub get | ||
| 6 | + | ||
| 7 | +if [ ! -f ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/tokens.txt ]; then | ||
| 8 | + curl -SL -O https://github.com/k2-fsa/sherpa-onnx/releases/download/kws-models/sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01.tar.bz2 | ||
| 9 | + tar xvf sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01.tar.bz2 | ||
| 10 | + rm sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01.tar.bz2 | ||
| 11 | +fi | ||
| 12 | + | ||
| 13 | +dart run \ | ||
| 14 | + ./bin/zipformer-transducer.dart \ | ||
| 15 | + --encoder ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/encoder-epoch-12-avg-2-chunk-16-left-64.onnx \ | ||
| 16 | + --decoder ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/decoder-epoch-12-avg-2-chunk-16-left-64.onnx \ | ||
| 17 | + --joiner ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/joiner-epoch-12-avg-2-chunk-16-left-64.onnx \ | ||
| 18 | + --tokens ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/tokens.txt \ | ||
| 19 | + --keywords-file ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/test_wavs/test_keywords.txt \ | ||
| 20 | + --input-wav ./sherpa-onnx-kws-zipformer-wenetspeech-3.3M-2024-01-01/test_wavs/3.wav | ||
| 21 | + |
| @@ -3,6 +3,7 @@ import 'dart:io'; | @@ -3,6 +3,7 @@ import 'dart:io'; | ||
| 3 | import 'dart:ffi'; | 3 | import 'dart:ffi'; |
| 4 | 4 | ||
| 5 | export 'src/feature_config.dart'; | 5 | export 'src/feature_config.dart'; |
| 6 | +export 'src/keyword_spotter.dart'; | ||
| 6 | export 'src/offline_recognizer.dart'; | 7 | export 'src/offline_recognizer.dart'; |
| 7 | export 'src/offline_stream.dart'; | 8 | export 'src/offline_stream.dart'; |
| 8 | export 'src/online_recognizer.dart'; | 9 | export 'src/online_recognizer.dart'; |
| 1 | +// Copyright (c) 2024 Xiaomi Corporation | ||
| 2 | +import 'dart:convert'; | ||
| 3 | +import 'dart:ffi'; | ||
| 4 | + | ||
| 5 | +import 'package:ffi/ffi.dart'; | ||
| 6 | + | ||
| 7 | +import './feature_config.dart'; | ||
| 8 | +import './online_stream.dart'; | ||
| 9 | +import './online_recognizer.dart'; | ||
| 10 | +import './sherpa_onnx_bindings.dart'; | ||
| 11 | +import './utils.dart'; | ||
| 12 | + | ||
| 13 | +class KeywordSpotterConfig { | ||
| 14 | + const KeywordSpotterConfig({ | ||
| 15 | + this.feat = const FeatureConfig(), | ||
| 16 | + required this.model, | ||
| 17 | + this.maxActivePaths = 4, | ||
| 18 | + this.numTrailingBlanks = 1, | ||
| 19 | + this.keywordsScore = 1.0, | ||
| 20 | + this.keywordsThreshold = 0.25, | ||
| 21 | + this.keywordsFile = '', | ||
| 22 | + }); | ||
| 23 | + | ||
| 24 | + @override | ||
| 25 | + String toString() { | ||
| 26 | + return 'KeywordSpotterConfig(feat: $feat, model: $model, maxActivePaths: $maxActivePaths, numTrailingBlanks: $numTrailingBlanks, keywordsScore: $keywordsScore, keywordsThreshold: $keywordsThreshold, keywordsFile: $keywordsFile)'; | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + final FeatureConfig feat; | ||
| 30 | + final OnlineModelConfig model; | ||
| 31 | + | ||
| 32 | + final int maxActivePaths; | ||
| 33 | + final int numTrailingBlanks; | ||
| 34 | + | ||
| 35 | + final double keywordsScore; | ||
| 36 | + final double keywordsThreshold; | ||
| 37 | + final String keywordsFile; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +class KeywordResult { | ||
| 41 | + KeywordResult({required this.keyword}); | ||
| 42 | + | ||
| 43 | + @override | ||
| 44 | + String toString() { | ||
| 45 | + return 'KeywordResult(keyword: $keyword)'; | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + final String keyword; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +class KeywordSpotter { | ||
| 52 | + KeywordSpotter._({required this.ptr, required this.config}); | ||
| 53 | + | ||
| 54 | + /// The user is responsible to call the OnlineRecognizer.free() | ||
| 55 | + /// method of the returned instance to avoid memory leak. | ||
| 56 | + factory KeywordSpotter(KeywordSpotterConfig config) { | ||
| 57 | + final c = calloc<SherpaOnnxKeywordSpotterConfig>(); | ||
| 58 | + c.ref.feat.sampleRate = config.feat.sampleRate; | ||
| 59 | + c.ref.feat.featureDim = config.feat.featureDim; | ||
| 60 | + | ||
| 61 | + // transducer | ||
| 62 | + c.ref.model.transducer.encoder = | ||
| 63 | + config.model.transducer.encoder.toNativeUtf8(); | ||
| 64 | + c.ref.model.transducer.decoder = | ||
| 65 | + config.model.transducer.decoder.toNativeUtf8(); | ||
| 66 | + c.ref.model.transducer.joiner = | ||
| 67 | + config.model.transducer.joiner.toNativeUtf8(); | ||
| 68 | + | ||
| 69 | + // paraformer | ||
| 70 | + c.ref.model.paraformer.encoder = | ||
| 71 | + config.model.paraformer.encoder.toNativeUtf8(); | ||
| 72 | + c.ref.model.paraformer.decoder = | ||
| 73 | + config.model.paraformer.decoder.toNativeUtf8(); | ||
| 74 | + | ||
| 75 | + // zipformer2Ctc | ||
| 76 | + c.ref.model.zipformer2Ctc.model = | ||
| 77 | + config.model.zipformer2Ctc.model.toNativeUtf8(); | ||
| 78 | + | ||
| 79 | + c.ref.model.tokens = config.model.tokens.toNativeUtf8(); | ||
| 80 | + c.ref.model.numThreads = config.model.numThreads; | ||
| 81 | + c.ref.model.provider = config.model.provider.toNativeUtf8(); | ||
| 82 | + c.ref.model.debug = config.model.debug ? 1 : 0; | ||
| 83 | + c.ref.model.modelType = config.model.modelType.toNativeUtf8(); | ||
| 84 | + c.ref.model.modelingUnit = config.model.modelingUnit.toNativeUtf8(); | ||
| 85 | + c.ref.model.bpeVocab = config.model.bpeVocab.toNativeUtf8(); | ||
| 86 | + | ||
| 87 | + c.ref.maxActivePaths = config.maxActivePaths; | ||
| 88 | + c.ref.numTrailingBlanks = config.numTrailingBlanks; | ||
| 89 | + c.ref.keywordsScore = config.keywordsScore; | ||
| 90 | + c.ref.keywordsThreshold = config.keywordsThreshold; | ||
| 91 | + c.ref.keywordsFile = config.keywordsFile.toNativeUtf8(); | ||
| 92 | + | ||
| 93 | + final ptr = SherpaOnnxBindings.createKeywordSpotter?.call(c) ?? nullptr; | ||
| 94 | + | ||
| 95 | + calloc.free(c.ref.keywordsFile); | ||
| 96 | + calloc.free(c.ref.model.bpeVocab); | ||
| 97 | + calloc.free(c.ref.model.modelingUnit); | ||
| 98 | + calloc.free(c.ref.model.modelType); | ||
| 99 | + calloc.free(c.ref.model.provider); | ||
| 100 | + calloc.free(c.ref.model.tokens); | ||
| 101 | + calloc.free(c.ref.model.zipformer2Ctc.model); | ||
| 102 | + calloc.free(c.ref.model.paraformer.encoder); | ||
| 103 | + calloc.free(c.ref.model.paraformer.decoder); | ||
| 104 | + | ||
| 105 | + calloc.free(c.ref.model.transducer.encoder); | ||
| 106 | + calloc.free(c.ref.model.transducer.decoder); | ||
| 107 | + calloc.free(c.ref.model.transducer.joiner); | ||
| 108 | + calloc.free(c); | ||
| 109 | + | ||
| 110 | + return KeywordSpotter._(ptr: ptr, config: config); | ||
| 111 | + } | ||
| 112 | + | ||
| 113 | + void free() { | ||
| 114 | + SherpaOnnxBindings.destroyKeywordSpotter?.call(ptr); | ||
| 115 | + ptr = nullptr; | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + /// The user has to invoke stream.free() on the returned instance | ||
| 119 | + /// to avoid memory leak | ||
| 120 | + OnlineStream createStream({String keywords = ''}) { | ||
| 121 | + if (keywords == '') { | ||
| 122 | + final p = SherpaOnnxBindings.createKeywordStream?.call(ptr) ?? nullptr; | ||
| 123 | + return OnlineStream(ptr: p); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + final utf8 = keywords.toNativeUtf8(); | ||
| 127 | + final p = | ||
| 128 | + SherpaOnnxBindings.createKeywordStreamWithKeywords?.call(ptr, utf8) ?? | ||
| 129 | + nullptr; | ||
| 130 | + calloc.free(utf8); | ||
| 131 | + return OnlineStream(ptr: p); | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + bool isReady(OnlineStream stream) { | ||
| 135 | + int ready = | ||
| 136 | + SherpaOnnxBindings.isKeywordStreamReady?.call(ptr, stream.ptr) ?? 0; | ||
| 137 | + | ||
| 138 | + return ready == 1; | ||
| 139 | + } | ||
| 140 | + | ||
| 141 | + KeywordResult getResult(OnlineStream stream) { | ||
| 142 | + final json = | ||
| 143 | + SherpaOnnxBindings.getKeywordResultAsJson?.call(ptr, stream.ptr) ?? | ||
| 144 | + nullptr; | ||
| 145 | + if (json == nullptr) { | ||
| 146 | + return KeywordResult(keyword: ''); | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + final parsedJson = jsonDecode(toDartString(json)); | ||
| 150 | + | ||
| 151 | + SherpaOnnxBindings.freeKeywordResultJson?.call(json); | ||
| 152 | + | ||
| 153 | + return KeywordResult( | ||
| 154 | + keyword: parsedJson['keyword'], | ||
| 155 | + ); | ||
| 156 | + } | ||
| 157 | + | ||
| 158 | + void decode(OnlineStream stream) { | ||
| 159 | + SherpaOnnxBindings.decodeKeywordStream?.call(ptr, stream.ptr); | ||
| 160 | + } | ||
| 161 | + | ||
| 162 | + Pointer<SherpaOnnxKeywordSpotter> ptr; | ||
| 163 | + KeywordSpotterConfig config; | ||
| 164 | +} |
| @@ -283,6 +283,28 @@ final class SherpaOnnxSpeakerEmbeddingExtractorConfig extends Struct { | @@ -283,6 +283,28 @@ final class SherpaOnnxSpeakerEmbeddingExtractorConfig extends Struct { | ||
| 283 | external Pointer<Utf8> provider; | 283 | external Pointer<Utf8> provider; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | +final class SherpaOnnxKeywordSpotterConfig extends Struct { | ||
| 287 | + external SherpaOnnxFeatureConfig feat; | ||
| 288 | + | ||
| 289 | + external SherpaOnnxOnlineModelConfig model; | ||
| 290 | + | ||
| 291 | + @Int32() | ||
| 292 | + external int maxActivePaths; | ||
| 293 | + | ||
| 294 | + @Int32() | ||
| 295 | + external int numTrailingBlanks; | ||
| 296 | + | ||
| 297 | + @Float() | ||
| 298 | + external double keywordsScore; | ||
| 299 | + | ||
| 300 | + @Float() | ||
| 301 | + external double keywordsThreshold; | ||
| 302 | + | ||
| 303 | + external Pointer<Utf8> keywordsFile; | ||
| 304 | +} | ||
| 305 | + | ||
| 306 | +final class SherpaOnnxKeywordSpotter extends Opaque {} | ||
| 307 | + | ||
| 286 | final class SherpaOnnxOfflineTts extends Opaque {} | 308 | final class SherpaOnnxOfflineTts extends Opaque {} |
| 287 | 309 | ||
| 288 | final class SherpaOnnxCircularBuffer extends Opaque {} | 310 | final class SherpaOnnxCircularBuffer extends Opaque {} |
| @@ -301,6 +323,48 @@ final class SherpaOnnxSpeakerEmbeddingExtractor extends Opaque {} | @@ -301,6 +323,48 @@ final class SherpaOnnxSpeakerEmbeddingExtractor extends Opaque {} | ||
| 301 | 323 | ||
| 302 | final class SherpaOnnxSpeakerEmbeddingManager extends Opaque {} | 324 | final class SherpaOnnxSpeakerEmbeddingManager extends Opaque {} |
| 303 | 325 | ||
| 326 | +typedef CreateKeywordSpotterNative = Pointer<SherpaOnnxKeywordSpotter> Function( | ||
| 327 | + Pointer<SherpaOnnxKeywordSpotterConfig>); | ||
| 328 | + | ||
| 329 | +typedef CreateKeywordSpotter = CreateKeywordSpotterNative; | ||
| 330 | + | ||
| 331 | +typedef DestroyKeywordSpotterNative = Void Function( | ||
| 332 | + Pointer<SherpaOnnxKeywordSpotter>); | ||
| 333 | + | ||
| 334 | +typedef DestroyKeywordSpotter = void Function( | ||
| 335 | + Pointer<SherpaOnnxKeywordSpotter>); | ||
| 336 | + | ||
| 337 | +typedef CreateKeywordStreamNative = Pointer<SherpaOnnxOnlineStream> Function( | ||
| 338 | + Pointer<SherpaOnnxKeywordSpotter>); | ||
| 339 | + | ||
| 340 | +typedef CreateKeywordStream = CreateKeywordStreamNative; | ||
| 341 | + | ||
| 342 | +typedef CreateKeywordStreamWithKeywordsNative = Pointer<SherpaOnnxOnlineStream> | ||
| 343 | + Function(Pointer<SherpaOnnxKeywordSpotter>, Pointer<Utf8>); | ||
| 344 | + | ||
| 345 | +typedef CreateKeywordStreamWithKeywords = CreateKeywordStreamWithKeywordsNative; | ||
| 346 | + | ||
| 347 | +typedef IsKeywordStreamReadyNative = Int32 Function( | ||
| 348 | + Pointer<SherpaOnnxKeywordSpotter>, Pointer<SherpaOnnxOnlineStream>); | ||
| 349 | + | ||
| 350 | +typedef IsKeywordStreamReady = int Function( | ||
| 351 | + Pointer<SherpaOnnxKeywordSpotter>, Pointer<SherpaOnnxOnlineStream>); | ||
| 352 | + | ||
| 353 | +typedef DecodeKeywordStreamNative = Void Function( | ||
| 354 | + Pointer<SherpaOnnxKeywordSpotter>, Pointer<SherpaOnnxOnlineStream>); | ||
| 355 | + | ||
| 356 | +typedef DecodeKeywordStream = void Function( | ||
| 357 | + Pointer<SherpaOnnxKeywordSpotter>, Pointer<SherpaOnnxOnlineStream>); | ||
| 358 | + | ||
| 359 | +typedef GetKeywordResultAsJsonNative = Pointer<Utf8> Function( | ||
| 360 | + Pointer<SherpaOnnxKeywordSpotter>, Pointer<SherpaOnnxOnlineStream>); | ||
| 361 | + | ||
| 362 | +typedef GetKeywordResultAsJson = GetKeywordResultAsJsonNative; | ||
| 363 | + | ||
| 364 | +typedef FreeKeywordResultJsonNative = Void Function(Pointer<Utf8>); | ||
| 365 | + | ||
| 366 | +typedef FreeKeywordResultJson = void Function(Pointer<Utf8>); | ||
| 367 | + | ||
| 304 | typedef SherpaOnnxCreateOfflineTtsNative = Pointer<SherpaOnnxOfflineTts> | 368 | typedef SherpaOnnxCreateOfflineTtsNative = Pointer<SherpaOnnxOfflineTts> |
| 305 | Function(Pointer<SherpaOnnxOfflineTtsConfig>); | 369 | Function(Pointer<SherpaOnnxOfflineTtsConfig>); |
| 306 | 370 | ||
| @@ -735,6 +799,15 @@ typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>); | @@ -735,6 +799,15 @@ typedef SherpaOnnxFreeWaveNative = Void Function(Pointer<SherpaOnnxWave>); | ||
| 735 | typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>); | 799 | typedef SherpaOnnxFreeWave = void Function(Pointer<SherpaOnnxWave>); |
| 736 | 800 | ||
| 737 | class SherpaOnnxBindings { | 801 | class SherpaOnnxBindings { |
| 802 | + static CreateKeywordSpotter? createKeywordSpotter; | ||
| 803 | + static DestroyKeywordSpotter? destroyKeywordSpotter; | ||
| 804 | + static CreateKeywordStream? createKeywordStream; | ||
| 805 | + static CreateKeywordStreamWithKeywords? createKeywordStreamWithKeywords; | ||
| 806 | + static IsKeywordStreamReady? isKeywordStreamReady; | ||
| 807 | + static DecodeKeywordStream? decodeKeywordStream; | ||
| 808 | + static GetKeywordResultAsJson? getKeywordResultAsJson; | ||
| 809 | + static FreeKeywordResultJson? freeKeywordResultJson; | ||
| 810 | + | ||
| 738 | static SherpaOnnxCreateOfflineTts? createOfflineTts; | 811 | static SherpaOnnxCreateOfflineTts? createOfflineTts; |
| 739 | static SherpaOnnxDestroyOfflineTts? destroyOfflineTts; | 812 | static SherpaOnnxDestroyOfflineTts? destroyOfflineTts; |
| 740 | static SherpaOnnxOfflineTtsSampleRate? offlineTtsSampleRate; | 813 | static SherpaOnnxOfflineTtsSampleRate? offlineTtsSampleRate; |
| @@ -879,6 +952,46 @@ class SherpaOnnxBindings { | @@ -879,6 +952,46 @@ class SherpaOnnxBindings { | ||
| 879 | static SherpaOnnxFreeWave? freeWave; | 952 | static SherpaOnnxFreeWave? freeWave; |
| 880 | 953 | ||
| 881 | static void init(DynamicLibrary dynamicLibrary) { | 954 | static void init(DynamicLibrary dynamicLibrary) { |
| 955 | + createKeywordSpotter ??= dynamicLibrary | ||
| 956 | + .lookup<NativeFunction<CreateKeywordSpotterNative>>( | ||
| 957 | + 'CreateKeywordSpotter') | ||
| 958 | + .asFunction(); | ||
| 959 | + | ||
| 960 | + destroyKeywordSpotter ??= dynamicLibrary | ||
| 961 | + .lookup<NativeFunction<DestroyKeywordSpotterNative>>( | ||
| 962 | + 'DestroyKeywordSpotter') | ||
| 963 | + .asFunction(); | ||
| 964 | + | ||
| 965 | + createKeywordStream ??= dynamicLibrary | ||
| 966 | + .lookup<NativeFunction<CreateKeywordStreamNative>>( | ||
| 967 | + 'CreateKeywordStream') | ||
| 968 | + .asFunction(); | ||
| 969 | + | ||
| 970 | + createKeywordStreamWithKeywords ??= dynamicLibrary | ||
| 971 | + .lookup<NativeFunction<CreateKeywordStreamWithKeywordsNative>>( | ||
| 972 | + 'CreateKeywordStreamWithKeywords') | ||
| 973 | + .asFunction(); | ||
| 974 | + | ||
| 975 | + isKeywordStreamReady ??= dynamicLibrary | ||
| 976 | + .lookup<NativeFunction<IsKeywordStreamReadyNative>>( | ||
| 977 | + 'IsKeywordStreamReady') | ||
| 978 | + .asFunction(); | ||
| 979 | + | ||
| 980 | + decodeKeywordStream ??= dynamicLibrary | ||
| 981 | + .lookup<NativeFunction<DecodeKeywordStreamNative>>( | ||
| 982 | + 'DecodeKeywordStream') | ||
| 983 | + .asFunction(); | ||
| 984 | + | ||
| 985 | + getKeywordResultAsJson ??= dynamicLibrary | ||
| 986 | + .lookup<NativeFunction<GetKeywordResultAsJsonNative>>( | ||
| 987 | + 'GetKeywordResultAsJson') | ||
| 988 | + .asFunction(); | ||
| 989 | + | ||
| 990 | + freeKeywordResultJson ??= dynamicLibrary | ||
| 991 | + .lookup<NativeFunction<FreeKeywordResultJsonNative>>( | ||
| 992 | + 'FreeKeywordResultJson') | ||
| 993 | + .asFunction(); | ||
| 994 | + | ||
| 882 | createOfflineTts ??= dynamicLibrary | 995 | createOfflineTts ??= dynamicLibrary |
| 883 | .lookup<NativeFunction<SherpaOnnxCreateOfflineTtsNative>>( | 996 | .lookup<NativeFunction<SherpaOnnxCreateOfflineTtsNative>>( |
| 884 | 'SherpaOnnxCreateOfflineTts') | 997 | 'SherpaOnnxCreateOfflineTts') |
| @@ -31,15 +31,19 @@ dependencies: | @@ -31,15 +31,19 @@ dependencies: | ||
| 31 | sdk: flutter | 31 | sdk: flutter |
| 32 | 32 | ||
| 33 | sherpa_onnx_android: ^1.10.17 | 33 | sherpa_onnx_android: ^1.10.17 |
| 34 | + # sherpa_onnx_android: | ||
| 34 | # path: ../sherpa_onnx_android | 35 | # path: ../sherpa_onnx_android |
| 35 | 36 | ||
| 36 | sherpa_onnx_macos: ^1.10.17 | 37 | sherpa_onnx_macos: ^1.10.17 |
| 38 | + # sherpa_onnx_macos: | ||
| 37 | # path: ../sherpa_onnx_macos | 39 | # path: ../sherpa_onnx_macos |
| 38 | 40 | ||
| 39 | sherpa_onnx_linux: ^1.10.17 | 41 | sherpa_onnx_linux: ^1.10.17 |
| 42 | + # sherpa_onnx_linux: | ||
| 40 | # path: ../sherpa_onnx_linux | 43 | # path: ../sherpa_onnx_linux |
| 41 | # | 44 | # |
| 42 | sherpa_onnx_windows: ^1.10.17 | 45 | sherpa_onnx_windows: ^1.10.17 |
| 46 | + # sherpa_onnx_windows: | ||
| 43 | # path: ../sherpa_onnx_windows | 47 | # path: ../sherpa_onnx_windows |
| 44 | 48 | ||
| 45 | sherpa_onnx_ios: ^1.10.17 | 49 | sherpa_onnx_ios: ^1.10.17 |
scripts/dart/kws-pubspec.yaml
0 → 100644
| 1 | +name: keyword_spotter | ||
| 2 | + | ||
| 3 | +description: > | ||
| 4 | + This example demonstrates how to use the Dart API for keyword spotting | ||
| 5 | + | ||
| 6 | +version: 1.0.0 | ||
| 7 | + | ||
| 8 | +environment: | ||
| 9 | + sdk: ^3.4.0 | ||
| 10 | + | ||
| 11 | +dependencies: | ||
| 12 | + # sherpa_onnx: ^1.10.17 | ||
| 13 | + sherpa_onnx: | ||
| 14 | + path: ../../flutter/sherpa_onnx | ||
| 15 | + path: ^1.9.0 | ||
| 16 | + args: ^2.5.0 | ||
| 17 | + | ||
| 18 | +dev_dependencies: | ||
| 19 | + lints: ^3.0.0 |
-
请 注册 或 登录 后发表评论