Flutter隐私保护通讯插件whisper_flutter_new的使用

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

Flutter隐私保护通讯插件whisper_flutter_new的使用

简介

whisper_flutter_new 是一个基于 whisper.cpp 模型实现的隐私保护通讯插件,支持iOS和Android平台。该插件可以用于音频转录和翻译。

主要特性

  1. 支持AGP8+。
  2. 支持Android 5.0+、iOS 13+ 和 MacOS 11+。
  3. 性能优化且运行速度快。

支持的模型

  • 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

1 回复

更多关于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 插件:

  1. 导入插件

在你的 Dart 文件中导入插件:

import 'package:whisper_flutter_new/whisper_flutter_new.dart';
  1. 初始化插件

通常在应用的入口文件(如 main.dart)中进行初始化。

void main() {
  WidgetsFlutterBinding.ensureInitialized();

  // 假设插件有一个初始化方法
  WhisperFlutterNew.instance.initialize().then((value) {
    runApp(MyApp());
  }).catchError((error) {
    // 处理初始化错误
    print('Initialization error: $error');
    runApp(MyApp()); // 或者显示错误页面
  });
}

注意:上面的 initialize 方法是假设的,具体方法名需参考插件文档。

  1. 使用插件进行通讯

在你的应用逻辑中使用插件提供的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');
    }
  }
}

注意:上面的 encryptdecrypt 方法以及它们的参数和返回值类型都是假设的。你需要根据 whisper_flutter_new 插件的实际API文档进行调整。

此外,隐私保护通讯通常涉及密钥管理,确保你理解并妥善处理密钥的存储和安全性。

希望这个示例能帮助你开始使用 whisper_flutter_new 插件。如果你有更多具体的问题或需要更详细的帮助,请查阅插件的官方文档或联系插件的维护者。

回到顶部