whisper_flutter 0.0.0 copy "whisper_flutter: ^0.0.0" to clipboard
whisper_flutter: ^0.0.0 copied to clipboard

whisper.cpp (from @ggerganov) implementation using ffi, a library for recognition audio to text without heavy gpu, support server side and client side.

example/lib/main.dart

// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, depend_on_referenced_packages

import 'dart:ffi';
import 'dart:io';
import 'dart:isolate';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:whisper_dart/whisper_dart.dart';
import 'package:galaxeus_lib/galaxeus_lib.dart';
import "package:cool_alert/cool_alert.dart";

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  DynamicLibrary.open("libwhisper.so");
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Whisper Speech to Text'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  EventEmitter eventEmitter = EventEmitter();

  late String model = "";
  late String audio = "";
  late String result = "";
  late bool is_procces = false;
  @override
  void initState() {
    super.initState();

    task();
  }

  void task() async {
    ReceivePort receivePort = ReceivePort();

    ReceivePort secondReceivePort = ReceivePort();
    receivePort.listen((message) {
      if (message is WhisperResponse) {
        setState(() {
          result = message.toString();
        });
      }

      setState(() {
        is_procces = false;
      });
    });
    Isolate.spawn(
      (WhisperIsolateData whisperIsolateData) {
        Whisper whisper = Whisper(
          whisperLib: "libwhisper.so",
        );
        ReceivePort receivePort = ReceivePort();
        whisperIsolateData.second_send_port.send(receivePort.sendPort);
        receivePort.listen((message) {
          if (message is WhisperData) {
            var res = whisper.request(
              whisperLib: "libwhisper.so",
              whisperRequest: WhisperRequest.fromWavFile(
                audio: File(message.audio),
                model: File(message.model),
              ),
            );
            whisperIsolateData.main_send_port.send(res);
          } else {
            whisperIsolateData.main_send_port.send("else");
          }
        });
      },
      WhisperIsolateData(
        main_send_port: receivePort.sendPort,
        second_send_port: secondReceivePort.sendPort,
      ),
    );

    final port = secondReceivePort.asBroadcastStream();
    final send_port = await port.first;
    if (send_port is SendPort) {
      eventEmitter.on("update", null, (ev, context) {
        if (ev.eventData is WhisperData) {
          send_port.send((ev.eventData as WhisperData));
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: ConstrainedBox(
          constraints: BoxConstraints(
            minHeight: MediaQuery.of(context).size.height,
            minWidth: MediaQuery.of(context).size.width,
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ChooseWidget(
                is_main: !is_procces,
                main_widget: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Padding(
                      padding: const EdgeInsets.all(10),
                      child: ElevatedButton(
                        onPressed: () async {
                          FilePickerResult? resul =
                              await FilePicker.platform.pickFiles();

                          if (resul != null) {
                            File file = File(resul.files.single.path!);
                            if (file.existsSync()) {
                              setState(() {
                                model = file.path;
                              });
                            }
                          }
                        },
                        child: const Text("set model"),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(10),
                      child: ElevatedButton(
                        onPressed: () async {
                          FilePickerResult? resul =
                              await FilePicker.platform.pickFiles();

                          if (resul != null) {
                            File file = File(resul.files.single.path!);
                            if (file.existsSync()) {
                              setState(() {
                                audio = file.path;
                              });
                            }
                          }
                        },
                        child: const Text("set audio"),
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(10),
                      child: ElevatedButton(
                        onPressed: () async {
                          if (is_procces) {
                            return await CoolAlert.show(
                              context: context,
                              type: CoolAlertType.info,
                              text:
                                  "Tolong tunggu procces tadi sampai selesai ya",
                            );
                          }
                          if (audio.isEmpty) {
                            await CoolAlert.show(
                              context: context,
                              type: CoolAlertType.info,
                              text:
                                  "Maaf audio kosong tolong setting dahulu ya",
                            );
                            if (kDebugMode) {
                              print("audio is empty");
                            }
                            return;
                          }
                          if (model.isEmpty) {
                            await CoolAlert.show(
                                context: context,
                                type: CoolAlertType.info,
                                text:
                                    "Maaf model kosong tolong setting dahulu ya");
                            if (kDebugMode) {
                              print("model is empty");
                            }
                            return;
                          }
                          eventEmitter.emit(
                            "update",
                            null,
                            WhisperData(audio: audio, model: model),
                          );
                          setState(() {
                            is_procces = true;
                          });
                        },
                        child: const Text("Start"),
                      ),
                    ),
                  ],
                ),
                second_widget: const CircularProgressIndicator(),
              ),
              Padding(
                padding: const EdgeInsets.all(10),
                child: Text("model: ${model}"),
              ),
              Padding(
                padding: const EdgeInsets.all(10),
                child: Text("audio: ${audio}"),
              ),
              Padding(
                padding: const EdgeInsets.all(10),
                child: Text("Result: ${result}"),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class ChooseWidget extends StatelessWidget {
  final bool is_main;
  final Widget main_widget;
  final Widget second_widget;
  const ChooseWidget({
    Key? key,
    this.is_main = true,
    required this.main_widget,
    required this.second_widget,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    if (is_main) {
      return main_widget;
    }
    return second_widget;
  }
}

class WhisperData {
  late String audio;
  late String model;
  WhisperData({required this.audio, required this.model});
}

class WhisperIsolateData {
  final SendPort main_send_port;
  final SendPort second_send_port;
  WhisperIsolateData({
    required this.main_send_port,
    required this.second_send_port,
  });
}
13
likes
0
pub points
56%
popularity

Publisher

unverified uploader

whisper.cpp (from @ggerganov) implementation using ffi, a library for recognition audio to text without heavy gpu, support server side and client side.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

ffi, flutter, plugin_platform_interface, whisper_dart

More

Packages that depend on whisper_flutter