asr_lib 0.3.0
asr_lib: ^0.3.0 copied to clipboard
On-device speech recognition for Flutter powered by sherpa-onnx.
example/example.md
sherpa-asr 使用示例 #
1. 基础用法 — 低层级 API #
import 'package:asr_lib/asr_lib.dart';
final asr = AsrLib();
// 监听状态变化
asr.stateStream.listen((state) {
print('状态: $state');
});
// 监听识别结果
asr.resultStream.listen((result) {
print('识别结果: ${result.text}');
});
// 监听下载进度
asr.progressStream.listen((progress) {
print('${progress.fileName}: ${progress.percent}%');
});
// 检查模型是否已下载
final downloaded = await asr.isModelDownloaded();
if (!downloaded) {
// 下载 funasr-nano 模型
await asr.downloadModel();
// 或下载 SenseVoice 模型:
// await asr.downloadModel(urls: AsrConfig.senseVoiceDownloadUrls);
}
// 初始化引擎(加载 VAD 和 ASR 模型)
await asr.initialize();
// 开始录音(自动 VAD + 识别)
asr.startRecording();
// 停止录音
asr.stopRecording();
// 释放资源
asr.release();
2. 全局服务 — AsrRegistry #
import 'package:asr_lib/asr_lib.dart';
import 'package:asr_lib/asr_registry.dart';
import 'package:asr_lib/asr_permissions.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 应用启动时预初始化(不阻塞 UI)
AsrRegistry.instance.preInitialize();
runApp(MyApp());
}
// 在任意页面使用
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async {
// 请求麦克风权限
final granted = await AsrPermissions.requestMicrophone();
if (!granted) return;
// 开始录音
AsrRegistry.instance.startRecording();
},
child: Text('录音'),
);
}
}
3. 自定义配置 #
import 'package:asr_lib/asr_lib.dart';
final config = AsrConfig(
sampleRate: 16000,
enableVad: true,
vadThreshold: 0.5,
vadMinSilenceDuration: 0.25,
vadMinSpeechDuration: 0.5,
modelType: 'zipformer_ctc', // zipformer_ctc | sense_voice | paraformer
decodingMethod: 'greedy_search',
numThreads: 2,
);
final asr = AsrLib();
await asr.initialize(config: config);
asr.startRecording();
4. UI 组件 #
import 'package:asr_lib/ui/asr_button.dart';
import 'package:asr_lib/ui/asr_overlay.dart';
// 长按录音按钮
VoiceRecordButton(
themeColor: Colors.blue,
maxDuration: 10,
onResult: (text) => print('最终结果: $text'),
onPartialResult: (text) => print('中间结果: $text'),
onError: (msg) => print('错误: $msg'),
)
// 全屏录音弹窗
final result = await showVoiceRecordOverlay(
context: context,
themeColor: Theme.of(context).primaryColor,
maxDuration: 10,
);
if (result != null && result.isNotEmpty) {
print('识别结果: $result');
}
5. 状态管理完整示例 #
import 'package:flutter/material.dart';
import 'package:asr_lib/asr_lib.dart';
import 'package:asr_lib/asr_permissions.dart';
class AsrExample extends StatefulWidget {
@override
State<AsrExample> createState() => _AsrExampleState();
}
class _AsrExampleState extends State<AsrExample> {
final AsrLib _asr = AsrLib();
String _result = '';
bool _isReady = false;
@override
void initState() {
super.initState();
_asr.stateStream.listen((state) {
setState(() => _isReady = state == AsrState.ready);
});
_asr.resultStream.listen((result) {
if (result.text.isNotEmpty) {
setState(() => _result = '${result.text}\n$_result');
}
});
_initialize();
}
Future<void> _initialize() async {
if (!await _asr.isModelDownloaded()) {
await _asr.downloadModel();
}
await _asr.initialize();
}
@override
void dispose() {
_asr.release();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('ASR 示例')),
body: Column(
children: [
Expanded(child: Text(_result)),
Row(
children: [
if (_isReady)
IconButton(
onPressed: () async {
if (await AsrPermissions.requestMicrophone()) {
_asr.startRecording();
}
},
icon: const Icon(Icons.mic),
),
if (_isReady)
IconButton(
onPressed: () => _asr.stopRecording(),
icon: const Icon(Icons.stop),
),
],
),
],
),
);
}
}
6. 模型下载 #
// 默认 funasr-nano (zipformer_ctc)
await _asr.downloadModel();
// SenseVoice 模型
await _asr.downloadModel(urls: AsrConfig.senseVoiceDownloadUrls);
// 自定义模型 URL
await _asr.downloadModel(urls: {
'model.int8.onnx': 'https://example.com/model.onnx',
'tokens.txt': 'https://example.com/tokens.txt',
});