Flutter隐私保护通讯插件whisper_flutter_new的使用
Flutter隐私保护通讯插件whisper_flutter_new的使用
简介
whisper_flutter_new
是一个基于 whisper.cpp
模型实现的隐私保护通讯插件,支持iOS和Android平台。该插件可以用于音频转录和翻译。
主要特性
- 支持AGP8+。
- 支持Android 5.0+、iOS 13+ 和 MacOS 11+。
- 性能优化且运行速度快。
支持的模型
- tiny
- base
- small
- medium
- large-v1
- large-v2
推荐模型
- base
- small
- medium
测试设备
- Android: Google Pixel 7 Pro
- iOS: M1 iOS 模拟器
- MacOS: M1 MacBook Pro & M2 Mac Mini
安装库
在 pubspec.yaml
文件中添加依赖:
flutter pub add whisper_flutter_new
导入库
在 Dart 文件中导入:
import 'package:whisper_flutter_new/whisper_flutter_new.dart';
快速开始
以下是一个简单的示例,展示如何使用 whisper_flutter_new
插件进行音频转录:
// 准备wav文件
final Directory documentDirectory = await getApplicationDocumentsDirectory();
final ByteData documentBytes = await rootBundle.load('assets/jfk.wav');
final String jfkPath = '${documentDirectory.path}/jfk.wav';
await File(jfkPath).writeAsBytes(
documentBytes.buffer.asUint8List(),
);
// 开始whisper转录
/// China: https://hf-mirror.com/ggerganov/whisper.cpp/resolve/main
/// Other: https://huggingface.co/ggerganov/whisper.cpp/resolve/main
final Whisper whisper = Whisper(
model: WhisperModel.base,
downloadHost: "https://huggingface.co/ggerganov/whisper.cpp/resolve/main"
);
final String? whisperVersion = await whisper.getVersion();
print(whisperVersion);
final String transcription = await whisper.transcribe(
transcribeRequest: TranscribeRequest(
audio: jfkPath,
isTranslate: true, // 将结果从音频语言翻译成英文文本
isNoTimestamps: false, // 获取段落信息
splitOnWord: true, // 将段落按每个单词分割
),
);
print(transcription);
示例代码
以下是完整的示例代码,展示了如何在 Flutter 应用中集成 whisper_flutter_new
插件:
/*
* Copyright (c) 田梓萱[小草林] 2021-2024.
* All Rights Reserved.
* All codes are protected by China's regulations on the protection of computer software, and infringement must be investigated.
* 版权所有 (c) 田梓萱[小草林] 2021-2024.
* 所有代码均受中国《计算机软件保护条例》保护,侵权必究.
*/
import "dart:io";
import "package:flutter/material.dart";
import "package:flutter/services.dart";
import "package:flutter_riverpod/flutter_riverpod.dart";
import "package:path_provider/path_provider.dart";
import "package:test_whisper/providers.dart";
import "package:test_whisper/record_page.dart";
import "package:test_whisper/whisper_controller.dart";
import "package:test_whisper/whisper_result.dart";
import "package:whisper_flutter_new/whisper_flutter_new.dart";
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
title: "Whisper for Flutter",
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: Theme.of(context).colorScheme.primary),
useMaterial3: true,
),
home: const MyHomePage(),
),
);
}
}
class MyHomePage extends ConsumerWidget {
const MyHomePage({
super.key,
});
[@override](/user/override)
Widget build(BuildContext context, WidgetRef ref) {
final WhisperModel model = ref.watch(modelProvider);
final String lang = ref.watch(langProvider);
final bool translate = ref.watch(translateProvider);
final bool withSegments = ref.watch(withSegmentsProvider);
final bool splitWords = ref.watch(splitWordsProvider);
final WhisperController controller = ref.watch(
whisperControllerProvider.notifier,
);
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text(
"Whisper flutter demo",
),
),
body: SafeArea(
minimum: const EdgeInsets.all(20),
child: SingleChildScrollView(child: Consumer(
builder: (context, ref, _) {
final AsyncValue<TranscribeResult?> transcriptionAsync = ref.watch(
whisperControllerProvider,
);
return transcriptionAsync.maybeWhen(
skipLoadingOnRefresh: true,
skipLoadingOnReload: true,
data: (TranscribeResult? transcriptionResult) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text("Model :"),
DropdownButton(
isExpanded: true,
value: model,
items: WhisperModel.values
.map(
(WhisperModel model) => DropdownMenuItem(
value: model,
child: Text(model.modelName),
),
)
.toList(),
onChanged: (WhisperModel? model) {
if (model != null) {
ref.read(modelProvider.notifier).state = model;
}
},
),
const SizedBox(height: 20),
const Text("Lang :"),
DropdownButton(
isExpanded: true,
value: lang,
items: ["auto", "zh", "en"]
.map(
(String lang) => DropdownMenuItem(
value: lang,
child: Text(lang),
),
)
.toList(),
onChanged: (String? lang) {
if (lang != null) {
ref.read(langProvider.notifier).state = lang;
}
},
),
const SizedBox(height: 20),
const Text("Translate result :"),
DropdownButton(
isExpanded: true,
value: translate,
items: const [
DropdownMenuItem(
value: false,
child: Text("No"),
),
DropdownMenuItem(
value: true,
child: Text("Yes"),
),
],
onChanged: (bool? translate) {
if (translate != null) {
ref.read(translateProvider.notifier).state = translate;
}
},
),
const Text("With segments :"),
DropdownButton(
isExpanded: true,
value: withSegments,
items: const [
DropdownMenuItem(
value: false,
child: Text("No"),
),
DropdownMenuItem(
value: true,
child: Text("Yes"),
),
],
onChanged: (bool? withSegments) {
if (withSegments != null) {
ref.read(withSegmentsProvider.notifier).state = withSegments;
}
},
),
const Text("Split word :"),
DropdownButton(
isExpanded: true,
value: splitWords,
items: const [
DropdownMenuItem(
value: false,
child: Text("No"),
),
DropdownMenuItem(
value: true,
child: Text("Yes"),
),
],
onChanged: (bool? splitWords) {
if (splitWords != null) {
ref.read(splitWordsProvider.notifier).state = splitWords;
}
},
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: () async {
final Directory documentDirectory = await getApplicationDocumentsDirectory();
final ByteData documentBytes = await rootBundle.load(
"assets/jfk.wav",
);
final String jfkPath = "${documentDirectory.path}/jfk.wav";
await File(jfkPath).writeAsBytes(
documentBytes.buffer.asUint8List(),
);
await controller.transcribe(jfkPath);
},
child: const Text("jfk.wav"),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: () async {
final String? recordFilePath = await RecordPage.openRecordPage(
context,
);
if (recordFilePath != null) {
await controller.transcribe(recordFilePath);
}
},
child: const Text("record"),
),
],
),
if (transcriptionResult != null) ...[
const SizedBox(height: 20),
Text(
transcriptionResult.transcription.text,
),
const SizedBox(height: 20),
Text(
transcriptionResult.time.toString(),
),
if (transcriptionResult.transcription.segments != null) ...[
const SizedBox(height: 25),
Expanded(
child: ListView.separated(
itemCount: transcriptionResult.transcription.segments!.length,
itemBuilder: (context, index) {
final WhisperTranscribeSegment segment = transcriptionResult.transcription.segments![index];
final Duration fromTs = segment.fromTs;
final Duration toTs = segment.toTs;
final String text = segment.text;
return Text(
"[$fromTs - $toTs] $text",
);
},
separatorBuilder: (context, index) {
return const Divider();
},
),
),
const SizedBox(height: 30),
],
],
],
);
},
orElse: () {
return const Center(
child: CircularProgressIndicator(),
);
},
);
},
)),
),
);
}
}
更多关于Flutter隐私保护通讯插件whisper_flutter_new的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter隐私保护通讯插件whisper_flutter_new的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 whisper_flutter_new
插件的示例代码。这个插件假设是用来进行隐私保护的通讯,具体功能和API可能需要根据插件的实际文档进行调整。以下是一个基本的Flutter应用示例,展示如何集成和使用 whisper_flutter_new
插件。
首先,确保你已经在 pubspec.yaml
文件中添加了 whisper_flutter_new
依赖:
dependencies:
flutter:
sdk: flutter
whisper_flutter_new: ^最新版本号
然后运行 flutter pub get
来获取依赖。
接下来,在你的 Flutter 应用中,你可以按照以下步骤使用 whisper_flutter_new
插件:
- 导入插件:
在你的 Dart 文件中导入插件:
import 'package:whisper_flutter_new/whisper_flutter_new.dart';
- 初始化插件:
通常在应用的入口文件(如 main.dart
)中进行初始化。
void main() {
WidgetsFlutterBinding.ensureInitialized();
// 假设插件有一个初始化方法
WhisperFlutterNew.instance.initialize().then((value) {
runApp(MyApp());
}).catchError((error) {
// 处理初始化错误
print('Initialization error: $error');
runApp(MyApp()); // 或者显示错误页面
});
}
注意:上面的 initialize
方法是假设的,具体方法名需参考插件文档。
- 使用插件进行通讯:
在你的应用逻辑中使用插件提供的API进行加密通讯。以下是一个假设的加密消息发送和接收的示例:
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String encryptedMessage = '';
String decryptedMessage = '';
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Whisper Flutter Demo'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
decoration: InputDecoration(labelText: 'Plain Text Message'),
onChanged: (value) {
// 当用户输入明文消息时,进行加密
encryptMessage(value);
},
),
SizedBox(height: 16),
Text('Encrypted Message: $encryptedMessage'),
SizedBox(height: 16),
Text('Decrypted Message: $decryptedMessage'),
SizedBox(height: 16),
ElevatedButton(
onPressed: () {
// 假设有一个解密方法
decryptMessage(encryptedMessage);
},
child: Text('Decrypt Message'),
),
],
),
),
),
);
}
void encryptMessage(String plainText) async {
try {
// 假设插件有一个加密方法
String encrypted = await WhisperFlutterNew.instance.encrypt(plainText);
setState(() {
encryptedMessage = encrypted;
});
} catch (e) {
print('Encryption error: $e');
}
}
void decryptMessage(String encryptedText) async {
try {
// 假设插件有一个解密方法
String decrypted = await WhisperFlutterNew.instance.decrypt(encryptedText);
setState(() {
decryptedMessage = decrypted;
});
} catch (e) {
print('Decryption error: $e');
}
}
}
注意:上面的 encrypt
和 decrypt
方法以及它们的参数和返回值类型都是假设的。你需要根据 whisper_flutter_new
插件的实际API文档进行调整。
此外,隐私保护通讯通常涉及密钥管理,确保你理解并妥善处理密钥的存储和安全性。
希望这个示例能帮助你开始使用 whisper_flutter_new
插件。如果你有更多具体的问题或需要更详细的帮助,请查阅插件的官方文档或联系插件的维护者。