├── .dart_tool ├── version └── package_config_subset ├── .idea ├── .gitignore ├── misc.xml ├── vcs.xml ├── modules.xml └── libraries │ ├── Flutter_Plugins.xml │ └── Dart_SDK.xml ├── android ├── settings.gradle ├── .gitignore ├── src │ ├── main │ │ └── AndroidManifest.xml │ └── whisper │ │ ├── whisper.cpp │ │ └── .gitignore │ │ ├── main.h │ │ ├── CMakeLists.txt │ │ └── main.cpp ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── gradle.properties └── build.gradle ├── example ├── ios │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Flutter │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ ├── RunnerTests │ │ └── RunnerTests.swift │ ├── .gitignore │ └── Podfile ├── assets │ └── jfk.wav ├── macos │ ├── Runner │ │ ├── Configs │ │ │ ├── Debug.xcconfig │ │ │ ├── Release.xcconfig │ │ │ ├── Warnings.xcconfig │ │ │ └── AppInfo.xcconfig │ │ ├── Assets.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── app_icon_16.png │ │ │ │ ├── app_icon_32.png │ │ │ │ ├── app_icon_64.png │ │ │ │ ├── app_icon_1024.png │ │ │ │ ├── app_icon_128.png │ │ │ │ ├── app_icon_256.png │ │ │ │ ├── app_icon_512.png │ │ │ │ └── Contents.json │ │ ├── Release.entitlements │ │ ├── AppDelegate.swift │ │ ├── MainFlutterWindow.swift │ │ ├── DebugProfile.entitlements │ │ └── Info.plist │ ├── .gitignore │ ├── Flutter │ │ ├── Flutter-Debug.xcconfig │ │ ├── Flutter-Release.xcconfig │ │ └── GeneratedPluginRegistrant.swift │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── RunnerTests │ │ └── RunnerTests.swift │ └── Podfile ├── windows │ └── runner │ │ └── resources │ │ └── app_icon.ico ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── drawable-v21 │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ ├── values │ │ │ │ │ │ └── styles.xml │ │ │ │ │ └── values-night │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── whisper_ggml │ │ │ │ │ │ └── example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── .gitignore │ ├── build.gradle │ └── settings.gradle ├── pubspec.yaml ├── README.md ├── .gitignore ├── test │ └── widget_test.dart ├── .metadata ├── analysis_options.yaml └── lib │ └── main.dart ├── linux ├── libggml.so ├── libggml-base.so ├── libggml-cpu.so └── CMakeLists.txt ├── analysis_options.yaml ├── lib ├── whisper_ggml.dart └── src │ ├── models │ ├── _models.dart │ ├── whisper_dto.dart │ ├── whisper_result.dart │ ├── requests │ │ ├── version_request.dart │ │ ├── transcribe_request.dart │ │ ├── transcribe_request_dto.g.dart │ │ ├── transcribe_request_dto.dart │ │ └── version_request.freezed.dart │ ├── responses │ │ ├── whisper_version_response.g.dart │ │ ├── whisper_version_response.dart │ │ ├── whisper_transcribe_response.dart │ │ ├── whisper_transcribe_response.g.dart │ │ ├── whisper_transcribe_segment.g.dart │ │ ├── whisper_transcribe_segment.dart │ │ ├── whisper_version_response.freezed.dart │ │ ├── whisper_transcribe_response.freezed.dart │ │ └── whisper_transcribe_segment.freezed.dart │ └── whisper_model.dart │ ├── whisper_audio_convert.dart │ ├── whisper_controller.dart │ └── whisper.dart ├── macos ├── Classes │ ├── whisper_ggml.h │ └── whisper_ggml.cpp └── whisper_ggml.podspec ├── windows ├── .gitignore └── CMakeLists.txt ├── LICENSE ├── pubspec.yaml ├── CHANGELOG.md ├── ios ├── whisper_ggml.podspec └── Classes │ └── whisper_flutter_plus.cpp └── README.md /.dart_tool/version: -------------------------------------------------------------------------------- 1 | 3.29.3 -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | package android 2 | 3 | rootProject.name = 'whisper_ggml' 4 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /linux/libggml.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/linux/libggml.so -------------------------------------------------------------------------------- /linux/libggml-base.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/linux/libggml-base.so -------------------------------------------------------------------------------- /linux/libggml-cpu.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/linux/libggml-cpu.so -------------------------------------------------------------------------------- /example/assets/jfk.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/assets/jfk.wav -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /example/macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /example/windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .cxx 10 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /example/macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "ephemeral/Flutter-Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:flutter_lints/flutter.yaml 2 | 3 | # Additional information about this file can be found at 4 | # https://dart.dev/guides/language/analysis-options 5 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sk3llo/whisper_ggml/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/whisper_ggml/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.whisper_ggml.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() 6 | -------------------------------------------------------------------------------- /lib/whisper_ggml.dart: -------------------------------------------------------------------------------- 1 | export 'src/models/whisper_model.dart'; 2 | export 'src/whisper.dart'; 3 | export 'src/whisper_audio_convert.dart'; 4 | export 'src/whisper_controller.dart'; 5 | export 'src/models/_models.dart'; 6 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/src/models/_models.dart: -------------------------------------------------------------------------------- 1 | export './requests/transcribe_request.dart'; 2 | export './responses/whisper_transcribe_response.dart'; 3 | export './responses/whisper_transcribe_segment.dart'; 4 | export './responses/whisper_version_response.dart'; 5 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | zipStoreBase=GRADLE_USER_HOME 4 | zipStorePath=wrapper/dists 5 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-all.zip 6 | -------------------------------------------------------------------------------- /lib/src/models/whisper_dto.dart: -------------------------------------------------------------------------------- 1 | /// Common whisper request 2 | abstract class WhisperRequestDto { 3 | /// Convert current request to String encoded whisper json 4 | String toRequestString(); 5 | 6 | /// Type of request or response 7 | String get specialType; 8 | } 9 | -------------------------------------------------------------------------------- /lib/src/models/whisper_result.dart: -------------------------------------------------------------------------------- 1 | import 'responses/whisper_transcribe_response.dart'; 2 | 3 | class TranscribeResult { 4 | const TranscribeResult({required this.transcription, required this.time}); 5 | final WhisperTranscribeResponse transcription; 6 | final Duration time; 7 | } 8 | -------------------------------------------------------------------------------- /example/macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /example/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/macos/RunnerTests/RunnerTests.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | import XCTest 4 | 5 | class RunnerTests: XCTestCase { 6 | 7 | func testExample() { 8 | // If you add code to the Runner application, consider adding tests here. 9 | // See https://developer.apple.com/documentation/xctest for more information about using XCTest. 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @main 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | 10 | override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /android/src/whisper/whisper.cpp/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | .cache/ 4 | .vs/ 5 | .vscode/ 6 | .DS_Store 7 | 8 | build/ 9 | build-em/ 10 | build-debug/ 11 | build-release/ 12 | build-static/ 13 | build-sanitize-addr/ 14 | build-sanitize-thread/ 15 | 16 | /main 17 | /stream 18 | /command 19 | /talk 20 | /bench 21 | 22 | arm_neon.h 23 | sync.sh 24 | libwhisper.a 25 | libwhisper.so 26 | compile_commands.json 27 | 28 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Flutter 2 | import UIKit 3 | 4 | @main 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /macos/Classes/whisper_ggml.h: -------------------------------------------------------------------------------- 1 | #if defined(__GNUC__) 2 | // Attributes to prevent 'unused' function from being removed and to make it visible 3 | #define FUNCTION_ATTRIBUTE __attribute__((visibility("default"))) __attribute__((used)) 4 | #elif defined(_MSC_VER) 5 | // Marking a function for export 6 | #define FUNCTION_ATTRIBUTE __declspec(dllexport) 7 | #endif 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | char *request(char *body); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif -------------------------------------------------------------------------------- /android/src/whisper/main.h: -------------------------------------------------------------------------------- 1 | #if defined(__GNUC__) 2 | // Attributes to prevent 'unused' function from being removed and to make it visible 3 | #define FUNCTION_ATTRIBUTE __attribute__((visibility("default"))) __attribute__((used)) 4 | #elif defined(_MSC_VER) 5 | // Marking a function for export 6 | #define FUNCTION_ATTRIBUTE __declspec(dllexport) 7 | #endif 8 | 9 | #ifdef __cplusplus 10 | extern "C" 11 | { 12 | #endif 13 | 14 | char *request(char *body); 15 | 16 | #ifdef __cplusplus 17 | } 18 | #endif -------------------------------------------------------------------------------- /example/macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | com.apple.security.network.client 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: "Whisper ggml example" 3 | publish_to: 'none' 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: ^3.6.2 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | cupertino_icons: ^1.0.8 15 | # Audio recorder 16 | record: ^6.0.0 17 | # Get local path 18 | path_provider: ^2.1.3 19 | # Whisper model 20 | whisper_ggml: 21 | path: ../ 22 | 23 | dev_dependencies: 24 | flutter_test: 25 | sdk: flutter 26 | 27 | flutter_lints: ^5.0.0 28 | 29 | flutter: 30 | uses-material-design: true 31 | 32 | assets: 33 | - assets/ -------------------------------------------------------------------------------- /example/macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import ffmpeg_kit_flutter_new_min 9 | import path_provider_foundation 10 | import record_macos 11 | 12 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 13 | FFmpegKitFlutterPlugin.register(with: registry.registrar(forPlugin: "FFmpegKitFlutterPlugin")) 14 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 15 | RecordMacOsPlugin.register(with: registry.registrar(forPlugin: "RecordMacOsPlugin")) 16 | } 17 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | # example 2 | 3 | A new Flutter project. 4 | 5 | ## Getting Started 6 | 7 | This project is a starting point for a Flutter application. 8 | 9 | A few resources to get you started if this is your first Flutter project: 10 | 11 | - [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) 12 | - [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) 13 | 14 | For help getting started with Flutter development, view the 15 | [online documentation](https://docs.flutter.dev/), which offers tutorials, 16 | samples, guidance on mobile development, and a full API reference. 17 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /lib/src/models/requests/version_request.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | import 'package:whisper_ggml/src/models/whisper_dto.dart'; 5 | 6 | part 'version_request.freezed.dart'; 7 | 8 | /// Get whisper version request 9 | @freezed 10 | class VersionRequest with _$VersionRequest implements WhisperRequestDto { 11 | /// 12 | const factory VersionRequest() = _VersionRequest; 13 | const VersionRequest._(); 14 | 15 | @override 16 | String get specialType => 'getVersion'; 17 | 18 | @override 19 | String toRequestString() { 20 | return json.encode({'@type': specialType}); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /example/macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = example 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.whisperggml.example 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2025 com.whisper_ggml. All rights reserved. 15 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | } 6 | } 7 | 8 | rootProject.buildDir = '../build' 9 | subprojects { 10 | project.buildDir = "${rootProject.buildDir}/${project.name}" 11 | } 12 | subprojects { 13 | afterEvaluate { project -> 14 | if (project.plugins.hasPlugin("com.android.application") || 15 | project.plugins.hasPlugin("com.android.library")) { 16 | project.android { 17 | compileSdkVersion 34 18 | buildToolsVersion "34.0.0" 19 | } 20 | } 21 | } 22 | } 23 | subprojects { 24 | project.evaluationDependsOn(':app') 25 | } 26 | 27 | tasks.register("clean", Delete) { 28 | delete rootProject.buildDir 29 | } 30 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_version_response.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'whisper_version_response.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _WhisperVersionResponse _$WhisperVersionResponseFromJson( 10 | Map json) => 11 | _WhisperVersionResponse( 12 | type: json['@type'] as String, 13 | message: json['message'] as String, 14 | ); 15 | 16 | Map _$WhisperVersionResponseToJson( 17 | _WhisperVersionResponse instance) => 18 | { 19 | '@type': instance.type, 20 | 'message': instance.message, 21 | }; 22 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | *.exe 19 | *.deb 20 | *.sqlite-* 21 | *.sqlite 22 | docs/canvaskit 23 | */canvaskit 24 | .dart_tool/ 25 | build/ 26 | ephemeral/ 27 | /build/ 28 | generate_glx_* 29 | node_modules/ 30 | flutter/ephemeral 31 | android/.gradle 32 | android/flutter/ephemeral 33 | linux/flutter/ephemeral 34 | macos/Flutter/ephemeral 35 | windows/ephemeral 36 | tmp/ 37 | temp/ 38 | generate_general_private_tools_* 39 | packagex-build-debug 40 | packagex-compile-debug -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_version_response.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | 5 | part 'whisper_version_response.freezed.dart'; 6 | part 'whisper_version_response.g.dart'; 7 | 8 | /// Response model of whisper getVersion 9 | @freezed 10 | abstract class WhisperVersionResponse with _$WhisperVersionResponse { 11 | /// 12 | const factory WhisperVersionResponse({ 13 | @JsonKey(name: '@type') required String type, 14 | required String message, 15 | }) = _WhisperVersionResponse; 16 | 17 | const WhisperVersionResponse._(); 18 | 19 | /// Parse [json] to WhisperVersionResponse 20 | factory WhisperVersionResponse.fromJson(Map json) => 21 | _$WhisperVersionResponseFromJson(json); 22 | } 23 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | def flutterSdkPath = { 3 | def properties = new Properties() 4 | file("local.properties").withInputStream { properties.load(it) } 5 | def flutterSdkPath = properties.getProperty("flutter.sdk") 6 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 7 | return flutterSdkPath 8 | }() 9 | 10 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 11 | 12 | repositories { 13 | google() 14 | mavenCentral() 15 | gradlePluginPortal() 16 | } 17 | } 18 | 19 | plugins { 20 | id "dev.flutter.flutter-plugin-loader" version "1.0.0" 21 | id "com.android.application" version "8.4.0" apply false 22 | id "org.jetbrains.kotlin.android" version "1.8.22" apply false 23 | } 24 | 25 | include ":app" 26 | -------------------------------------------------------------------------------- /.idea/libraries/Flutter_Plugins.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 12.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .build/ 9 | .buildlog/ 10 | .history 11 | .svn/ 12 | .swiftpm/ 13 | migrate_working_dir/ 14 | 15 | # IntelliJ related 16 | *.iml 17 | *.ipr 18 | *.iws 19 | .idea/ 20 | .dart_tool/ 21 | 22 | # The .vscode folder contains launch configuration and tasks you configure in 23 | # VS Code which you may wish to be included in version control, so this line 24 | # is commented out by default. 25 | #.vscode/ 26 | 27 | # Flutter/Dart/Pub related 28 | **/doc/api/ 29 | **/ios/Flutter/.last_build_id 30 | .flutter-plugins 31 | .flutter-plugins-dependencies 32 | .pub-cache/ 33 | .pub/ 34 | /build/ 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Android Studio will place build artifacts here 43 | /android/app/debug 44 | /android/app/profile 45 | /android/app/release 46 | -------------------------------------------------------------------------------- /lib/src/models/requests/transcribe_request.dart: -------------------------------------------------------------------------------- 1 | import 'package:freezed_annotation/freezed_annotation.dart'; 2 | 3 | part 'transcribe_request.freezed.dart'; 4 | 5 | /// Transcription request parameters 6 | @freezed 7 | abstract class TranscribeRequest with _$TranscribeRequest { 8 | const factory TranscribeRequest({ 9 | required String audio, 10 | @Default(false) bool isTranslate, 11 | @Default(6) int threads, 12 | @Default(false) bool isVerbose, 13 | @Default('en') String language, 14 | @Default(false) bool isSpecialTokens, 15 | @Default(false) bool isNoTimestamps, 16 | @Default(false) bool isRealtime, 17 | @Default(1) int nProcessors, 18 | @Default(false) bool splitOnWord, 19 | @Default(false) bool noFallback, 20 | @Default(false) bool diarize, 21 | @Default(false) bool speedUp, 22 | @Default(null) Stream? realtimeStream, 23 | }) = _TranscribeRequest; 24 | const TranscribeRequest._(); 25 | } 26 | -------------------------------------------------------------------------------- /linux/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have CMake 3.10 or later 2 | # installed. You should not increase this version, as doing so will cause 3 | # the plugin to fail to compile for some customers of the plugin. 4 | cmake_minimum_required(VERSION 3.10) 5 | 6 | # Project-level configuration. 7 | set(PROJECT_NAME "whisper_ggml") 8 | project(${PROJECT_NAME} LANGUAGES CXX) 9 | 10 | # List of absolute paths to libraries that should be bundled with the plugin. 11 | # This list could contain prebuilt libraries, or libraries created by an 12 | # external build triggered from this build file. 13 | set(ggml_library_flutter_bundled_libraries 14 | # Defined in ../src/CMakeLists.txt. 15 | # This can be changed to accommodate different builds. 16 | "${CMAKE_CURRENT_SOURCE_DIR}/libggml-base.so" 17 | "${CMAKE_CURRENT_SOURCE_DIR}/libggml-cpu.so" 18 | "${CMAKE_CURRENT_SOURCE_DIR}/libggml.so" 19 | PARENT_SCOPE 20 | ) -------------------------------------------------------------------------------- /windows/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have a version of Visual Studio 2 | # installed that includes CMake 3.14 or later. You should not increase this 3 | # version, as doing so will cause the plugin to fail to compile for some 4 | # customers of the plugin. 5 | cmake_minimum_required(VERSION 3.14) 6 | 7 | # Project-level configuration. 8 | set(PROJECT_NAME "whisper_ggml") 9 | project(${PROJECT_NAME} LANGUAGES CXX) 10 | 11 | # List of absolute paths to libraries that should be bundled with the plugin. 12 | # This list could contain prebuilt libraries, or libraries created by an 13 | # external build triggered from this build file. 14 | set(ggml_library_flutter_bundled_libraries 15 | # Defined in ../src/CMakeLists.txt. 16 | # This can be changed to accommodate different builds. 17 | "${CMAKE_CURRENT_SOURCE_DIR}/tts_general_ai.dll" 18 | "${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime.dll" 19 | PARENT_SCOPE 20 | ) -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_response.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | import 'package:whisper_ggml/src/models/responses/whisper_transcribe_segment.dart'; 5 | 6 | part 'whisper_transcribe_response.freezed.dart'; 7 | part 'whisper_transcribe_response.g.dart'; 8 | 9 | /// Response model of whisper getVersion 10 | @freezed 11 | abstract class WhisperTranscribeResponse with _$WhisperTranscribeResponse { 12 | /// 13 | const factory WhisperTranscribeResponse({ 14 | @JsonKey(name: '@type') required String type, 15 | required String text, 16 | @JsonKey(name: 'segments') 17 | required List? segments, 18 | }) = _WhisperTranscribeResponse; 19 | 20 | const WhisperTranscribeResponse._(); 21 | 22 | /// Parse [json] to WhisperTranscribeResponse 23 | factory WhisperTranscribeResponse.fromJson(Map json) => 24 | _$WhisperTranscribeResponseFromJson(json); 25 | } 26 | -------------------------------------------------------------------------------- /lib/src/models/whisper_model.dart: -------------------------------------------------------------------------------- 1 | /// Available whisper models 2 | enum WhisperModel { 3 | /// tiny model for all languages 4 | tiny('tiny'), 5 | 6 | /// base model for all languages 7 | base('base'), 8 | 9 | /// small model for all languages 10 | small('small'), 11 | 12 | /// medium model for all languages 13 | medium('medium'), 14 | 15 | /// large model for all languages 16 | large('large-v3'), 17 | 18 | /// tiny model for english only 19 | tinyEn('tiny.en'), 20 | 21 | /// base model for english only 22 | baseEn('base.en'), 23 | 24 | /// small model for english only 25 | smallEn('small.en'), 26 | 27 | /// medium model for english only 28 | mediumEn('medium.en'); 29 | 30 | const WhisperModel(this.modelName); 31 | 32 | /// Public name of model 33 | final String modelName; 34 | 35 | /// Huggingface url to download model 36 | Uri get modelUri { 37 | return Uri.parse( 38 | 'https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-$modelName.bin', 39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_response.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'whisper_transcribe_response.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _WhisperTranscribeResponse _$WhisperTranscribeResponseFromJson( 10 | Map json) => 11 | _WhisperTranscribeResponse( 12 | type: json['@type'] as String, 13 | text: json['text'] as String, 14 | segments: (json['segments'] as List?) 15 | ?.map((e) => 16 | WhisperTranscribeSegment.fromJson(e as Map)) 17 | .toList(), 18 | ); 19 | 20 | Map _$WhisperTranscribeResponseToJson( 21 | _WhisperTranscribeResponse instance) => 22 | { 23 | '@type': instance.type, 24 | 'text': instance.text, 25 | 'segments': instance.segments, 26 | }; 27 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_segment.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'whisper_transcribe_segment.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _WhisperTranscribeSegment _$WhisperTranscribeSegmentFromJson( 10 | Map json) => 11 | _WhisperTranscribeSegment( 12 | fromTs: WhisperTranscribeSegment._durationFromInt( 13 | (json['from_ts'] as num).toInt()), 14 | toTs: WhisperTranscribeSegment._durationFromInt( 15 | (json['to_ts'] as num).toInt()), 16 | text: json['text'] as String, 17 | ); 18 | 19 | Map _$WhisperTranscribeSegmentToJson( 20 | _WhisperTranscribeSegment instance) => 21 | { 22 | 'from_ts': instance.fromTs.inMicroseconds, 23 | 'to_ts': instance.toTs.inMicroseconds, 24 | 'text': instance.text, 25 | }; 26 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_segment.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | 5 | part 'whisper_transcribe_segment.freezed.dart'; 6 | part 'whisper_transcribe_segment.g.dart'; 7 | 8 | @freezed 9 | 10 | /// Transcribe segment model 11 | abstract class WhisperTranscribeSegment with _$WhisperTranscribeSegment { 12 | /// 13 | const factory WhisperTranscribeSegment({ 14 | @JsonKey( 15 | name: 'from_ts', 16 | fromJson: WhisperTranscribeSegment._durationFromInt, 17 | ) 18 | required Duration fromTs, 19 | @JsonKey(name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 20 | required Duration toTs, 21 | required String text, 22 | }) = _WhisperTranscribeSegment; 23 | 24 | /// Parse [json] to WhisperTranscribeSegment 25 | factory WhisperTranscribeSegment.fromJson(Map json) => 26 | _$WhisperTranscribeSegmentFromJson(json); 27 | 28 | static Duration _durationFromInt(int timestamp) { 29 | return Duration(milliseconds: timestamp * 10); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Hrvoje Cukman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: whisper_ggml 2 | description: OpenAI Whisper ASR (Automatic Speech Recognition) for Flutter 3 | version: 1.7.0 4 | repository: https://github.com/sk3llo/whisper_ggml 5 | 6 | environment: 7 | sdk: '>=3.1.0 <4.0.0' 8 | flutter: ">=3.7.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | ffi: ^2.1.4 15 | ffmpeg_kit_flutter_new_min: ^2.1.0 16 | freezed_annotation: ^3.0.0 17 | json_annotation: ^4.9.0 18 | plugin_platform_interface: ^2.1.8 19 | universal_io: ^2.2.2 20 | flutter_riverpod: ^2.6.1 21 | path_provider: ^2.1.5 22 | 23 | dev_dependencies: 24 | build_runner: ^2.4.15 25 | ffigen: ^18.1.0 26 | freezed: ^3.0.6 27 | json_serializable: ^6.9.5 28 | very_good_analysis: ^7.0.0 29 | 30 | topics: 31 | - 'ggml' 32 | - 'artificial-intelligence' 33 | - 'machine-learning' 34 | 35 | flutter: 36 | uses-material-design: true 37 | plugin: 38 | platforms: 39 | android: 40 | ffiPlugin: true 41 | ios: 42 | ffiPlugin: true 43 | linux: 44 | ffiPlugin: true 45 | macos: 46 | ffiPlugin: true 47 | windows: 48 | ffiPlugin: true -------------------------------------------------------------------------------- /macos/whisper_ggml.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'whisper_ggml' 3 | s.version = '1.0.0' 4 | s.summary = 'A new Flutter FFI plugin project.' 5 | s.description = <<-DESC 6 | A new Flutter FFI plugin project. 7 | DESC 8 | s.homepage = 'https://github.com/sk3llo/whisper_ggml' 9 | s.license = { :file => '../LICENSE' } 10 | s.author = { 'Your Company' => 'www.antonkarpenko.com' } 11 | 12 | # This will ensure the source files in Classes/ are included in the native 13 | # builds of apps using this FFI plugin. Podspec does not support relative 14 | # paths, so Classes contains a forwarder C file that relatively imports 15 | # `../src/*` so that the C sources can be shared among all target platforms. 16 | s.source = { :path => '.' } 17 | s.source_files = 'Classes/**/*' 18 | s.dependency 'FlutterMacOS' 19 | s.platform = :osx, '10.15' 20 | s.xcconfig = { 21 | 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++20', 22 | } 23 | s.library = 'c++' 24 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } 25 | s.swift_version = '5.0' 26 | end -------------------------------------------------------------------------------- /example/test/widget_test.dart: -------------------------------------------------------------------------------- 1 | // This is a basic Flutter widget test. 2 | // 3 | // To perform an interaction with a widget in your test, use the WidgetTester 4 | // utility in the flutter_test package. For example, you can send tap and scroll 5 | // gestures. You can also use WidgetTester to find child widgets in the widget 6 | // tree, read text, and verify that the values of widget properties are correct. 7 | 8 | import 'package:flutter/material.dart'; 9 | import 'package:flutter_test/flutter_test.dart'; 10 | 11 | import 'package:example/main.dart'; 12 | 13 | void main() { 14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async { 15 | // Build our app and trigger a frame. 16 | await tester.pumpWidget(const MyApp()); 17 | 18 | // Verify that our counter starts at 0. 19 | expect(find.text('0'), findsOneWidget); 20 | expect(find.text('1'), findsNothing); 21 | 22 | // Tap the '+' icon and trigger a frame. 23 | await tester.tap(find.byIcon(Icons.add)); 24 | await tester.pump(); 25 | 26 | // Verify that our counter has incremented. 27 | expect(find.text('0'), findsNothing); 28 | expect(find.text('1'), findsOneWidget); 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.7.0 2 | 3 | * Connected `diarize` transcribe parameter to the underlying whisper C++ code 4 | * Added `diarize` parameter to the `transcribe` method 5 | 6 | ## 1.6.0 7 | 8 | * Fixed iOS issues 9 | * Added `auto` language support for iOS 10 | * Fixed `example` project 11 | * Increased NDK version in order to support Google 16 KB requirement 12 | 13 | ## 1.5.0 14 | 15 | * Switched main FFmpeg from **heavy** `ffmpeg_kit_flutter_new: ^1.6.1` to **lightweight** `ffmpeg_kit_flutter_new_min: ^2.1.0` 16 | * Upgraded `recorder` dependency for `example` project from `v5.2.1` to `v6.0.0` 17 | * Updated main code files 18 | 19 | ## 1.4.0 20 | 21 | * Added ability to use "auto" [language detection](https://github.com/ggml-org/whisper.cpp/blob/b175baa665bc35f97a2ca774174f07dfffb84e19/examples/cli/README.md?plain=1#L51) 22 | * Upgraded `pubspec.yaml` dependencies 23 | 24 | ## 1.3.0 25 | 26 | * Upgraded Android bindings to work with Flutter 3.29 27 | * Added new FFmpeg kit dependency 28 | 29 | ## 1.2.0 30 | 31 | * Fixed Android v1 embedding issue by adding override for ffmpeg_kit_flutter_full_gpl 32 | * Upgraded dependencies 33 | 34 | ## 1.1.1 35 | 36 | * Cleaned up code 37 | 38 | ## 1.1.0 39 | 40 | * Added support for MacOS 41 | 42 | ## 1.0.0 43 | 44 | * Added support for Android and iOS 45 | 46 | -------------------------------------------------------------------------------- /ios/whisper_ggml.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'whisper_ggml' 3 | s.version = '1.0.1' 4 | s.summary = 'A new Flutter FFI plugin project.' 5 | s.description = <<-DESC 6 | A new Flutter FFI plugin project. 7 | DESC 8 | s.homepage = 'https://github.com/sk3llo/whisper_ggml' 9 | s.license = { :file => '../LICENSE' } 10 | s.author = { 'Your Company' => 'kapraton@gmail.com' } 11 | 12 | # This will ensure the source files in Classes/ are included in the native 13 | # builds of apps using this FFI plugin. Podspec does not support relative 14 | # paths, so Classes contains a forwarder C file that relatively imports 15 | # `../src/*` so that the C sources can be shared among all target platforms. 16 | s.dependency 'Flutter' 17 | s.source = { 18 | :git => 'https://github.com/sk3llo/whisper_ggml' 19 | } 20 | s.source_files = 'Classes/**/*.{cpp,c}' 21 | #s.private_header_files = 'Classes/**/*.{h,hpp}' 22 | s.platform = :ios, '15.6' 23 | s.ios.deployment_target = '15.6' 24 | 25 | # Flutter.framework does not contain a i386 slice. 26 | s.xcconfig = { 27 | 'IPHONEOS_DEPLOYMENT_TARGET' => '15.6' 28 | } 29 | s.pod_target_xcconfig = { 30 | 'DEFINES_MODULE' => 'YES', 31 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386', 32 | } 33 | s.swift_version = '5.0' 34 | end 35 | -------------------------------------------------------------------------------- /example/macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Whisper ggml example 9 | NSMicrophoneUsageDescription 10 | Need microphone access to record voice commands 11 | CFBundleExecutable 12 | $(EXECUTABLE_NAME) 13 | CFBundleIconFile 14 | 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | Whisper ggml example 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | $(FLUTTER_BUILD_NAME) 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSMinimumSystemVersion 28 | $(MACOSX_DEPLOYMENT_TARGET) 29 | NSHumanReadableCopyright 30 | $(PRODUCT_COPYRIGHT) 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "d8a9f9a52e5af486f80d932e838ee93861ffd863" 8 | channel: "[user-branch]" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 17 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 18 | - platform: linux 19 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 20 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 21 | - platform: macos 22 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 23 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 24 | - platform: windows 25 | create_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 26 | base_revision: d8a9f9a52e5af486f80d932e838ee93861ffd863 27 | 28 | # User provided section 29 | 30 | # List of Local paths (relative to this file) that should be 31 | # ignored by the migrate tool. 32 | # 33 | # Files that are not part of the templates will be ignored by default. 34 | unmanaged_files: 35 | - 'lib/main.dart' 36 | - 'ios/Runner.xcodeproj/project.pbxproj' 37 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx10g -Xss1024k -XX:ParallelGCThreads=8 -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:MaxMetaspaceSize=5g -Dkotlin.daemon.jvm.options\="-Xmx10g" 2 | org.gradle.parallel=true 3 | org.gradle.configureondemand=true 4 | org.gradle.caching=true 5 | systemProp.https.protocols=TLSv1.3,TLSv1.2,TLSv1.1 6 | systemProp.jdk.tls.client.protocols=TLSv1.3,TLSv1.2,TLSv1.1 7 | android.useAndroidX=true 8 | android.enableJetifier=true 9 | android.nonTransitiveRClass=true 10 | android.suppressUnsupportedCompileSdk=UpsideDownCake 11 | android.debug.obsoleteApi=false 12 | # Kotlin code style for this project: "official" or "obsolete": 13 | kotlin.code.style=official 14 | kotlin.build.report.output=file 15 | vcsInfo.include=true 16 | # android.enableVcsInfo=true 17 | # Enables namespacing of each library's R class so that its R class includes only the 18 | # resources declared in the library itself and none from the library's dependencies, 19 | # thereby reducing the size of the R class for that library 20 | # Enable R8 full mode. 21 | android.enableR8.fullMode=true 22 | # Only for Debug 23 | android.injected.testOnly=false 24 | #kotlin incremental 25 | kotlin.incremental=true 26 | kotlin.incremental.java=true 27 | kotlin.caching.enabled=true 28 | #MPP 29 | kotlin.mpp.enableCInteropCommonization=true 30 | kotlin.mpp.androidSourceSetLayoutVersion=2 31 | firebasePerformanceInstrumentationEnabled=true 32 | -------------------------------------------------------------------------------- /example/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at https://dart.dev/lints. 17 | # 18 | # Instead of disabling a lint rule for the entire project in the 19 | # section below, it can also be suppressed for a single line of code 20 | # or a specific dart file by using the `// ignore: name_of_lint` and 21 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 22 | # producing the lint. 23 | rules: 24 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 25 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 26 | 27 | # Additional information about this file can be found at 28 | # https://dart.dev/guides/language/analysis-options 29 | -------------------------------------------------------------------------------- /example/macos/Podfile: -------------------------------------------------------------------------------- 1 | platform :osx, '12.4' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_macos_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_macos_build_settings(target) 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/src/whisper_audio_convert.dart: -------------------------------------------------------------------------------- 1 | import 'dart:async'; 2 | 3 | import 'package:ffmpeg_kit_flutter_new_min/ffmpeg_kit.dart'; 4 | import 'package:ffmpeg_kit_flutter_new_min/ffmpeg_session.dart'; 5 | import 'package:ffmpeg_kit_flutter_new_min/return_code.dart'; 6 | import 'package:flutter/foundation.dart'; 7 | import 'package:universal_io/io.dart'; 8 | 9 | /// Class used to convert any audio file to wav 10 | class WhisperAudioConvert { 11 | /// 12 | const WhisperAudioConvert({ 13 | required this.audioInput, 14 | required this.audioOutput, 15 | }); 16 | 17 | /// Input audio file 18 | final File audioInput; 19 | 20 | /// Output audio file 21 | /// Overwriten if already exist 22 | final File audioOutput; 23 | 24 | /// convert [audioInput] to wav file 25 | Future convert() async { 26 | final FFmpegSession session = await FFmpegKit.execute( 27 | [ 28 | '-y', 29 | '-i', 30 | audioInput.path, 31 | '-ar', 32 | '16000', 33 | '-ac', 34 | '1', 35 | '-c:a', 36 | 'pcm_s16le', 37 | audioOutput.path, 38 | ].join(' '), 39 | ); 40 | 41 | final ReturnCode? returnCode = await session.getReturnCode(); 42 | 43 | if (ReturnCode.isSuccess(returnCode)) { 44 | return audioOutput; 45 | } else if (ReturnCode.isCancel(returnCode)) { 46 | debugPrint('File convertion canceled'); 47 | } else { 48 | debugPrint( 49 | 'File convertion error with returnCode ${returnCode?.getValue()}', 50 | ); 51 | } 52 | 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /example/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '15.6' 2 | 3 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 4 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 5 | 6 | project 'Runner', { 7 | 'Debug' => :debug, 8 | 'Profile' => :release, 9 | 'Release' => :release, 10 | } 11 | 12 | def flutter_root 13 | generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) 14 | unless File.exist?(generated_xcode_build_settings_path) 15 | raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" 16 | end 17 | 18 | File.foreach(generated_xcode_build_settings_path) do |line| 19 | matches = line.match(/FLUTTER_ROOT\=(.*)/) 20 | return matches[1].strip if matches 21 | end 22 | raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" 23 | end 24 | 25 | require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) 26 | 27 | flutter_ios_podfile_setup 28 | 29 | target 'Runner' do 30 | use_frameworks! 31 | use_modular_headers! 32 | 33 | flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) 34 | target 'RunnerTests' do 35 | inherit! :search_paths 36 | end 37 | end 38 | 39 | post_install do |installer| 40 | installer.pods_project.targets.each do |target| 41 | flutter_additional_ios_build_settings(target) 42 | # Add this loop to exclude arm64 architecture for simulator builds 43 | target.build_configurations.each do |config| 44 | config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64' 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | group 'com.devac.whisper_flutter' 2 | version '1.0' 3 | 4 | buildscript { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | // The Android Gradle Plugin knows how to build native code with the NDK. 12 | classpath 'com.android.tools.build:gradle:8.4.2' 13 | } 14 | } 15 | 16 | rootProject.allprojects { 17 | repositories { 18 | google() 19 | mavenCentral() 20 | } 21 | } 22 | 23 | apply plugin: 'com.android.library' 24 | 25 | android { 26 | namespace "com.devac.whisper_ggml" 27 | ndkVersion "29.0.13113456" 28 | 29 | compileSdk 34 30 | 31 | // Invoke the shared CMake build with the Android Gradle Plugin. 32 | externalNativeBuild { 33 | cmake { 34 | path "src/whisper/CMakeLists.txt" 35 | version "3.22.1" 36 | } 37 | } 38 | 39 | compileOptions { 40 | sourceCompatibility JavaVersion.VERSION_17 41 | targetCompatibility JavaVersion.VERSION_17 42 | } 43 | 44 | defaultConfig { 45 | minSdkVersion 21 46 | ndk { 47 | // Flutter does not currently support building for x86 Android (See Issue 9253). 48 | abiFilters("armeabi-v7a", "x86_64", "arm64-v8a", "x86") 49 | } 50 | externalNativeBuild { 51 | cmake { 52 | cFlags "-O3 -s -flto=thin -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden" 53 | cppFlags "-O3 -s -flto=thin -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden" 54 | arguments "-Wl,--gc-sections,--exclude-libs,ALL", "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=Release" 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /android/src/whisper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # The Flutter tooling requires that developers have CMake 3.10 or later 2 | # installed. You should not increase this version, as doing so will cause 3 | # the plugin to fail to compile for some customers of the plugin. 4 | cmake_minimum_required(VERSION 3.10) 5 | 6 | project(whisper_flutter_library LANGUAGES C CXX) 7 | set(CMAKE_CXX_STANDARD 20) 8 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3 -s -flto=thin -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden") 9 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -s -flto=thin -fdata-sections -ffunction-sections -fvisibility=hidden -fvisibility-inlines-hidden") 10 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL") 11 | set(CMAKE_BUILD_PARALLEL_LEVEL 6) 12 | add_library(whisper_flutter SHARED main.cpp) 13 | file(GLOB WHISPER_SRC whisper.cpp/*.cpp whisper.cpp/*.c) 14 | add_library(whisper ${WHISPER_SRC}) 15 | 16 | set_target_properties(whisper_flutter PROPERTIES 17 | PUBLIC_HEADER whisper.cpp/whisper.h 18 | OUTPUT_NAME "whisper" 19 | ) 20 | 21 | if (${ANDROID_ABI} STREQUAL "arm64-v8a") 22 | target_compile_options(whisper PRIVATE -march=armv8.2-a+fp16) 23 | elseif (${ANDROID_ABI} STREQUAL "armeabi-v7a") 24 | target_compile_options(whisper PRIVATE -mfpu=neon-vfpv4) 25 | endif () 26 | 27 | target_compile_options(whisper PRIVATE -O3 -s -flto=thin -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections) 28 | target_compile_options(whisper_flutter PRIVATE -O3 -s -flto=thin -fvisibility=hidden -fvisibility-inlines-hidden -ffunction-sections -fdata-sections) 29 | target_link_options(whisper PRIVATE -Wl,--gc-sections,--exclude-libs,ALL) 30 | target_link_options(whisper_flutter PRIVATE -Wl,--gc-sections,--exclude-libs,ALL) 31 | target_compile_definitions(whisper_flutter PUBLIC DART_SHARED_LIB) 32 | target_link_libraries(whisper_flutter PRIVATE whisper ${CMAKE_THREAD_LIBS_INIT}) 33 | -------------------------------------------------------------------------------- /lib/src/models/requests/transcribe_request_dto.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'transcribe_request_dto.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _TranscribeRequestDto _$TranscribeRequestDtoFromJson( 10 | Map json) => 11 | _TranscribeRequestDto( 12 | audio: json['audio'] as String, 13 | model: json['model'] as String, 14 | isTranslate: json['is_translate'] as bool, 15 | threads: (json['threads'] as num).toInt(), 16 | isVerbose: json['is_verbose'] as bool, 17 | language: json['language'] as String, 18 | isSpecialTokens: json['is_special_tokens'] as bool, 19 | isNoTimestamps: json['is_no_timestamps'] as bool, 20 | nProcessors: (json['n_processors'] as num).toInt(), 21 | splitOnWord: json['split_on_word'] as bool, 22 | noFallback: json['no_fallback'] as bool, 23 | isRealtime: json['is_realtime'] as bool, 24 | diarize: json['diarize'] as bool, 25 | speedUp: json['speed_up'] as bool, 26 | ); 27 | 28 | Map _$TranscribeRequestDtoToJson( 29 | _TranscribeRequestDto instance) => 30 | { 31 | 'audio': instance.audio, 32 | 'model': instance.model, 33 | 'is_translate': instance.isTranslate, 34 | 'threads': instance.threads, 35 | 'is_verbose': instance.isVerbose, 36 | 'language': instance.language, 37 | 'is_special_tokens': instance.isSpecialTokens, 38 | 'is_no_timestamps': instance.isNoTimestamps, 39 | 'n_processors': instance.nProcessors, 40 | 'split_on_word': instance.splitOnWord, 41 | 'no_fallback': instance.noFallback, 42 | 'is_realtime': instance.isRealtime, 43 | 'diarize': instance.diarize, 44 | 'speed_up': instance.speedUp, 45 | }; 46 | -------------------------------------------------------------------------------- /.idea/libraries/Dart_SDK.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Whisper ggml Example 9 | CFBundleName 10 | Whisper ggml example 11 | NSMicrophoneUsageDescription 12 | Listen to user audio recording 13 | CFBundleExecutable 14 | $(EXECUTABLE_NAME) 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | $(FLUTTER_BUILD_NAME) 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | $(FLUTTER_BUILD_NUMBER) 27 | LSRequiresIPhoneOS 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | UIApplicationSupportsIndirectInputEvents 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 20 | 24 | 28 | 29 | 30 | 31 | 32 | 33 | 35 | 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /lib/src/models/requests/transcribe_request_dto.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'dart:convert'; 4 | 5 | import 'package:freezed_annotation/freezed_annotation.dart'; 6 | import 'package:whisper_ggml/src/models/requests/transcribe_request.dart'; 7 | import 'package:whisper_ggml/src/models/whisper_dto.dart'; 8 | 9 | part 'transcribe_request_dto.freezed.dart'; 10 | part 'transcribe_request_dto.g.dart'; 11 | 12 | /// Transcribe request sent to whisper.cpp 13 | @freezed 14 | abstract class TranscribeRequestDto 15 | with _$TranscribeRequestDto 16 | implements WhisperRequestDto { 17 | /// 18 | const factory TranscribeRequestDto({ 19 | required String audio, 20 | required String model, 21 | @JsonKey(name: 'is_translate') required bool isTranslate, 22 | required int threads, 23 | @JsonKey(name: 'is_verbose') required bool isVerbose, 24 | required String language, 25 | @JsonKey(name: 'is_special_tokens') required bool isSpecialTokens, 26 | @JsonKey(name: 'is_no_timestamps') required bool isNoTimestamps, 27 | @JsonKey(name: 'n_processors') required int nProcessors, 28 | @JsonKey(name: 'split_on_word') required bool splitOnWord, 29 | @JsonKey(name: 'no_fallback') required bool noFallback, 30 | @JsonKey(name: 'is_realtime') required bool isRealtime, 31 | required bool diarize, 32 | @JsonKey(name: 'speed_up') required bool speedUp, 33 | }) = _TranscribeRequestDto; 34 | 35 | /// Convert [request] to TranscribeRequestDto with specified [modelPath] 36 | factory TranscribeRequestDto.fromTranscribeRequest( 37 | TranscribeRequest request, 38 | String modelPath, 39 | ) { 40 | return TranscribeRequestDto( 41 | audio: request.audio, 42 | model: modelPath, 43 | isTranslate: request.isTranslate, 44 | threads: request.threads, 45 | isVerbose: request.isVerbose, 46 | language: request.language, 47 | isSpecialTokens: request.isSpecialTokens, 48 | isNoTimestamps: request.isNoTimestamps, 49 | nProcessors: request.nProcessors, 50 | splitOnWord: request.splitOnWord, 51 | noFallback: request.noFallback, 52 | diarize: request.diarize, 53 | speedUp: request.speedUp, 54 | isRealtime: request.isRealtime, 55 | ); 56 | } 57 | const TranscribeRequestDto._(); 58 | 59 | /// Create request json 60 | factory TranscribeRequestDto.fromJson(Map json) => 61 | _$TranscribeRequestDtoFromJson(json); 62 | 63 | @override 64 | String get specialType => 'getTextFromWavFile'; 65 | 66 | @override 67 | String toRequestString() { 68 | return json.encode({'@type': specialType, ...toJson()}); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "com.android.application" 3 | id "kotlin-android" 4 | id "dev.flutter.flutter-gradle-plugin" 5 | } 6 | 7 | def localProperties = new Properties() 8 | def localPropertiesFile = rootProject.file('local.properties') 9 | if (localPropertiesFile.exists()) { 10 | localPropertiesFile.withReader('UTF-8') { reader -> 11 | localProperties.load(reader) 12 | } 13 | } 14 | 15 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 16 | if (flutterVersionCode == null) { 17 | flutterVersionCode = '1' 18 | } 19 | 20 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 21 | if (flutterVersionName == null) { 22 | flutterVersionName = '1.0' 23 | } 24 | 25 | android { 26 | namespace = "com.whisper_ggml.example" 27 | compileSdk = flutter.compileSdkVersion 28 | ndkVersion = "29.0.13113456" 29 | 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_17 32 | targetCompatibility JavaVersion.VERSION_17 33 | } 34 | 35 | kotlinOptions { 36 | jvmTarget = '17' 37 | } 38 | 39 | sourceSets { 40 | main.java.srcDirs += 'src/main/kotlin' 41 | } 42 | 43 | defaultConfig { 44 | applicationId = "com.whisper_ggml.example" 45 | // You can update the following values to match your application needs. 46 | // For more information, see: https://flutter.dev/to/review-gradle-config. 47 | minSdk = 24 48 | targetSdk = flutter.targetSdkVersion 49 | versionCode = flutterVersionCode.toInteger() 50 | versionName = flutterVersionName 51 | multiDexEnabled true 52 | ndk { 53 | // Flutter does not currently support building for x86 Android (See Issue 9253). 54 | abiFilters("armeabi-v7a", "x86_64", "arm64-v8a", "x86") 55 | } 56 | externalNativeBuild { 57 | cmake { 58 | cFlags "-O3 -s -flto=thin -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden" 59 | cppFlags "-O3 -s -flto=thin -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden" 60 | arguments "-Wl,--gc-sections,--exclude-libs,ALL", "-DANDROID_STL=c++_static", "-DCMAKE_BUILD_TYPE=Release" 61 | } 62 | } 63 | } 64 | 65 | buildTypes { 66 | release { 67 | // TODO: Add your own signing config for the release build. 68 | // Signing with the debug keys for now, so `flutter run --release` works. 69 | signingConfig = signingConfigs.debug 70 | } 71 | } 72 | } 73 | 74 | flutter { 75 | source = "../.." 76 | } 77 | 78 | dependencies {} 79 | -------------------------------------------------------------------------------- /lib/src/whisper_controller.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'package:path_provider/path_provider.dart'; 3 | import 'package:universal_io/io.dart'; 4 | import 'package:whisper_ggml/src/models/whisper_model.dart'; 5 | 6 | import 'models/whisper_result.dart'; 7 | import 'whisper.dart'; 8 | 9 | class WhisperController { 10 | String _modelPath = ''; 11 | String? _dir; 12 | 13 | Future initModel(WhisperModel model) async { 14 | _dir ??= await getModelDir(); 15 | _modelPath = '$_dir/ggml-${model.modelName}.bin'; 16 | } 17 | 18 | Future transcribe({ 19 | required WhisperModel model, 20 | required String audioPath, 21 | String lang = 'en', 22 | bool diarize = false, 23 | }) async { 24 | await initModel(model); 25 | 26 | final Whisper whisper = Whisper(model: model); 27 | final DateTime start = DateTime.now(); 28 | const bool translate = false; 29 | const bool withSegments = false; 30 | const bool splitWords = false; 31 | 32 | try { 33 | final WhisperTranscribeResponse transcription = await whisper.transcribe( 34 | transcribeRequest: TranscribeRequest( 35 | audio: audioPath, 36 | language: lang, 37 | isTranslate: translate, 38 | isNoTimestamps: !withSegments, 39 | splitOnWord: splitWords, 40 | isRealtime: true, 41 | diarize: diarize, 42 | ), 43 | modelPath: _modelPath, 44 | ); 45 | 46 | final Duration transcriptionDuration = DateTime.now().difference(start); 47 | 48 | return TranscribeResult( 49 | time: transcriptionDuration, 50 | transcription: transcription, 51 | ); 52 | } catch (e) { 53 | debugPrint(e.toString()); 54 | return null; 55 | } 56 | } 57 | 58 | static Future getModelDir() async { 59 | final Directory libraryDirectory = Platform.isAndroid 60 | ? await getApplicationSupportDirectory() 61 | : await getLibraryDirectory(); 62 | return libraryDirectory.path; 63 | } 64 | 65 | /// Get local path of model file 66 | Future getPath(WhisperModel model) async { 67 | _dir ??= await getModelDir(); 68 | return '$_dir/ggml-${model.modelName}.bin'; 69 | } 70 | 71 | /// Download [model] to [destinationPath] 72 | Future downloadModel(WhisperModel model) async { 73 | if (!File(await getPath(model)).existsSync()) { 74 | final request = await HttpClient().getUrl(model.modelUri); 75 | 76 | final response = await request.close(); 77 | 78 | final bytes = await consolidateHttpClientResponseBytes(response); 79 | 80 | final File file = File(await getPath(model)); 81 | await file.writeAsBytes(bytes); 82 | 83 | return file.path; 84 | } else { 85 | return await getPath(model); 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # Whisper GGML 4 | 5 | _OpenAI Whisper ASR (Automatic Speech Recognition) for Flutter using [Whisper.cpp](https://github.com/ggerganov/whisper.cpp)._ 6 | 7 |

8 | 9 | pub 10 | 11 | Buy Me A Coffee 12 |

13 |
14 | 15 | 16 | ## Supported platforms 17 | 18 | 19 | | Platform | Supported | 20 | |-----------|-----------| 21 | | Android | ✅ | 22 | | iOS | ✅ | 23 | | MacOS | ✅ | 24 | 25 | 26 | ## Features 27 | 28 | 29 | 30 | - Automatic Speech Recognition integration for Flutter apps. 31 | 32 | - Supports automatic model downloading and initialization. Can be configured to work fully offline by using `assets` models (see example folder). 33 | 34 | - Seamless iOS and Android support with optimized performance. 35 | 36 | - Can be configured to use specific language ("en", "fr", "de", etc) or auto-detect ("auto"). 37 | 38 | - Utilizes [CORE ML](https://github.com/ggml-org/whisper.cpp/tree/master?tab=readme-ov-file#core-ml-support) for enhanced processing on iOS devices. 39 | 40 | 41 | 42 | ## Installation 43 | 44 | 45 | 46 | To use this library in your Flutter project, follow these steps: 47 | 48 | 49 | 50 | 1. Add the library to your Flutter project's `pubspec.yaml`: 51 | 52 | ```yaml 53 | dependencies: 54 | whisper_ggml: ^1.7.0 55 | ``` 56 | 57 | 2. Run `flutter pub get` to install the package. 58 | 59 | 60 | 61 | ## Usage 62 | 63 | 64 | 65 | To integrate Whisper ASR in your Flutter app: 66 | 67 | 68 | 69 | 1. Import the package: 70 | 71 | ```dart 72 | import 'package:whisper_ggml/whisper_ggml.dart'; 73 | ``` 74 | 75 | 76 | 77 | 2. Pick your model. Smaller models are more performant, but the accuracy may be lower. Recommended models are `tiny` and `small`. 78 | 79 | ```dart 80 | final model = WhisperModel.tiny; 81 | ``` 82 | 83 | 3. Declare `WhisperController` and use it for transcription: 84 | 85 | ```dart 86 | final controller = WhisperController(); 87 | 88 | final result = await controller.transcribe( 89 | model: model, /// Selected WhisperModel 90 | audioPath: audioPath, /// Path to .wav file 91 | lang: 'en', /// Language to transcribe 92 | ); 93 | ``` 94 | 95 | 4. Use the `result` variable to access the transcription result: 96 | 97 | ```dart 98 | if (result?.transcription.text != null) { 99 | /// Do something with the transcription 100 | print(result!.transcription.text); 101 | } 102 | ``` 103 | 104 | 105 | 106 | ## Notes 107 | 108 | 109 | 110 | Transcription processing time is about `5x` times faster when running in release mode. -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/src/whisper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:ffi'; 3 | import 'dart:isolate'; 4 | 5 | import 'package:ffi/ffi.dart'; 6 | import 'package:flutter/foundation.dart'; 7 | import 'package:universal_io/io.dart'; 8 | import 'package:whisper_ggml/src/models/whisper_model.dart'; 9 | import 'package:whisper_ggml/src/whisper_audio_convert.dart'; 10 | 11 | import 'models/requests/transcribe_request.dart'; 12 | import 'models/requests/transcribe_request_dto.dart'; 13 | import 'models/requests/version_request.dart'; 14 | import 'models/responses/whisper_transcribe_response.dart'; 15 | import 'models/responses/whisper_version_response.dart'; 16 | import 'models/whisper_dto.dart'; 17 | 18 | export 'models/_models.dart'; 19 | export 'whisper_audio_convert.dart'; 20 | 21 | /// Native request type 22 | typedef WReqNative = Pointer Function(Pointer body); 23 | 24 | /// Entry point 25 | class Whisper { 26 | /// [model] is required 27 | /// [modelDir] is path where downloaded model will be stored. 28 | /// Default to library directory 29 | const Whisper({required this.model, this.modelDir}); 30 | 31 | /// model used for transcription 32 | final WhisperModel model; 33 | 34 | /// override of model storage path 35 | final String? modelDir; 36 | 37 | DynamicLibrary _openLib() { 38 | if (Platform.isAndroid) { 39 | return DynamicLibrary.open('libwhisper.so'); 40 | } else { 41 | return DynamicLibrary.process(); 42 | } 43 | } 44 | 45 | Future> _request({ 46 | required WhisperRequestDto whisperRequest, 47 | }) async { 48 | return Isolate.run(() async { 49 | final Pointer data = 50 | whisperRequest.toRequestString().toNativeUtf8(); 51 | final Pointer res = _openLib() 52 | .lookupFunction('request') 53 | .call(data); 54 | 55 | final Map result = 56 | json.decode(res.toDartString()) as Map; 57 | 58 | malloc.free(data); 59 | return result; 60 | }); 61 | } 62 | 63 | /// Transcribe audio file to text 64 | Future transcribe({ 65 | required TranscribeRequest transcribeRequest, 66 | required String modelPath, 67 | }) async { 68 | try { 69 | final WhisperAudioConvert converter = WhisperAudioConvert( 70 | audioInput: File(transcribeRequest.audio), 71 | audioOutput: File('${transcribeRequest.audio}.wav'), 72 | ); 73 | 74 | final File? convertedFile = await converter.convert(); 75 | 76 | final TranscribeRequest req = transcribeRequest.copyWith( 77 | audio: convertedFile?.path ?? transcribeRequest.audio, 78 | ); 79 | 80 | final Map result = await _request( 81 | whisperRequest: TranscribeRequestDto.fromTranscribeRequest( 82 | req, 83 | modelPath, 84 | ), 85 | ); 86 | 87 | if (result['text'] == null) { 88 | throw Exception(result['message']); 89 | } 90 | return WhisperTranscribeResponse.fromJson(result); 91 | } catch (e) { 92 | debugPrint(e.toString()); 93 | rethrow; 94 | } 95 | } 96 | 97 | /// Get whisper version 98 | Future getVersion() async { 99 | final Map result = await _request( 100 | whisperRequest: const VersionRequest(), 101 | ); 102 | 103 | final WhisperVersionResponse response = WhisperVersionResponse.fromJson( 104 | result, 105 | ); 106 | return response.message; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 43 | 49 | 50 | 51 | 52 | 53 | 64 | 66 | 72 | 73 | 74 | 75 | 81 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 38 | 39 | 40 | 41 | 44 | 50 | 51 | 52 | 53 | 54 | 66 | 68 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /lib/src/models/requests/version_request.freezed.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // coverage:ignore-file 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'version_request.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | // dart format off 13 | T _$identity(T value) => value; 14 | 15 | /// @nodoc 16 | mixin _$VersionRequest { 17 | @override 18 | bool operator ==(Object other) { 19 | return identical(this, other) || 20 | (other.runtimeType == runtimeType && other is VersionRequest); 21 | } 22 | 23 | @override 24 | int get hashCode => runtimeType.hashCode; 25 | 26 | @override 27 | String toString() { 28 | return 'VersionRequest()'; 29 | } 30 | } 31 | 32 | /// @nodoc 33 | class $VersionRequestCopyWith<$Res> { 34 | $VersionRequestCopyWith(VersionRequest _, $Res Function(VersionRequest) __); 35 | } 36 | 37 | /// Adds pattern-matching-related methods to [VersionRequest]. 38 | extension VersionRequestPatterns on VersionRequest { 39 | /// A variant of `map` that fallback to returning `orElse`. 40 | /// 41 | /// It is equivalent to doing: 42 | /// ```dart 43 | /// switch (sealedClass) { 44 | /// case final Subclass value: 45 | /// return ...; 46 | /// case _: 47 | /// return orElse(); 48 | /// } 49 | /// ``` 50 | 51 | @optionalTypeArgs 52 | TResult maybeMap( 53 | TResult Function(_VersionRequest value)? $default, { 54 | required TResult orElse(), 55 | }) { 56 | final _that = this; 57 | switch (_that) { 58 | case _VersionRequest() when $default != null: 59 | return $default(_that); 60 | case _: 61 | return orElse(); 62 | } 63 | } 64 | 65 | /// A `switch`-like method, using callbacks. 66 | /// 67 | /// Callbacks receives the raw object, upcasted. 68 | /// It is equivalent to doing: 69 | /// ```dart 70 | /// switch (sealedClass) { 71 | /// case final Subclass value: 72 | /// return ...; 73 | /// case final Subclass2 value: 74 | /// return ...; 75 | /// } 76 | /// ``` 77 | 78 | @optionalTypeArgs 79 | TResult map( 80 | TResult Function(_VersionRequest value) $default, 81 | ) { 82 | final _that = this; 83 | switch (_that) { 84 | case _VersionRequest(): 85 | return $default(_that); 86 | case _: 87 | throw StateError('Unexpected subclass'); 88 | } 89 | } 90 | 91 | /// A variant of `map` that fallback to returning `null`. 92 | /// 93 | /// It is equivalent to doing: 94 | /// ```dart 95 | /// switch (sealedClass) { 96 | /// case final Subclass value: 97 | /// return ...; 98 | /// case _: 99 | /// return null; 100 | /// } 101 | /// ``` 102 | 103 | @optionalTypeArgs 104 | TResult? mapOrNull( 105 | TResult? Function(_VersionRequest value)? $default, 106 | ) { 107 | final _that = this; 108 | switch (_that) { 109 | case _VersionRequest() when $default != null: 110 | return $default(_that); 111 | case _: 112 | return null; 113 | } 114 | } 115 | 116 | /// A variant of `when` that fallback to an `orElse` callback. 117 | /// 118 | /// It is equivalent to doing: 119 | /// ```dart 120 | /// switch (sealedClass) { 121 | /// case Subclass(:final field): 122 | /// return ...; 123 | /// case _: 124 | /// return orElse(); 125 | /// } 126 | /// ``` 127 | 128 | @optionalTypeArgs 129 | TResult maybeWhen( 130 | TResult Function()? $default, { 131 | required TResult orElse(), 132 | }) { 133 | final _that = this; 134 | switch (_that) { 135 | case _VersionRequest() when $default != null: 136 | return $default(); 137 | case _: 138 | return orElse(); 139 | } 140 | } 141 | 142 | /// A `switch`-like method, using callbacks. 143 | /// 144 | /// As opposed to `map`, this offers destructuring. 145 | /// It is equivalent to doing: 146 | /// ```dart 147 | /// switch (sealedClass) { 148 | /// case Subclass(:final field): 149 | /// return ...; 150 | /// case Subclass2(:final field2): 151 | /// return ...; 152 | /// } 153 | /// ``` 154 | 155 | @optionalTypeArgs 156 | TResult when( 157 | TResult Function() $default, 158 | ) { 159 | final _that = this; 160 | switch (_that) { 161 | case _VersionRequest(): 162 | return $default(); 163 | case _: 164 | throw StateError('Unexpected subclass'); 165 | } 166 | } 167 | 168 | /// A variant of `when` that fallback to returning `null` 169 | /// 170 | /// It is equivalent to doing: 171 | /// ```dart 172 | /// switch (sealedClass) { 173 | /// case Subclass(:final field): 174 | /// return ...; 175 | /// case _: 176 | /// return null; 177 | /// } 178 | /// ``` 179 | 180 | @optionalTypeArgs 181 | TResult? whenOrNull( 182 | TResult? Function()? $default, 183 | ) { 184 | final _that = this; 185 | switch (_that) { 186 | case _VersionRequest() when $default != null: 187 | return $default(); 188 | case _: 189 | return null; 190 | } 191 | } 192 | } 193 | 194 | /// @nodoc 195 | 196 | class _VersionRequest extends VersionRequest { 197 | const _VersionRequest() : super._(); 198 | 199 | @override 200 | bool operator ==(Object other) { 201 | return identical(this, other) || 202 | (other.runtimeType == runtimeType && other is _VersionRequest); 203 | } 204 | 205 | @override 206 | int get hashCode => runtimeType.hashCode; 207 | 208 | @override 209 | String toString() { 210 | return 'VersionRequest()'; 211 | } 212 | } 213 | 214 | // dart format on 215 | -------------------------------------------------------------------------------- /example/lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter/services.dart'; 5 | import 'package:path_provider/path_provider.dart'; 6 | import 'package:whisper_ggml/whisper_ggml.dart'; 7 | import 'package:record/record.dart'; 8 | 9 | void main() { 10 | runApp(const MyApp()); 11 | } 12 | 13 | class MyApp extends StatelessWidget { 14 | const MyApp({super.key}); 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return MaterialApp( 19 | title: 'Whisper ggml example', 20 | theme: ThemeData( 21 | colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), 22 | useMaterial3: true, 23 | ), 24 | home: const MyHomePage(), 25 | ); 26 | } 27 | } 28 | 29 | class MyHomePage extends StatefulWidget { 30 | /// Modify this model based on your needs 31 | 32 | const MyHomePage({super.key}); 33 | 34 | @override 35 | State createState() => _MyHomePageState(); 36 | } 37 | 38 | class _MyHomePageState extends State { 39 | final model = WhisperModel.base; 40 | final AudioRecorder audioRecorder = AudioRecorder(); 41 | final WhisperController whisperController = WhisperController(); 42 | String transcribedText = 'Transcribed text will be displayed here'; 43 | bool isProcessing = false; 44 | bool isProcessingFile = false; 45 | bool isListening = false; 46 | 47 | @override 48 | void initState() { 49 | initModel(); 50 | super.initState(); 51 | } 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Scaffold( 56 | appBar: AppBar( 57 | backgroundColor: Theme.of(context).colorScheme.inversePrimary, 58 | title: Text('Whisper ggml example'), 59 | ), 60 | body: SafeArea( 61 | child: Padding( 62 | padding: const EdgeInsets.symmetric(horizontal: 24), 63 | child: Stack( 64 | fit: StackFit.expand, 65 | children: [ 66 | Center( 67 | child: Text( 68 | transcribedText, 69 | style: Theme.of(context).textTheme.headlineMedium, 70 | ), 71 | ), 72 | Positioned( 73 | bottom: 24, 74 | left: 0, 75 | child: Tooltip( 76 | message: 'Transcribe jfk.wav asset file', 77 | child: CircleAvatar( 78 | backgroundColor: Colors.purple.shade100, 79 | maxRadius: 25, 80 | child: isProcessingFile 81 | ? const CircularProgressIndicator() 82 | : IconButton( 83 | onPressed: transcribeJfk, 84 | icon: Icon( 85 | Icons.folder, 86 | ), 87 | ), 88 | ), 89 | ), 90 | ) 91 | ], 92 | ), 93 | ), 94 | ), 95 | floatingActionButton: FloatingActionButton( 96 | onPressed: record, 97 | tooltip: 'Start listening', 98 | child: isProcessing 99 | ? const CircularProgressIndicator() 100 | : Icon( 101 | isListening ? Icons.mic_off : Icons.mic, 102 | color: isListening ? Colors.red : null, 103 | ), 104 | ), 105 | ); 106 | } 107 | 108 | Future initModel() async { 109 | try { 110 | /// Try initializing the model from assets 111 | final bytesBase = 112 | await rootBundle.load('assets/ggml-${model.modelName}.bin'); 113 | final modelPathBase = await whisperController.getPath(model); 114 | final fileBase = File(modelPathBase); 115 | await fileBase.writeAsBytes(bytesBase.buffer 116 | .asUint8List(bytesBase.offsetInBytes, bytesBase.lengthInBytes)); 117 | } catch (e) { 118 | /// On error try downloading the model 119 | await whisperController.downloadModel(model); 120 | } 121 | } 122 | 123 | Future record() async { 124 | if (await audioRecorder.hasPermission()) { 125 | if (await audioRecorder.isRecording()) { 126 | final audioPath = await audioRecorder.stop(); 127 | 128 | if (audioPath != null) { 129 | debugPrint('Stopped listening.'); 130 | 131 | setState(() { 132 | isListening = false; 133 | isProcessing = true; 134 | }); 135 | 136 | final result = await whisperController.transcribe( 137 | model: model, 138 | audioPath: audioPath, 139 | lang: 'en', 140 | ); 141 | 142 | if (mounted) { 143 | setState(() { 144 | isProcessing = false; 145 | }); 146 | } 147 | 148 | if (result?.transcription.text != null) { 149 | setState(() { 150 | transcribedText = result!.transcription.text; 151 | }); 152 | } 153 | } else { 154 | debugPrint('No recording exists.'); 155 | } 156 | } else { 157 | debugPrint('Started listening.'); 158 | 159 | setState(() { 160 | isListening = true; 161 | }); 162 | 163 | final Directory appDirectory = await getTemporaryDirectory(); 164 | await audioRecorder.start(const RecordConfig(), 165 | path: '${appDirectory.path}/test.m4a'); 166 | } 167 | } 168 | } 169 | 170 | Future transcribeJfk() async { 171 | final Directory tempDir = await getTemporaryDirectory(); 172 | final asset = await rootBundle.load('assets/jfk.wav'); 173 | final String jfkPath = "${tempDir.path}/jfk.wav"; 174 | final File convertedFile = await File(jfkPath).writeAsBytes( 175 | asset.buffer.asUint8List(), 176 | ); 177 | 178 | setState(() { 179 | isProcessingFile = true; 180 | }); 181 | 182 | final result = await whisperController.transcribe( 183 | model: model, 184 | audioPath: convertedFile.path, 185 | lang: 'auto', 186 | ); 187 | 188 | setState(() { 189 | isProcessingFile = false; 190 | }); 191 | 192 | if (result?.transcription.text != null) { 193 | setState(() { 194 | transcribedText = result!.transcription.text; 195 | }); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /android/src/whisper/main.cpp: -------------------------------------------------------------------------------- 1 | #include "main.h" 2 | #include "whisper.cpp/whisper.h" 3 | 4 | #define DR_WAV_IMPLEMENTATION 5 | #include "whisper.cpp/examples/dr_wav.h" 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "json/json.hpp" 15 | 16 | using json = nlohmann::json; 17 | 18 | char *jsonToChar(json jsonData) noexcept 19 | { 20 | std::string result = jsonData.dump(); 21 | char *ch = new char[result.size() + 1]; 22 | strcpy(ch, result.c_str()); 23 | return ch; 24 | } 25 | 26 | struct whisper_params 27 | { 28 | int32_t seed = -1; // RNG seed, not used currently 29 | int32_t n_threads = std::min(4, (int32_t)std::thread::hardware_concurrency()); 30 | 31 | int32_t n_processors = 1; 32 | int32_t offset_t_ms = 0; 33 | int32_t offset_n = 0; 34 | int32_t duration_ms = 0; 35 | int32_t max_context = -1; 36 | int32_t max_len = 0; 37 | int32_t best_of = 5; 38 | int32_t beam_size = -1; 39 | 40 | float word_thold = 0.01f; 41 | float entropy_thold = 2.40f; 42 | float logprob_thold = -1.00f; 43 | 44 | bool verbose = false; 45 | bool print_special_tokens = false; 46 | bool speed_up = false; 47 | bool translate = false; 48 | bool diarize = false; 49 | bool no_fallback = false; 50 | bool output_txt = false; 51 | bool output_vtt = false; 52 | bool output_srt = false; 53 | bool output_wts = false; 54 | bool output_csv = false; 55 | bool print_special = false; 56 | bool print_colors = false; 57 | bool print_progress = false; 58 | bool no_timestamps = false; 59 | bool split_on_word = false; 60 | 61 | std::string language = "auto"; 62 | std::string prompt; 63 | std::string model = "models/ggml-tiny.bin"; 64 | std::string audio = "samples/jfk.wav"; 65 | std::vector fname_inp = {}; 66 | std::vector fname_outp = {}; 67 | }; 68 | 69 | struct whisper_print_user_data 70 | { 71 | const whisper_params *params; 72 | 73 | const std::vector> *pcmf32s; 74 | }; 75 | 76 | json transcribe(json jsonBody) noexcept 77 | { 78 | whisper_params params; 79 | 80 | params.n_threads = jsonBody["threads"]; 81 | params.verbose = jsonBody["is_verbose"]; 82 | params.translate = jsonBody["is_translate"]; 83 | params.language = jsonBody["language"]; 84 | params.print_special_tokens = jsonBody["is_special_tokens"]; 85 | params.no_timestamps = jsonBody["is_no_timestamps"]; 86 | params.model = jsonBody["model"]; 87 | params.audio = jsonBody["audio"]; 88 | params.split_on_word = jsonBody["split_on_word"]; 89 | params.diarize = jsonBody["diarize"]; 90 | json jsonResult; 91 | jsonResult["@type"] = "transcribe"; 92 | 93 | if (params.language != "" && params.language != "auto" && whisper_lang_id(params.language.c_str()) == -1) 94 | { 95 | jsonResult["@type"] = "error"; 96 | jsonResult["message"] = "error: unknown language = " + params.language; 97 | return jsonResult; 98 | } 99 | 100 | if (params.seed < 0) 101 | { 102 | params.seed = time(NULL); 103 | } 104 | 105 | // whisper init 106 | struct whisper_context *ctx = whisper_init_from_file(params.model.c_str()); 107 | std::string text_result = ""; 108 | const auto fname_inp = params.audio; 109 | // WAV input 110 | std::vector pcmf32; 111 | { 112 | drwav wav; 113 | if (!drwav_init_file(&wav, fname_inp.c_str(), NULL)) 114 | { 115 | jsonResult["@type"] = "error"; 116 | jsonResult["message"] = " failed to open WAV file "; 117 | return jsonResult; 118 | } 119 | 120 | if (wav.channels != 1 && wav.channels != 2) 121 | { 122 | jsonResult["@type"] = "error"; 123 | jsonResult["message"] = "must be mono or stereo"; 124 | return jsonResult; 125 | } 126 | 127 | if (wav.sampleRate != WHISPER_SAMPLE_RATE) 128 | { 129 | jsonResult["@type"] = "error"; 130 | jsonResult["message"] = "WAV file must be 16 kHz"; 131 | return jsonResult; 132 | } 133 | 134 | if (wav.bitsPerSample != 16) 135 | { 136 | jsonResult["@type"] = "error"; 137 | jsonResult["message"] = "WAV file must be 16 bit"; 138 | return jsonResult; 139 | } 140 | 141 | int n = wav.totalPCMFrameCount; 142 | 143 | std::vector pcm16; 144 | pcm16.resize(n * wav.channels); 145 | drwav_read_pcm_frames_s16(&wav, n, pcm16.data()); 146 | drwav_uninit(&wav); 147 | 148 | // convert to mono, float 149 | pcmf32.resize(n); 150 | if (wav.channels == 1) 151 | { 152 | for (int i = 0; i < n; i++) 153 | { 154 | pcmf32[i] = float(pcm16[i]) / 32768.0f; 155 | } 156 | } 157 | else 158 | { 159 | for (int i = 0; i < n; i++) 160 | { 161 | pcmf32[i] = float(pcm16[2 * i] + pcm16[2 * i + 1]) / 65536.0f; 162 | } 163 | } 164 | } 165 | 166 | { 167 | if (params.language == "" && params.language == "auto") 168 | { 169 | params.language = "auto"; 170 | params.translate = false; 171 | } 172 | } 173 | // run the inference 174 | { 175 | whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); 176 | 177 | wparams.print_realtime = false; 178 | wparams.print_progress = false; 179 | wparams.print_timestamps = !params.no_timestamps; 180 | // wparams.print_special_tokens = params.print_special_tokens; 181 | wparams.translate = params.translate; 182 | wparams.language = params.language.c_str(); 183 | wparams.n_threads = params.n_threads; 184 | wparams.split_on_word = params.split_on_word; 185 | 186 | if (params.split_on_word) { 187 | wparams.max_len = 1; 188 | wparams.token_timestamps = true; 189 | } 190 | 191 | if (whisper_full(ctx, wparams, pcmf32.data(), pcmf32.size()) != 0) 192 | { 193 | jsonResult["@type"] = "error"; 194 | jsonResult["message"] = "failed to process audio"; 195 | return jsonResult; 196 | } 197 | 198 | 199 | 200 | // print result; 201 | if (!wparams.print_realtime) 202 | { 203 | 204 | const int n_segments = whisper_full_n_segments(ctx); 205 | 206 | std::vector segmentsJson = {}; 207 | 208 | for (int i = 0; i < n_segments; ++i) 209 | { 210 | const char *text = whisper_full_get_segment_text(ctx, i); 211 | 212 | std::string str(text); 213 | text_result += str; 214 | if (params.no_timestamps) 215 | { 216 | // printf("%s", text); 217 | // fflush(stdout); 218 | } else { 219 | json jsonSegment; 220 | const int64_t t0 = whisper_full_get_segment_t0(ctx, i); 221 | const int64_t t1 = whisper_full_get_segment_t1(ctx, i); 222 | 223 | // printf("[%s --> %s] %s\n", to_timestamp(t0).c_str(), to_timestamp(t1).c_str(), text); 224 | 225 | jsonSegment["from_ts"] = t0; 226 | jsonSegment["to_ts"] = t1; 227 | jsonSegment["text"] = text; 228 | 229 | segmentsJson.push_back(jsonSegment); 230 | } 231 | } 232 | 233 | if (!params.no_timestamps) { 234 | jsonResult["segments"] = segmentsJson; 235 | } 236 | } 237 | } 238 | jsonResult["text"] = text_result; 239 | 240 | whisper_free(ctx); 241 | return jsonResult; 242 | } 243 | extern "C" 244 | { 245 | FUNCTION_ATTRIBUTE 246 | char *request(char *body) 247 | { 248 | try 249 | { 250 | json jsonBody = json::parse(body); 251 | json jsonResult; 252 | 253 | if (jsonBody["@type"] == "getTextFromWavFile") 254 | { 255 | try 256 | { 257 | return jsonToChar(transcribe(jsonBody)); 258 | } 259 | catch (const std::exception &e) 260 | { 261 | jsonResult["@type"] = "error"; 262 | jsonResult["message"] = e.what(); 263 | return jsonToChar(jsonResult); 264 | } 265 | } 266 | if (jsonBody["@type"] == "getVersion") 267 | { 268 | jsonResult["@type"] = "version"; 269 | jsonResult["message"] = "lib version: v1.0.1"; 270 | return jsonToChar(jsonResult); 271 | } 272 | 273 | jsonResult["@type"] = "error"; 274 | jsonResult["message"] = "method not found"; 275 | return jsonToChar(jsonResult); 276 | } 277 | catch (const std::exception &e) 278 | { 279 | json jsonResult; 280 | jsonResult["@type"] = "error"; 281 | jsonResult["message"] = e.what(); 282 | return jsonToChar(jsonResult); 283 | } 284 | } 285 | } -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_version_response.freezed.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // coverage:ignore-file 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'whisper_version_response.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | // dart format off 13 | T _$identity(T value) => value; 14 | 15 | /// @nodoc 16 | mixin _$WhisperVersionResponse { 17 | @JsonKey(name: '@type') 18 | String get type; 19 | String get message; 20 | 21 | /// Create a copy of WhisperVersionResponse 22 | /// with the given fields replaced by the non-null parameter values. 23 | @JsonKey(includeFromJson: false, includeToJson: false) 24 | @pragma('vm:prefer-inline') 25 | $WhisperVersionResponseCopyWith get copyWith => 26 | _$WhisperVersionResponseCopyWithImpl( 27 | this as WhisperVersionResponse, _$identity); 28 | 29 | /// Serializes this WhisperVersionResponse to a JSON map. 30 | Map toJson(); 31 | 32 | @override 33 | bool operator ==(Object other) { 34 | return identical(this, other) || 35 | (other.runtimeType == runtimeType && 36 | other is WhisperVersionResponse && 37 | (identical(other.type, type) || other.type == type) && 38 | (identical(other.message, message) || other.message == message)); 39 | } 40 | 41 | @JsonKey(includeFromJson: false, includeToJson: false) 42 | @override 43 | int get hashCode => Object.hash(runtimeType, type, message); 44 | 45 | @override 46 | String toString() { 47 | return 'WhisperVersionResponse(type: $type, message: $message)'; 48 | } 49 | } 50 | 51 | /// @nodoc 52 | abstract mixin class $WhisperVersionResponseCopyWith<$Res> { 53 | factory $WhisperVersionResponseCopyWith(WhisperVersionResponse value, 54 | $Res Function(WhisperVersionResponse) _then) = 55 | _$WhisperVersionResponseCopyWithImpl; 56 | @useResult 57 | $Res call({@JsonKey(name: '@type') String type, String message}); 58 | } 59 | 60 | /// @nodoc 61 | class _$WhisperVersionResponseCopyWithImpl<$Res> 62 | implements $WhisperVersionResponseCopyWith<$Res> { 63 | _$WhisperVersionResponseCopyWithImpl(this._self, this._then); 64 | 65 | final WhisperVersionResponse _self; 66 | final $Res Function(WhisperVersionResponse) _then; 67 | 68 | /// Create a copy of WhisperVersionResponse 69 | /// with the given fields replaced by the non-null parameter values. 70 | @pragma('vm:prefer-inline') 71 | @override 72 | $Res call({ 73 | Object? type = null, 74 | Object? message = null, 75 | }) { 76 | return _then(_self.copyWith( 77 | type: null == type 78 | ? _self.type 79 | : type // ignore: cast_nullable_to_non_nullable 80 | as String, 81 | message: null == message 82 | ? _self.message 83 | : message // ignore: cast_nullable_to_non_nullable 84 | as String, 85 | )); 86 | } 87 | } 88 | 89 | /// Adds pattern-matching-related methods to [WhisperVersionResponse]. 90 | extension WhisperVersionResponsePatterns on WhisperVersionResponse { 91 | /// A variant of `map` that fallback to returning `orElse`. 92 | /// 93 | /// It is equivalent to doing: 94 | /// ```dart 95 | /// switch (sealedClass) { 96 | /// case final Subclass value: 97 | /// return ...; 98 | /// case _: 99 | /// return orElse(); 100 | /// } 101 | /// ``` 102 | 103 | @optionalTypeArgs 104 | TResult maybeMap( 105 | TResult Function(_WhisperVersionResponse value)? $default, { 106 | required TResult orElse(), 107 | }) { 108 | final _that = this; 109 | switch (_that) { 110 | case _WhisperVersionResponse() when $default != null: 111 | return $default(_that); 112 | case _: 113 | return orElse(); 114 | } 115 | } 116 | 117 | /// A `switch`-like method, using callbacks. 118 | /// 119 | /// Callbacks receives the raw object, upcasted. 120 | /// It is equivalent to doing: 121 | /// ```dart 122 | /// switch (sealedClass) { 123 | /// case final Subclass value: 124 | /// return ...; 125 | /// case final Subclass2 value: 126 | /// return ...; 127 | /// } 128 | /// ``` 129 | 130 | @optionalTypeArgs 131 | TResult map( 132 | TResult Function(_WhisperVersionResponse value) $default, 133 | ) { 134 | final _that = this; 135 | switch (_that) { 136 | case _WhisperVersionResponse(): 137 | return $default(_that); 138 | case _: 139 | throw StateError('Unexpected subclass'); 140 | } 141 | } 142 | 143 | /// A variant of `map` that fallback to returning `null`. 144 | /// 145 | /// It is equivalent to doing: 146 | /// ```dart 147 | /// switch (sealedClass) { 148 | /// case final Subclass value: 149 | /// return ...; 150 | /// case _: 151 | /// return null; 152 | /// } 153 | /// ``` 154 | 155 | @optionalTypeArgs 156 | TResult? mapOrNull( 157 | TResult? Function(_WhisperVersionResponse value)? $default, 158 | ) { 159 | final _that = this; 160 | switch (_that) { 161 | case _WhisperVersionResponse() when $default != null: 162 | return $default(_that); 163 | case _: 164 | return null; 165 | } 166 | } 167 | 168 | /// A variant of `when` that fallback to an `orElse` callback. 169 | /// 170 | /// It is equivalent to doing: 171 | /// ```dart 172 | /// switch (sealedClass) { 173 | /// case Subclass(:final field): 174 | /// return ...; 175 | /// case _: 176 | /// return orElse(); 177 | /// } 178 | /// ``` 179 | 180 | @optionalTypeArgs 181 | TResult maybeWhen( 182 | TResult Function(@JsonKey(name: '@type') String type, String message)? 183 | $default, { 184 | required TResult orElse(), 185 | }) { 186 | final _that = this; 187 | switch (_that) { 188 | case _WhisperVersionResponse() when $default != null: 189 | return $default(_that.type, _that.message); 190 | case _: 191 | return orElse(); 192 | } 193 | } 194 | 195 | /// A `switch`-like method, using callbacks. 196 | /// 197 | /// As opposed to `map`, this offers destructuring. 198 | /// It is equivalent to doing: 199 | /// ```dart 200 | /// switch (sealedClass) { 201 | /// case Subclass(:final field): 202 | /// return ...; 203 | /// case Subclass2(:final field2): 204 | /// return ...; 205 | /// } 206 | /// ``` 207 | 208 | @optionalTypeArgs 209 | TResult when( 210 | TResult Function(@JsonKey(name: '@type') String type, String message) 211 | $default, 212 | ) { 213 | final _that = this; 214 | switch (_that) { 215 | case _WhisperVersionResponse(): 216 | return $default(_that.type, _that.message); 217 | case _: 218 | throw StateError('Unexpected subclass'); 219 | } 220 | } 221 | 222 | /// A variant of `when` that fallback to returning `null` 223 | /// 224 | /// It is equivalent to doing: 225 | /// ```dart 226 | /// switch (sealedClass) { 227 | /// case Subclass(:final field): 228 | /// return ...; 229 | /// case _: 230 | /// return null; 231 | /// } 232 | /// ``` 233 | 234 | @optionalTypeArgs 235 | TResult? whenOrNull( 236 | TResult? Function(@JsonKey(name: '@type') String type, String message)? 237 | $default, 238 | ) { 239 | final _that = this; 240 | switch (_that) { 241 | case _WhisperVersionResponse() when $default != null: 242 | return $default(_that.type, _that.message); 243 | case _: 244 | return null; 245 | } 246 | } 247 | } 248 | 249 | /// @nodoc 250 | @JsonSerializable() 251 | class _WhisperVersionResponse extends WhisperVersionResponse { 252 | const _WhisperVersionResponse( 253 | {@JsonKey(name: '@type') required this.type, required this.message}) 254 | : super._(); 255 | factory _WhisperVersionResponse.fromJson(Map json) => 256 | _$WhisperVersionResponseFromJson(json); 257 | 258 | @override 259 | @JsonKey(name: '@type') 260 | final String type; 261 | @override 262 | final String message; 263 | 264 | /// Create a copy of WhisperVersionResponse 265 | /// with the given fields replaced by the non-null parameter values. 266 | @override 267 | @JsonKey(includeFromJson: false, includeToJson: false) 268 | @pragma('vm:prefer-inline') 269 | _$WhisperVersionResponseCopyWith<_WhisperVersionResponse> get copyWith => 270 | __$WhisperVersionResponseCopyWithImpl<_WhisperVersionResponse>( 271 | this, _$identity); 272 | 273 | @override 274 | Map toJson() { 275 | return _$WhisperVersionResponseToJson( 276 | this, 277 | ); 278 | } 279 | 280 | @override 281 | bool operator ==(Object other) { 282 | return identical(this, other) || 283 | (other.runtimeType == runtimeType && 284 | other is _WhisperVersionResponse && 285 | (identical(other.type, type) || other.type == type) && 286 | (identical(other.message, message) || other.message == message)); 287 | } 288 | 289 | @JsonKey(includeFromJson: false, includeToJson: false) 290 | @override 291 | int get hashCode => Object.hash(runtimeType, type, message); 292 | 293 | @override 294 | String toString() { 295 | return 'WhisperVersionResponse(type: $type, message: $message)'; 296 | } 297 | } 298 | 299 | /// @nodoc 300 | abstract mixin class _$WhisperVersionResponseCopyWith<$Res> 301 | implements $WhisperVersionResponseCopyWith<$Res> { 302 | factory _$WhisperVersionResponseCopyWith(_WhisperVersionResponse value, 303 | $Res Function(_WhisperVersionResponse) _then) = 304 | __$WhisperVersionResponseCopyWithImpl; 305 | @override 306 | @useResult 307 | $Res call({@JsonKey(name: '@type') String type, String message}); 308 | } 309 | 310 | /// @nodoc 311 | class __$WhisperVersionResponseCopyWithImpl<$Res> 312 | implements _$WhisperVersionResponseCopyWith<$Res> { 313 | __$WhisperVersionResponseCopyWithImpl(this._self, this._then); 314 | 315 | final _WhisperVersionResponse _self; 316 | final $Res Function(_WhisperVersionResponse) _then; 317 | 318 | /// Create a copy of WhisperVersionResponse 319 | /// with the given fields replaced by the non-null parameter values. 320 | @override 321 | @pragma('vm:prefer-inline') 322 | $Res call({ 323 | Object? type = null, 324 | Object? message = null, 325 | }) { 326 | return _then(_WhisperVersionResponse( 327 | type: null == type 328 | ? _self.type 329 | : type // ignore: cast_nullable_to_non_nullable 330 | as String, 331 | message: null == message 332 | ? _self.message 333 | : message // ignore: cast_nullable_to_non_nullable 334 | as String, 335 | )); 336 | } 337 | } 338 | 339 | // dart format on 340 | -------------------------------------------------------------------------------- /ios/Classes/whisper_flutter_plus.cpp: -------------------------------------------------------------------------------- 1 | #include "whisper/whisper.h" 2 | 3 | #define DR_WAV_IMPLEMENTATION 4 | #include "whisper/examples/dr_wav.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include "json/json.hpp" 15 | #include 16 | 17 | using json = nlohmann::json; 18 | 19 | void print(std::string value) 20 | { 21 | std::cout << value << std::endl; 22 | } 23 | 24 | char *jsonToChar(json jsonData) 25 | { 26 | std::string result = jsonData.dump(); 27 | char *ch = new char[result.size() + 1]; 28 | strcpy(ch, result.c_str()); 29 | return ch; 30 | } 31 | 32 | std::string charToString(char *value) 33 | { 34 | std::string result(value); 35 | return result; 36 | } 37 | 38 | char *stringToChar(std::string value) 39 | { 40 | char *ch = new char[value.size() + 1]; 41 | strcpy(ch, value.c_str()); 42 | return ch; 43 | } 44 | 45 | // // 500 -> 00:05.000 46 | // // 6000 -> 01:00.000 47 | // std::string to_timestamp(int64_t t) 48 | // { 49 | // int64_t sec = t / 100; 50 | // int64_t msec = t - sec * 100; 51 | // int64_t min = sec / 60; 52 | // sec = sec - min * 60; 53 | 54 | // char buf[32]; 55 | // snprintf(buf, sizeof(buf), "%02d:%02d.%03d", (int)min, (int)sec, (int)msec); 56 | 57 | // return std::string(buf); 58 | // } 59 | 60 | // Terminal color map. 10 colors grouped in ranges [0.0, 0.1, ..., 0.9] 61 | // Lowest is red, middle is yellow, highest is green. 62 | const std::vector k_colors = { 63 | "\033[38;5;196m", 64 | "\033[38;5;202m", 65 | "\033[38;5;208m", 66 | "\033[38;5;214m", 67 | "\033[38;5;220m", 68 | "\033[38;5;226m", 69 | "\033[38;5;190m", 70 | "\033[38;5;154m", 71 | "\033[38;5;118m", 72 | "\033[38;5;82m", 73 | }; 74 | 75 | // 500 -> 00:05.000 76 | // 6000 -> 01:00.000 77 | std::string to_timestamp(int64_t t, bool comma = false) 78 | { 79 | int64_t msec = t * 10; 80 | int64_t hr = msec / (1000 * 60 * 60); 81 | msec = msec - hr * (1000 * 60 * 60); 82 | int64_t min = msec / (1000 * 60); 83 | msec = msec - min * (1000 * 60); 84 | int64_t sec = msec / 1000; 85 | msec = msec - sec * 1000; 86 | 87 | char buf[32]; 88 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d%s%03d", (int)hr, (int)min, (int)sec, comma ? "," : ".", (int)msec); 89 | 90 | return std::string(buf); 91 | } 92 | 93 | int timestamp_to_sample(int64_t t, int n_samples) 94 | { 95 | return std::max(0, std::min((int)n_samples - 1, (int)((t * WHISPER_SAMPLE_RATE) / 100))); 96 | } 97 | 98 | // command-line parameters 99 | struct whisper_params 100 | { 101 | int32_t seed = -1; // RNG seed, not used currently 102 | int32_t n_threads = std::min(4, (int32_t)std::thread::hardware_concurrency()); 103 | 104 | int32_t n_processors = 1; 105 | int32_t offset_t_ms = 0; 106 | int32_t offset_n = 0; 107 | int32_t duration_ms = 0; 108 | int32_t max_context = -1; 109 | int32_t max_len = 0; 110 | int32_t best_of = 5; 111 | int32_t beam_size = -1; 112 | 113 | float word_thold = 0.01f; 114 | float entropy_thold = 2.40f; 115 | float logprob_thold = -1.00f; 116 | 117 | bool verbose = false; 118 | bool print_special_tokens = false; 119 | bool speed_up = false; 120 | bool translate = false; 121 | bool diarize = false; 122 | bool no_fallback = false; 123 | bool output_txt = false; 124 | bool output_vtt = false; 125 | bool output_srt = false; 126 | bool output_wts = false; 127 | bool output_csv = false; 128 | bool print_special = false; 129 | bool print_colors = false; 130 | bool print_progress = false; 131 | bool no_timestamps = false; 132 | bool split_on_word = false; 133 | 134 | std::string language = "id"; 135 | std::string prompt; 136 | std::string model = "models/ggml-model-whisper-small.bin"; 137 | std::string audio = "samples/jfk.wav"; 138 | std::vector fname_inp = {}; 139 | std::vector fname_outp = {}; 140 | }; 141 | 142 | struct whisper_print_user_data 143 | { 144 | const whisper_params *params; 145 | 146 | const std::vector> *pcmf32s; 147 | }; 148 | 149 | json transcribe(json jsonBody) 150 | { 151 | whisper_params params; 152 | 153 | params.n_threads = jsonBody["threads"]; 154 | params.verbose = jsonBody["is_verbose"]; 155 | params.translate = jsonBody["is_translate"]; 156 | params.language = jsonBody["language"]; 157 | params.print_special_tokens = jsonBody["is_special_tokens"]; 158 | params.no_timestamps = jsonBody["is_no_timestamps"]; 159 | params.model = jsonBody["model"]; 160 | params.audio = jsonBody["audio"]; 161 | params.split_on_word = jsonBody["split_on_word"]; 162 | params.diarize = jsonBody["diarize"]; 163 | json jsonResult; 164 | jsonResult["@type"] = "transcribe"; 165 | 166 | if (whisper_lang_id(params.language.c_str()) == -1) 167 | { 168 | jsonResult["@type"] = "error"; 169 | jsonResult["message"] = "error: unknown language"; 170 | return jsonResult; 171 | } 172 | 173 | if (params.seed < 0) 174 | { 175 | params.seed = time(NULL); 176 | } 177 | 178 | // whisper init 179 | struct whisper_context *ctx = whisper_init_from_file(params.model.c_str()); 180 | 181 | // struct whisper_context *ctx = whisper_init(params.model.c_str()); 182 | std::string text_result = ""; 183 | // for (int f = 0; f < (int)params.fname_inp.size(); ++f) 184 | // { 185 | const auto fname_inp = params.audio; 186 | // WAV input 187 | std::vector pcmf32; 188 | { 189 | drwav wav; 190 | if (!drwav_init_file(&wav, fname_inp.c_str(), NULL)) 191 | { 192 | jsonResult["@type"] = "error"; 193 | jsonResult["message"] = " failed to open WAV file "; 194 | return jsonResult; 195 | } 196 | 197 | if (wav.channels != 1 && wav.channels != 2) 198 | { 199 | jsonResult["@type"] = "error"; 200 | jsonResult["message"] = "must be mono or stereo"; 201 | return jsonResult; 202 | } 203 | 204 | if (wav.sampleRate != WHISPER_SAMPLE_RATE) 205 | { 206 | jsonResult["@type"] = "error"; 207 | jsonResult["message"] = "WAV file must be 16 kHz"; 208 | return jsonResult; 209 | } 210 | 211 | if (wav.bitsPerSample != 16) 212 | { 213 | jsonResult["@type"] = "error"; 214 | jsonResult["message"] = "WAV file must be 16 bit"; 215 | return jsonResult; 216 | } 217 | 218 | int n = wav.totalPCMFrameCount; 219 | 220 | std::vector pcm16; 221 | pcm16.resize(n * wav.channels); 222 | drwav_read_pcm_frames_s16(&wav, n, pcm16.data()); 223 | drwav_uninit(&wav); 224 | 225 | // convert to mono, float 226 | pcmf32.resize(n); 227 | if (wav.channels == 1) 228 | { 229 | for (int i = 0; i < n; i++) 230 | { 231 | pcmf32[i] = float(pcm16[i]) / 32768.0f; 232 | } 233 | } 234 | else 235 | { 236 | for (int i = 0; i < n; i++) 237 | { 238 | pcmf32[i] = float(pcm16[2 * i] + pcm16[2 * i + 1]) / 65536.0f; 239 | } 240 | } 241 | } 242 | 243 | // print some info about the processing 244 | { 245 | // printf("\n"); 246 | if (!whisper_is_multilingual(ctx)) 247 | { 248 | if (params.language != "en" || params.translate) 249 | { 250 | params.language = "en"; 251 | params.translate = false; 252 | // printf("%s: WARNING: model is not multilingual, ignoring language and translation options\n", __func__); 253 | } 254 | } 255 | // printf("%s: processing '%s' (%d samples, %.1f sec), %d threads, lang = %s, task = %s, timestamps = %d ...\n", 256 | // __func__, fname_inp.c_str(), int(pcmf32.size()), float(pcmf32.size()) / WHISPER_SAMPLE_RATE, params.n_threads, 257 | // params.language.c_str(), 258 | // params.translate ? "translate" : "transcribe", 259 | // params.no_timestamps ? 0 : 1); 260 | // printf("\n"); 261 | } 262 | // run the inference 263 | { 264 | whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); 265 | 266 | wparams.print_realtime = false; 267 | wparams.print_progress = false; 268 | wparams.print_timestamps = !params.no_timestamps; 269 | // wparams.print_special_tokens = params.print_special_tokens; 270 | wparams.translate = params.translate; 271 | wparams.language = params.language.c_str(); 272 | wparams.n_threads = params.n_threads; 273 | wparams.split_on_word = params.split_on_word; 274 | 275 | if (params.split_on_word) { 276 | wparams.max_len = 1; 277 | wparams.token_timestamps = true; 278 | } 279 | 280 | if (whisper_full(ctx, wparams, pcmf32.data(), pcmf32.size()) != 0) 281 | { 282 | jsonResult["@type"] = "error"; 283 | jsonResult["message"] = "failed to process audio"; 284 | return jsonResult; 285 | } 286 | 287 | 288 | 289 | // print result; 290 | if (!wparams.print_realtime) 291 | { 292 | 293 | const int n_segments = whisper_full_n_segments(ctx); 294 | 295 | std::vector segmentsJson = {}; 296 | 297 | for (int i = 0; i < n_segments; ++i) 298 | { 299 | const char *text = whisper_full_get_segment_text(ctx, i); 300 | 301 | std::string str(text); 302 | text_result += str; 303 | if (params.no_timestamps) 304 | { 305 | // printf("%s", text); 306 | // fflush(stdout); 307 | } else { 308 | json jsonSegment; 309 | const int64_t t0 = whisper_full_get_segment_t0(ctx, i); 310 | const int64_t t1 = whisper_full_get_segment_t1(ctx, i); 311 | 312 | // printf("[%s --> %s] %s\n", to_timestamp(t0).c_str(), to_timestamp(t1).c_str(), text); 313 | 314 | jsonSegment["from_ts"] = t0; 315 | jsonSegment["to_ts"] = t1; 316 | jsonSegment["text"] = text; 317 | 318 | segmentsJson.push_back(jsonSegment); 319 | } 320 | } 321 | 322 | if (!params.no_timestamps) { 323 | jsonResult["segments"] = segmentsJson; 324 | } 325 | } 326 | } 327 | jsonResult["text"] = text_result; 328 | 329 | whisper_free(ctx); 330 | return jsonResult; 331 | } 332 | 333 | extern "C" 334 | { 335 | char *request(char *body) 336 | { 337 | json jsonBody = json::parse(body); 338 | json jsonResult; 339 | 340 | if (jsonBody["@type"] == "getTextFromWavFile") 341 | { 342 | return jsonToChar(transcribe(jsonBody)); 343 | } 344 | 345 | if (jsonBody["@type"] == "getVersion") 346 | { 347 | jsonResult["@type"] = "version"; 348 | jsonResult["message"] = "version lib v0.0.0"; 349 | return jsonToChar(jsonResult); 350 | } 351 | 352 | jsonResult["@type"] = "error"; 353 | jsonResult["message"] = "method not found"; 354 | return jsonToChar(jsonResult); 355 | } 356 | 357 | int main() 358 | { 359 | json jsonBody; 360 | jsonBody["@type"] = "al"; 361 | print(transcribe(jsonBody).dump()); 362 | return 0; 363 | } 364 | } 365 | -------------------------------------------------------------------------------- /macos/Classes/whisper_ggml.cpp: -------------------------------------------------------------------------------- 1 | #include "whisper/whisper.h" 2 | 3 | #define DR_WAV_IMPLEMENTATION 4 | #include "whisper/examples/dr_wav.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include "json/json.hpp" 15 | #include 16 | 17 | using json = nlohmann::json; 18 | 19 | void print(std::string value) 20 | { 21 | std::cout << value << std::endl; 22 | } 23 | 24 | char *jsonToChar(json jsonData) 25 | { 26 | std::string result = jsonData.dump(); 27 | char *ch = new char[result.size() + 1]; 28 | strcpy(ch, result.c_str()); 29 | return ch; 30 | } 31 | 32 | std::string charToString(char *value) 33 | { 34 | std::string result(value); 35 | return result; 36 | } 37 | 38 | char *stringToChar(std::string value) 39 | { 40 | char *ch = new char[value.size() + 1]; 41 | strcpy(ch, value.c_str()); 42 | return ch; 43 | } 44 | 45 | // // 500 -> 00:05.000 46 | // // 6000 -> 01:00.000 47 | // std::string to_timestamp(int64_t t) 48 | // { 49 | // int64_t sec = t / 100; 50 | // int64_t msec = t - sec * 100; 51 | // int64_t min = sec / 60; 52 | // sec = sec - min * 60; 53 | 54 | // char buf[32]; 55 | // snprintf(buf, sizeof(buf), "%02d:%02d.%03d", (int)min, (int)sec, (int)msec); 56 | 57 | // return std::string(buf); 58 | // } 59 | 60 | // Terminal color map. 10 colors grouped in ranges [0.0, 0.1, ..., 0.9] 61 | // Lowest is red, middle is yellow, highest is green. 62 | const std::vector k_colors = { 63 | "\033[38;5;196m", 64 | "\033[38;5;202m", 65 | "\033[38;5;208m", 66 | "\033[38;5;214m", 67 | "\033[38;5;220m", 68 | "\033[38;5;226m", 69 | "\033[38;5;190m", 70 | "\033[38;5;154m", 71 | "\033[38;5;118m", 72 | "\033[38;5;82m", 73 | }; 74 | 75 | // 500 -> 00:05.000 76 | // 6000 -> 01:00.000 77 | std::string to_timestamp(int64_t t, bool comma = false) 78 | { 79 | int64_t msec = t * 10; 80 | int64_t hr = msec / (1000 * 60 * 60); 81 | msec = msec - hr * (1000 * 60 * 60); 82 | int64_t min = msec / (1000 * 60); 83 | msec = msec - min * (1000 * 60); 84 | int64_t sec = msec / 1000; 85 | msec = msec - sec * 1000; 86 | 87 | char buf[32]; 88 | snprintf(buf, sizeof(buf), "%02d:%02d:%02d%s%03d", (int)hr, (int)min, (int)sec, comma ? "," : ".", (int)msec); 89 | 90 | return std::string(buf); 91 | } 92 | 93 | int timestamp_to_sample(int64_t t, int n_samples) 94 | { 95 | return std::max(0, std::min((int)n_samples - 1, (int)((t * WHISPER_SAMPLE_RATE) / 100))); 96 | } 97 | 98 | // command-line parameters 99 | struct whisper_params 100 | { 101 | int32_t seed = -1; // RNG seed, not used currently 102 | int32_t n_threads = std::min(4, (int32_t)std::thread::hardware_concurrency()); 103 | 104 | int32_t n_processors = 1; 105 | int32_t offset_t_ms = 0; 106 | int32_t offset_n = 0; 107 | int32_t duration_ms = 0; 108 | int32_t max_context = -1; 109 | int32_t max_len = 0; 110 | int32_t best_of = 5; 111 | int32_t beam_size = -1; 112 | 113 | float word_thold = 0.01f; 114 | float entropy_thold = 2.40f; 115 | float logprob_thold = -1.00f; 116 | 117 | bool verbose = false; 118 | bool print_special_tokens = false; 119 | bool speed_up = false; 120 | bool translate = false; 121 | bool diarize = false; 122 | bool no_fallback = false; 123 | bool output_txt = false; 124 | bool output_vtt = false; 125 | bool output_srt = false; 126 | bool output_wts = false; 127 | bool output_csv = false; 128 | bool print_special = false; 129 | bool print_colors = false; 130 | bool print_progress = false; 131 | bool no_timestamps = false; 132 | bool split_on_word = false; 133 | 134 | std::string language = "id"; 135 | std::string prompt; 136 | std::string model = "models/ggml-model-whisper-small.bin"; 137 | std::string audio = "samples/jfk.wav"; 138 | std::vector fname_inp = {}; 139 | std::vector fname_outp = {}; 140 | }; 141 | 142 | struct whisper_print_user_data 143 | { 144 | const whisper_params *params; 145 | 146 | const std::vector> *pcmf32s; 147 | }; 148 | 149 | json transcribe(json jsonBody) 150 | { 151 | whisper_params params; 152 | 153 | params.n_threads = jsonBody["threads"]; 154 | params.verbose = jsonBody["is_verbose"]; 155 | params.translate = jsonBody["is_translate"]; 156 | params.language = jsonBody["language"]; 157 | params.print_special_tokens = jsonBody["is_special_tokens"]; 158 | params.no_timestamps = jsonBody["is_no_timestamps"]; 159 | params.model = jsonBody["model"]; 160 | params.audio = jsonBody["audio"]; 161 | params.split_on_word = jsonBody["split_on_word"]; 162 | params.diarize = jsonBody["diarize"]; 163 | json jsonResult; 164 | jsonResult["@type"] = "transcribe"; 165 | 166 | if (whisper_lang_id(params.language.c_str()) == -1) 167 | { 168 | // params.language = nullptr; 169 | 170 | jsonResult["@type"] = "error"; 171 | jsonResult["message"] = "error: unknown language"; 172 | return jsonResult; 173 | } 174 | 175 | if (params.seed < 0) 176 | { 177 | params.seed = time(NULL); 178 | } 179 | 180 | // whisper init 181 | struct whisper_context *ctx = whisper_init_from_file(params.model.c_str()); 182 | 183 | // struct whisper_context *ctx = whisper_init(params.model.c_str()); 184 | std::string text_result = ""; 185 | // for (int f = 0; f < (int)params.fname_inp.size(); ++f) 186 | // { 187 | const auto fname_inp = params.audio; 188 | // WAV input 189 | std::vector pcmf32; 190 | { 191 | drwav wav; 192 | if (!drwav_init_file(&wav, fname_inp.c_str(), NULL)) 193 | { 194 | jsonResult["@type"] = "error"; 195 | jsonResult["message"] = " failed to open WAV file "; 196 | return jsonResult; 197 | } 198 | 199 | if (wav.channels != 1 && wav.channels != 2) 200 | { 201 | jsonResult["@type"] = "error"; 202 | jsonResult["message"] = "must be mono or stereo"; 203 | return jsonResult; 204 | } 205 | 206 | if (wav.sampleRate != WHISPER_SAMPLE_RATE) 207 | { 208 | jsonResult["@type"] = "error"; 209 | jsonResult["message"] = "WAV file must be 16 kHz"; 210 | return jsonResult; 211 | } 212 | 213 | if (wav.bitsPerSample != 16) 214 | { 215 | jsonResult["@type"] = "error"; 216 | jsonResult["message"] = "WAV file must be 16 bit"; 217 | return jsonResult; 218 | } 219 | 220 | int n = wav.totalPCMFrameCount; 221 | 222 | std::vector pcm16; 223 | pcm16.resize(n * wav.channels); 224 | drwav_read_pcm_frames_s16(&wav, n, pcm16.data()); 225 | drwav_uninit(&wav); 226 | 227 | // convert to mono, float 228 | pcmf32.resize(n); 229 | if (wav.channels == 1) 230 | { 231 | for (int i = 0; i < n; i++) 232 | { 233 | pcmf32[i] = float(pcm16[i]) / 32768.0f; 234 | } 235 | } 236 | else 237 | { 238 | for (int i = 0; i < n; i++) 239 | { 240 | pcmf32[i] = float(pcm16[2 * i] + pcm16[2 * i + 1]) / 65536.0f; 241 | } 242 | } 243 | } 244 | 245 | // print some info about the processing 246 | { 247 | // printf("\n"); 248 | if (!whisper_is_multilingual(ctx)) 249 | { 250 | if (params.language != "en" || params.translate) 251 | { 252 | params.language = "en"; 253 | params.translate = false; 254 | // printf("%s: WARNING: model is not multilingual, ignoring language and translation options\n", __func__); 255 | } 256 | } 257 | // printf("%s: processing '%s' (%d samples, %.1f sec), %d threads, lang = %s, task = %s, timestamps = %d ...\n", 258 | // __func__, fname_inp.c_str(), int(pcmf32.size()), float(pcmf32.size()) / WHISPER_SAMPLE_RATE, params.n_threads, 259 | // params.language.c_str(), 260 | // params.translate ? "translate" : "transcribe", 261 | // params.no_timestamps ? 0 : 1); 262 | // printf("\n"); 263 | } 264 | // run the inference 265 | { 266 | whisper_full_params wparams = whisper_full_default_params(WHISPER_SAMPLING_GREEDY); 267 | 268 | wparams.print_realtime = false; 269 | wparams.print_progress = false; 270 | wparams.print_timestamps = !params.no_timestamps; 271 | // wparams.print_special_tokens = params.print_special_tokens; 272 | wparams.translate = params.translate; 273 | 274 | wparams.language = params.language.c_str(); 275 | wparams.n_threads = params.n_threads; 276 | wparams.split_on_word = params.split_on_word; 277 | 278 | if (params.split_on_word) { 279 | wparams.max_len = 1; 280 | wparams.token_timestamps = true; 281 | } 282 | 283 | if (whisper_full(ctx, wparams, pcmf32.data(), pcmf32.size()) != 0) 284 | { 285 | jsonResult["@type"] = "error"; 286 | jsonResult["message"] = "failed to process audio"; 287 | return jsonResult; 288 | } 289 | 290 | 291 | 292 | // print result; 293 | if (!wparams.print_realtime) 294 | { 295 | 296 | const int n_segments = whisper_full_n_segments(ctx); 297 | 298 | std::vector segmentsJson = {}; 299 | 300 | for (int i = 0; i < n_segments; ++i) 301 | { 302 | const char *text = whisper_full_get_segment_text(ctx, i); 303 | 304 | std::string str(text); 305 | text_result += str; 306 | if (params.no_timestamps) 307 | { 308 | // printf("%s", text); 309 | // fflush(stdout); 310 | } else { 311 | json jsonSegment; 312 | const int64_t t0 = whisper_full_get_segment_t0(ctx, i); 313 | const int64_t t1 = whisper_full_get_segment_t1(ctx, i); 314 | 315 | // printf("[%s --> %s] %s\n", to_timestamp(t0).c_str(), to_timestamp(t1).c_str(), text); 316 | 317 | jsonSegment["from_ts"] = t0; 318 | jsonSegment["to_ts"] = t1; 319 | jsonSegment["text"] = text; 320 | 321 | segmentsJson.push_back(jsonSegment); 322 | } 323 | } 324 | 325 | if (!params.no_timestamps) { 326 | jsonResult["segments"] = segmentsJson; 327 | } 328 | } 329 | } 330 | jsonResult["text"] = text_result; 331 | 332 | whisper_free(ctx); 333 | return jsonResult; 334 | } 335 | 336 | extern "C" 337 | { 338 | char *request(char *body) 339 | { 340 | json jsonBody = json::parse(body); 341 | json jsonResult; 342 | 343 | if (jsonBody["@type"] == "getTextFromWavFile") 344 | { 345 | return jsonToChar(transcribe(jsonBody)); 346 | } 347 | 348 | if (jsonBody["@type"] == "getVersion") 349 | { 350 | jsonResult["@type"] = "version"; 351 | jsonResult["message"] = "version lib v0.0.0"; 352 | return jsonToChar(jsonResult); 353 | } 354 | 355 | jsonResult["@type"] = "error"; 356 | jsonResult["message"] = "method not found"; 357 | return jsonToChar(jsonResult); 358 | } 359 | 360 | int main() 361 | { 362 | json jsonBody; 363 | jsonBody["@type"] = "al"; 364 | print(transcribe(jsonBody).dump()); 365 | return 0; 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_response.freezed.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // coverage:ignore-file 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'whisper_transcribe_response.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | // dart format off 13 | T _$identity(T value) => value; 14 | 15 | /// @nodoc 16 | mixin _$WhisperTranscribeResponse { 17 | @JsonKey(name: '@type') 18 | String get type; 19 | String get text; 20 | @JsonKey(name: 'segments') 21 | List? get segments; 22 | 23 | /// Create a copy of WhisperTranscribeResponse 24 | /// with the given fields replaced by the non-null parameter values. 25 | @JsonKey(includeFromJson: false, includeToJson: false) 26 | @pragma('vm:prefer-inline') 27 | $WhisperTranscribeResponseCopyWith get copyWith => 28 | _$WhisperTranscribeResponseCopyWithImpl( 29 | this as WhisperTranscribeResponse, _$identity); 30 | 31 | /// Serializes this WhisperTranscribeResponse to a JSON map. 32 | Map toJson(); 33 | 34 | @override 35 | bool operator ==(Object other) { 36 | return identical(this, other) || 37 | (other.runtimeType == runtimeType && 38 | other is WhisperTranscribeResponse && 39 | (identical(other.type, type) || other.type == type) && 40 | (identical(other.text, text) || other.text == text) && 41 | const DeepCollectionEquality().equals(other.segments, segments)); 42 | } 43 | 44 | @JsonKey(includeFromJson: false, includeToJson: false) 45 | @override 46 | int get hashCode => Object.hash( 47 | runtimeType, type, text, const DeepCollectionEquality().hash(segments)); 48 | 49 | @override 50 | String toString() { 51 | return 'WhisperTranscribeResponse(type: $type, text: $text, segments: $segments)'; 52 | } 53 | } 54 | 55 | /// @nodoc 56 | abstract mixin class $WhisperTranscribeResponseCopyWith<$Res> { 57 | factory $WhisperTranscribeResponseCopyWith(WhisperTranscribeResponse value, 58 | $Res Function(WhisperTranscribeResponse) _then) = 59 | _$WhisperTranscribeResponseCopyWithImpl; 60 | @useResult 61 | $Res call( 62 | {@JsonKey(name: '@type') String type, 63 | String text, 64 | @JsonKey(name: 'segments') List? segments}); 65 | } 66 | 67 | /// @nodoc 68 | class _$WhisperTranscribeResponseCopyWithImpl<$Res> 69 | implements $WhisperTranscribeResponseCopyWith<$Res> { 70 | _$WhisperTranscribeResponseCopyWithImpl(this._self, this._then); 71 | 72 | final WhisperTranscribeResponse _self; 73 | final $Res Function(WhisperTranscribeResponse) _then; 74 | 75 | /// Create a copy of WhisperTranscribeResponse 76 | /// with the given fields replaced by the non-null parameter values. 77 | @pragma('vm:prefer-inline') 78 | @override 79 | $Res call({ 80 | Object? type = null, 81 | Object? text = null, 82 | Object? segments = freezed, 83 | }) { 84 | return _then(_self.copyWith( 85 | type: null == type 86 | ? _self.type 87 | : type // ignore: cast_nullable_to_non_nullable 88 | as String, 89 | text: null == text 90 | ? _self.text 91 | : text // ignore: cast_nullable_to_non_nullable 92 | as String, 93 | segments: freezed == segments 94 | ? _self.segments 95 | : segments // ignore: cast_nullable_to_non_nullable 96 | as List?, 97 | )); 98 | } 99 | } 100 | 101 | /// Adds pattern-matching-related methods to [WhisperTranscribeResponse]. 102 | extension WhisperTranscribeResponsePatterns on WhisperTranscribeResponse { 103 | /// A variant of `map` that fallback to returning `orElse`. 104 | /// 105 | /// It is equivalent to doing: 106 | /// ```dart 107 | /// switch (sealedClass) { 108 | /// case final Subclass value: 109 | /// return ...; 110 | /// case _: 111 | /// return orElse(); 112 | /// } 113 | /// ``` 114 | 115 | @optionalTypeArgs 116 | TResult maybeMap( 117 | TResult Function(_WhisperTranscribeResponse value)? $default, { 118 | required TResult orElse(), 119 | }) { 120 | final _that = this; 121 | switch (_that) { 122 | case _WhisperTranscribeResponse() when $default != null: 123 | return $default(_that); 124 | case _: 125 | return orElse(); 126 | } 127 | } 128 | 129 | /// A `switch`-like method, using callbacks. 130 | /// 131 | /// Callbacks receives the raw object, upcasted. 132 | /// It is equivalent to doing: 133 | /// ```dart 134 | /// switch (sealedClass) { 135 | /// case final Subclass value: 136 | /// return ...; 137 | /// case final Subclass2 value: 138 | /// return ...; 139 | /// } 140 | /// ``` 141 | 142 | @optionalTypeArgs 143 | TResult map( 144 | TResult Function(_WhisperTranscribeResponse value) $default, 145 | ) { 146 | final _that = this; 147 | switch (_that) { 148 | case _WhisperTranscribeResponse(): 149 | return $default(_that); 150 | case _: 151 | throw StateError('Unexpected subclass'); 152 | } 153 | } 154 | 155 | /// A variant of `map` that fallback to returning `null`. 156 | /// 157 | /// It is equivalent to doing: 158 | /// ```dart 159 | /// switch (sealedClass) { 160 | /// case final Subclass value: 161 | /// return ...; 162 | /// case _: 163 | /// return null; 164 | /// } 165 | /// ``` 166 | 167 | @optionalTypeArgs 168 | TResult? mapOrNull( 169 | TResult? Function(_WhisperTranscribeResponse value)? $default, 170 | ) { 171 | final _that = this; 172 | switch (_that) { 173 | case _WhisperTranscribeResponse() when $default != null: 174 | return $default(_that); 175 | case _: 176 | return null; 177 | } 178 | } 179 | 180 | /// A variant of `when` that fallback to an `orElse` callback. 181 | /// 182 | /// It is equivalent to doing: 183 | /// ```dart 184 | /// switch (sealedClass) { 185 | /// case Subclass(:final field): 186 | /// return ...; 187 | /// case _: 188 | /// return orElse(); 189 | /// } 190 | /// ``` 191 | 192 | @optionalTypeArgs 193 | TResult maybeWhen( 194 | TResult Function( 195 | @JsonKey(name: '@type') String type, 196 | String text, 197 | @JsonKey(name: 'segments') 198 | List? segments)? 199 | $default, { 200 | required TResult orElse(), 201 | }) { 202 | final _that = this; 203 | switch (_that) { 204 | case _WhisperTranscribeResponse() when $default != null: 205 | return $default(_that.type, _that.text, _that.segments); 206 | case _: 207 | return orElse(); 208 | } 209 | } 210 | 211 | /// A `switch`-like method, using callbacks. 212 | /// 213 | /// As opposed to `map`, this offers destructuring. 214 | /// It is equivalent to doing: 215 | /// ```dart 216 | /// switch (sealedClass) { 217 | /// case Subclass(:final field): 218 | /// return ...; 219 | /// case Subclass2(:final field2): 220 | /// return ...; 221 | /// } 222 | /// ``` 223 | 224 | @optionalTypeArgs 225 | TResult when( 226 | TResult Function(@JsonKey(name: '@type') String type, String text, 227 | @JsonKey(name: 'segments') List? segments) 228 | $default, 229 | ) { 230 | final _that = this; 231 | switch (_that) { 232 | case _WhisperTranscribeResponse(): 233 | return $default(_that.type, _that.text, _that.segments); 234 | case _: 235 | throw StateError('Unexpected subclass'); 236 | } 237 | } 238 | 239 | /// A variant of `when` that fallback to returning `null` 240 | /// 241 | /// It is equivalent to doing: 242 | /// ```dart 243 | /// switch (sealedClass) { 244 | /// case Subclass(:final field): 245 | /// return ...; 246 | /// case _: 247 | /// return null; 248 | /// } 249 | /// ``` 250 | 251 | @optionalTypeArgs 252 | TResult? whenOrNull( 253 | TResult? Function( 254 | @JsonKey(name: '@type') String type, 255 | String text, 256 | @JsonKey(name: 'segments') 257 | List? segments)? 258 | $default, 259 | ) { 260 | final _that = this; 261 | switch (_that) { 262 | case _WhisperTranscribeResponse() when $default != null: 263 | return $default(_that.type, _that.text, _that.segments); 264 | case _: 265 | return null; 266 | } 267 | } 268 | } 269 | 270 | /// @nodoc 271 | @JsonSerializable() 272 | class _WhisperTranscribeResponse extends WhisperTranscribeResponse { 273 | const _WhisperTranscribeResponse( 274 | {@JsonKey(name: '@type') required this.type, 275 | required this.text, 276 | @JsonKey(name: 'segments') 277 | required final List? segments}) 278 | : _segments = segments, 279 | super._(); 280 | factory _WhisperTranscribeResponse.fromJson(Map json) => 281 | _$WhisperTranscribeResponseFromJson(json); 282 | 283 | @override 284 | @JsonKey(name: '@type') 285 | final String type; 286 | @override 287 | final String text; 288 | final List? _segments; 289 | @override 290 | @JsonKey(name: 'segments') 291 | List? get segments { 292 | final value = _segments; 293 | if (value == null) return null; 294 | if (_segments is EqualUnmodifiableListView) return _segments; 295 | // ignore: implicit_dynamic_type 296 | return EqualUnmodifiableListView(value); 297 | } 298 | 299 | /// Create a copy of WhisperTranscribeResponse 300 | /// with the given fields replaced by the non-null parameter values. 301 | @override 302 | @JsonKey(includeFromJson: false, includeToJson: false) 303 | @pragma('vm:prefer-inline') 304 | _$WhisperTranscribeResponseCopyWith<_WhisperTranscribeResponse> 305 | get copyWith => 306 | __$WhisperTranscribeResponseCopyWithImpl<_WhisperTranscribeResponse>( 307 | this, _$identity); 308 | 309 | @override 310 | Map toJson() { 311 | return _$WhisperTranscribeResponseToJson( 312 | this, 313 | ); 314 | } 315 | 316 | @override 317 | bool operator ==(Object other) { 318 | return identical(this, other) || 319 | (other.runtimeType == runtimeType && 320 | other is _WhisperTranscribeResponse && 321 | (identical(other.type, type) || other.type == type) && 322 | (identical(other.text, text) || other.text == text) && 323 | const DeepCollectionEquality().equals(other._segments, _segments)); 324 | } 325 | 326 | @JsonKey(includeFromJson: false, includeToJson: false) 327 | @override 328 | int get hashCode => Object.hash( 329 | runtimeType, type, text, const DeepCollectionEquality().hash(_segments)); 330 | 331 | @override 332 | String toString() { 333 | return 'WhisperTranscribeResponse(type: $type, text: $text, segments: $segments)'; 334 | } 335 | } 336 | 337 | /// @nodoc 338 | abstract mixin class _$WhisperTranscribeResponseCopyWith<$Res> 339 | implements $WhisperTranscribeResponseCopyWith<$Res> { 340 | factory _$WhisperTranscribeResponseCopyWith(_WhisperTranscribeResponse value, 341 | $Res Function(_WhisperTranscribeResponse) _then) = 342 | __$WhisperTranscribeResponseCopyWithImpl; 343 | @override 344 | @useResult 345 | $Res call( 346 | {@JsonKey(name: '@type') String type, 347 | String text, 348 | @JsonKey(name: 'segments') List? segments}); 349 | } 350 | 351 | /// @nodoc 352 | class __$WhisperTranscribeResponseCopyWithImpl<$Res> 353 | implements _$WhisperTranscribeResponseCopyWith<$Res> { 354 | __$WhisperTranscribeResponseCopyWithImpl(this._self, this._then); 355 | 356 | final _WhisperTranscribeResponse _self; 357 | final $Res Function(_WhisperTranscribeResponse) _then; 358 | 359 | /// Create a copy of WhisperTranscribeResponse 360 | /// with the given fields replaced by the non-null parameter values. 361 | @override 362 | @pragma('vm:prefer-inline') 363 | $Res call({ 364 | Object? type = null, 365 | Object? text = null, 366 | Object? segments = freezed, 367 | }) { 368 | return _then(_WhisperTranscribeResponse( 369 | type: null == type 370 | ? _self.type 371 | : type // ignore: cast_nullable_to_non_nullable 372 | as String, 373 | text: null == text 374 | ? _self.text 375 | : text // ignore: cast_nullable_to_non_nullable 376 | as String, 377 | segments: freezed == segments 378 | ? _self._segments 379 | : segments // ignore: cast_nullable_to_non_nullable 380 | as List?, 381 | )); 382 | } 383 | } 384 | 385 | // dart format on 386 | -------------------------------------------------------------------------------- /lib/src/models/responses/whisper_transcribe_segment.freezed.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | // coverage:ignore-file 3 | // ignore_for_file: type=lint 4 | // ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark 5 | 6 | part of 'whisper_transcribe_segment.dart'; 7 | 8 | // ************************************************************************** 9 | // FreezedGenerator 10 | // ************************************************************************** 11 | 12 | // dart format off 13 | T _$identity(T value) => value; 14 | 15 | /// @nodoc 16 | mixin _$WhisperTranscribeSegment { 17 | @JsonKey(name: 'from_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 18 | Duration get fromTs; 19 | @JsonKey(name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 20 | Duration get toTs; 21 | String get text; 22 | 23 | /// Create a copy of WhisperTranscribeSegment 24 | /// with the given fields replaced by the non-null parameter values. 25 | @JsonKey(includeFromJson: false, includeToJson: false) 26 | @pragma('vm:prefer-inline') 27 | $WhisperTranscribeSegmentCopyWith get copyWith => 28 | _$WhisperTranscribeSegmentCopyWithImpl( 29 | this as WhisperTranscribeSegment, _$identity); 30 | 31 | /// Serializes this WhisperTranscribeSegment to a JSON map. 32 | Map toJson(); 33 | 34 | @override 35 | bool operator ==(Object other) { 36 | return identical(this, other) || 37 | (other.runtimeType == runtimeType && 38 | other is WhisperTranscribeSegment && 39 | (identical(other.fromTs, fromTs) || other.fromTs == fromTs) && 40 | (identical(other.toTs, toTs) || other.toTs == toTs) && 41 | (identical(other.text, text) || other.text == text)); 42 | } 43 | 44 | @JsonKey(includeFromJson: false, includeToJson: false) 45 | @override 46 | int get hashCode => Object.hash(runtimeType, fromTs, toTs, text); 47 | 48 | @override 49 | String toString() { 50 | return 'WhisperTranscribeSegment(fromTs: $fromTs, toTs: $toTs, text: $text)'; 51 | } 52 | } 53 | 54 | /// @nodoc 55 | abstract mixin class $WhisperTranscribeSegmentCopyWith<$Res> { 56 | factory $WhisperTranscribeSegmentCopyWith(WhisperTranscribeSegment value, 57 | $Res Function(WhisperTranscribeSegment) _then) = 58 | _$WhisperTranscribeSegmentCopyWithImpl; 59 | @useResult 60 | $Res call( 61 | {@JsonKey( 62 | name: 'from_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 63 | Duration fromTs, 64 | @JsonKey( 65 | name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 66 | Duration toTs, 67 | String text}); 68 | } 69 | 70 | /// @nodoc 71 | class _$WhisperTranscribeSegmentCopyWithImpl<$Res> 72 | implements $WhisperTranscribeSegmentCopyWith<$Res> { 73 | _$WhisperTranscribeSegmentCopyWithImpl(this._self, this._then); 74 | 75 | final WhisperTranscribeSegment _self; 76 | final $Res Function(WhisperTranscribeSegment) _then; 77 | 78 | /// Create a copy of WhisperTranscribeSegment 79 | /// with the given fields replaced by the non-null parameter values. 80 | @pragma('vm:prefer-inline') 81 | @override 82 | $Res call({ 83 | Object? fromTs = null, 84 | Object? toTs = null, 85 | Object? text = null, 86 | }) { 87 | return _then(_self.copyWith( 88 | fromTs: null == fromTs 89 | ? _self.fromTs 90 | : fromTs // ignore: cast_nullable_to_non_nullable 91 | as Duration, 92 | toTs: null == toTs 93 | ? _self.toTs 94 | : toTs // ignore: cast_nullable_to_non_nullable 95 | as Duration, 96 | text: null == text 97 | ? _self.text 98 | : text // ignore: cast_nullable_to_non_nullable 99 | as String, 100 | )); 101 | } 102 | } 103 | 104 | /// Adds pattern-matching-related methods to [WhisperTranscribeSegment]. 105 | extension WhisperTranscribeSegmentPatterns on WhisperTranscribeSegment { 106 | /// A variant of `map` that fallback to returning `orElse`. 107 | /// 108 | /// It is equivalent to doing: 109 | /// ```dart 110 | /// switch (sealedClass) { 111 | /// case final Subclass value: 112 | /// return ...; 113 | /// case _: 114 | /// return orElse(); 115 | /// } 116 | /// ``` 117 | 118 | @optionalTypeArgs 119 | TResult maybeMap( 120 | TResult Function(_WhisperTranscribeSegment value)? $default, { 121 | required TResult orElse(), 122 | }) { 123 | final _that = this; 124 | switch (_that) { 125 | case _WhisperTranscribeSegment() when $default != null: 126 | return $default(_that); 127 | case _: 128 | return orElse(); 129 | } 130 | } 131 | 132 | /// A `switch`-like method, using callbacks. 133 | /// 134 | /// Callbacks receives the raw object, upcasted. 135 | /// It is equivalent to doing: 136 | /// ```dart 137 | /// switch (sealedClass) { 138 | /// case final Subclass value: 139 | /// return ...; 140 | /// case final Subclass2 value: 141 | /// return ...; 142 | /// } 143 | /// ``` 144 | 145 | @optionalTypeArgs 146 | TResult map( 147 | TResult Function(_WhisperTranscribeSegment value) $default, 148 | ) { 149 | final _that = this; 150 | switch (_that) { 151 | case _WhisperTranscribeSegment(): 152 | return $default(_that); 153 | case _: 154 | throw StateError('Unexpected subclass'); 155 | } 156 | } 157 | 158 | /// A variant of `map` that fallback to returning `null`. 159 | /// 160 | /// It is equivalent to doing: 161 | /// ```dart 162 | /// switch (sealedClass) { 163 | /// case final Subclass value: 164 | /// return ...; 165 | /// case _: 166 | /// return null; 167 | /// } 168 | /// ``` 169 | 170 | @optionalTypeArgs 171 | TResult? mapOrNull( 172 | TResult? Function(_WhisperTranscribeSegment value)? $default, 173 | ) { 174 | final _that = this; 175 | switch (_that) { 176 | case _WhisperTranscribeSegment() when $default != null: 177 | return $default(_that); 178 | case _: 179 | return null; 180 | } 181 | } 182 | 183 | /// A variant of `when` that fallback to an `orElse` callback. 184 | /// 185 | /// It is equivalent to doing: 186 | /// ```dart 187 | /// switch (sealedClass) { 188 | /// case Subclass(:final field): 189 | /// return ...; 190 | /// case _: 191 | /// return orElse(); 192 | /// } 193 | /// ``` 194 | 195 | @optionalTypeArgs 196 | TResult maybeWhen( 197 | TResult Function( 198 | @JsonKey( 199 | name: 'from_ts', 200 | fromJson: WhisperTranscribeSegment._durationFromInt) 201 | Duration fromTs, 202 | @JsonKey( 203 | name: 'to_ts', 204 | fromJson: WhisperTranscribeSegment._durationFromInt) 205 | Duration toTs, 206 | String text)? 207 | $default, { 208 | required TResult orElse(), 209 | }) { 210 | final _that = this; 211 | switch (_that) { 212 | case _WhisperTranscribeSegment() when $default != null: 213 | return $default(_that.fromTs, _that.toTs, _that.text); 214 | case _: 215 | return orElse(); 216 | } 217 | } 218 | 219 | /// A `switch`-like method, using callbacks. 220 | /// 221 | /// As opposed to `map`, this offers destructuring. 222 | /// It is equivalent to doing: 223 | /// ```dart 224 | /// switch (sealedClass) { 225 | /// case Subclass(:final field): 226 | /// return ...; 227 | /// case Subclass2(:final field2): 228 | /// return ...; 229 | /// } 230 | /// ``` 231 | 232 | @optionalTypeArgs 233 | TResult when( 234 | TResult Function( 235 | @JsonKey( 236 | name: 'from_ts', 237 | fromJson: WhisperTranscribeSegment._durationFromInt) 238 | Duration fromTs, 239 | @JsonKey( 240 | name: 'to_ts', 241 | fromJson: WhisperTranscribeSegment._durationFromInt) 242 | Duration toTs, 243 | String text) 244 | $default, 245 | ) { 246 | final _that = this; 247 | switch (_that) { 248 | case _WhisperTranscribeSegment(): 249 | return $default(_that.fromTs, _that.toTs, _that.text); 250 | case _: 251 | throw StateError('Unexpected subclass'); 252 | } 253 | } 254 | 255 | /// A variant of `when` that fallback to returning `null` 256 | /// 257 | /// It is equivalent to doing: 258 | /// ```dart 259 | /// switch (sealedClass) { 260 | /// case Subclass(:final field): 261 | /// return ...; 262 | /// case _: 263 | /// return null; 264 | /// } 265 | /// ``` 266 | 267 | @optionalTypeArgs 268 | TResult? whenOrNull( 269 | TResult? Function( 270 | @JsonKey( 271 | name: 'from_ts', 272 | fromJson: WhisperTranscribeSegment._durationFromInt) 273 | Duration fromTs, 274 | @JsonKey( 275 | name: 'to_ts', 276 | fromJson: WhisperTranscribeSegment._durationFromInt) 277 | Duration toTs, 278 | String text)? 279 | $default, 280 | ) { 281 | final _that = this; 282 | switch (_that) { 283 | case _WhisperTranscribeSegment() when $default != null: 284 | return $default(_that.fromTs, _that.toTs, _that.text); 285 | case _: 286 | return null; 287 | } 288 | } 289 | } 290 | 291 | /// @nodoc 292 | @JsonSerializable() 293 | class _WhisperTranscribeSegment implements WhisperTranscribeSegment { 294 | const _WhisperTranscribeSegment( 295 | {@JsonKey( 296 | name: 'from_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 297 | required this.fromTs, 298 | @JsonKey( 299 | name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 300 | required this.toTs, 301 | required this.text}); 302 | factory _WhisperTranscribeSegment.fromJson(Map json) => 303 | _$WhisperTranscribeSegmentFromJson(json); 304 | 305 | @override 306 | @JsonKey(name: 'from_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 307 | final Duration fromTs; 308 | @override 309 | @JsonKey(name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 310 | final Duration toTs; 311 | @override 312 | final String text; 313 | 314 | /// Create a copy of WhisperTranscribeSegment 315 | /// with the given fields replaced by the non-null parameter values. 316 | @override 317 | @JsonKey(includeFromJson: false, includeToJson: false) 318 | @pragma('vm:prefer-inline') 319 | _$WhisperTranscribeSegmentCopyWith<_WhisperTranscribeSegment> get copyWith => 320 | __$WhisperTranscribeSegmentCopyWithImpl<_WhisperTranscribeSegment>( 321 | this, _$identity); 322 | 323 | @override 324 | Map toJson() { 325 | return _$WhisperTranscribeSegmentToJson( 326 | this, 327 | ); 328 | } 329 | 330 | @override 331 | bool operator ==(Object other) { 332 | return identical(this, other) || 333 | (other.runtimeType == runtimeType && 334 | other is _WhisperTranscribeSegment && 335 | (identical(other.fromTs, fromTs) || other.fromTs == fromTs) && 336 | (identical(other.toTs, toTs) || other.toTs == toTs) && 337 | (identical(other.text, text) || other.text == text)); 338 | } 339 | 340 | @JsonKey(includeFromJson: false, includeToJson: false) 341 | @override 342 | int get hashCode => Object.hash(runtimeType, fromTs, toTs, text); 343 | 344 | @override 345 | String toString() { 346 | return 'WhisperTranscribeSegment(fromTs: $fromTs, toTs: $toTs, text: $text)'; 347 | } 348 | } 349 | 350 | /// @nodoc 351 | abstract mixin class _$WhisperTranscribeSegmentCopyWith<$Res> 352 | implements $WhisperTranscribeSegmentCopyWith<$Res> { 353 | factory _$WhisperTranscribeSegmentCopyWith(_WhisperTranscribeSegment value, 354 | $Res Function(_WhisperTranscribeSegment) _then) = 355 | __$WhisperTranscribeSegmentCopyWithImpl; 356 | @override 357 | @useResult 358 | $Res call( 359 | {@JsonKey( 360 | name: 'from_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 361 | Duration fromTs, 362 | @JsonKey( 363 | name: 'to_ts', fromJson: WhisperTranscribeSegment._durationFromInt) 364 | Duration toTs, 365 | String text}); 366 | } 367 | 368 | /// @nodoc 369 | class __$WhisperTranscribeSegmentCopyWithImpl<$Res> 370 | implements _$WhisperTranscribeSegmentCopyWith<$Res> { 371 | __$WhisperTranscribeSegmentCopyWithImpl(this._self, this._then); 372 | 373 | final _WhisperTranscribeSegment _self; 374 | final $Res Function(_WhisperTranscribeSegment) _then; 375 | 376 | /// Create a copy of WhisperTranscribeSegment 377 | /// with the given fields replaced by the non-null parameter values. 378 | @override 379 | @pragma('vm:prefer-inline') 380 | $Res call({ 381 | Object? fromTs = null, 382 | Object? toTs = null, 383 | Object? text = null, 384 | }) { 385 | return _then(_WhisperTranscribeSegment( 386 | fromTs: null == fromTs 387 | ? _self.fromTs 388 | : fromTs // ignore: cast_nullable_to_non_nullable 389 | as Duration, 390 | toTs: null == toTs 391 | ? _self.toTs 392 | : toTs // ignore: cast_nullable_to_non_nullable 393 | as Duration, 394 | text: null == text 395 | ? _self.text 396 | : text // ignore: cast_nullable_to_non_nullable 397 | as String, 398 | )); 399 | } 400 | } 401 | 402 | // dart format on 403 | -------------------------------------------------------------------------------- /.dart_tool/package_config_subset: -------------------------------------------------------------------------------- 1 | _fe_analyzer_shared 2 | 3.3 3 | file:///Users/me/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-80.0.0/ 4 | file:///Users/me/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-80.0.0/lib/ 5 | analyzer 6 | 3.3 7 | file:///Users/me/.pub-cache/hosted/pub.dev/analyzer-7.3.0/ 8 | file:///Users/me/.pub-cache/hosted/pub.dev/analyzer-7.3.0/lib/ 9 | args 10 | 3.3 11 | file:///Users/me/.pub-cache/hosted/pub.dev/args-2.7.0/ 12 | file:///Users/me/.pub-cache/hosted/pub.dev/args-2.7.0/lib/ 13 | async 14 | 3.4 15 | file:///Users/me/.pub-cache/hosted/pub.dev/async-2.13.0/ 16 | file:///Users/me/.pub-cache/hosted/pub.dev/async-2.13.0/lib/ 17 | boolean_selector 18 | 3.1 19 | file:///Users/me/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2/ 20 | file:///Users/me/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2/lib/ 21 | build 22 | 3.6 23 | file:///Users/me/.pub-cache/hosted/pub.dev/build-2.4.2/ 24 | file:///Users/me/.pub-cache/hosted/pub.dev/build-2.4.2/lib/ 25 | build_config 26 | 3.6 27 | file:///Users/me/.pub-cache/hosted/pub.dev/build_config-1.1.2/ 28 | file:///Users/me/.pub-cache/hosted/pub.dev/build_config-1.1.2/lib/ 29 | build_daemon 30 | 3.6 31 | file:///Users/me/.pub-cache/hosted/pub.dev/build_daemon-4.0.4/ 32 | file:///Users/me/.pub-cache/hosted/pub.dev/build_daemon-4.0.4/lib/ 33 | build_resolvers 34 | 3.6 35 | file:///Users/me/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4/ 36 | file:///Users/me/.pub-cache/hosted/pub.dev/build_resolvers-2.4.4/lib/ 37 | build_runner 38 | 3.6 39 | file:///Users/me/.pub-cache/hosted/pub.dev/build_runner-2.4.15/ 40 | file:///Users/me/.pub-cache/hosted/pub.dev/build_runner-2.4.15/lib/ 41 | build_runner_core 42 | 3.6 43 | file:///Users/me/.pub-cache/hosted/pub.dev/build_runner_core-8.0.0/ 44 | file:///Users/me/.pub-cache/hosted/pub.dev/build_runner_core-8.0.0/lib/ 45 | built_collection 46 | 2.12 47 | file:///Users/me/.pub-cache/hosted/pub.dev/built_collection-5.1.1/ 48 | file:///Users/me/.pub-cache/hosted/pub.dev/built_collection-5.1.1/lib/ 49 | built_value 50 | 3.0 51 | file:///Users/me/.pub-cache/hosted/pub.dev/built_value-8.9.5/ 52 | file:///Users/me/.pub-cache/hosted/pub.dev/built_value-8.9.5/lib/ 53 | characters 54 | 3.4 55 | file:///Users/me/.pub-cache/hosted/pub.dev/characters-1.4.0/ 56 | file:///Users/me/.pub-cache/hosted/pub.dev/characters-1.4.0/lib/ 57 | checked_yaml 58 | 2.19 59 | file:///Users/me/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/ 60 | file:///Users/me/.pub-cache/hosted/pub.dev/checked_yaml-2.0.3/lib/ 61 | cli_util 62 | 3.4 63 | file:///Users/me/.pub-cache/hosted/pub.dev/cli_util-0.4.2/ 64 | file:///Users/me/.pub-cache/hosted/pub.dev/cli_util-0.4.2/lib/ 65 | code_builder 66 | 3.5 67 | file:///Users/me/.pub-cache/hosted/pub.dev/code_builder-4.10.1/ 68 | file:///Users/me/.pub-cache/hosted/pub.dev/code_builder-4.10.1/lib/ 69 | collection 70 | 3.4 71 | file:///Users/me/.pub-cache/hosted/pub.dev/collection-1.19.1/ 72 | file:///Users/me/.pub-cache/hosted/pub.dev/collection-1.19.1/lib/ 73 | convert 74 | 3.4 75 | file:///Users/me/.pub-cache/hosted/pub.dev/convert-3.1.2/ 76 | file:///Users/me/.pub-cache/hosted/pub.dev/convert-3.1.2/lib/ 77 | crypto 78 | 3.4 79 | file:///Users/me/.pub-cache/hosted/pub.dev/crypto-3.0.6/ 80 | file:///Users/me/.pub-cache/hosted/pub.dev/crypto-3.0.6/lib/ 81 | dart_style 82 | 3.4 83 | file:///Users/me/.pub-cache/hosted/pub.dev/dart_style-3.0.1/ 84 | file:///Users/me/.pub-cache/hosted/pub.dev/dart_style-3.0.1/lib/ 85 | ffi 86 | 3.3 87 | file:///Users/me/.pub-cache/hosted/pub.dev/ffi-2.1.3/ 88 | file:///Users/me/.pub-cache/hosted/pub.dev/ffi-2.1.3/lib/ 89 | ffigen 90 | 3.4 91 | file:///Users/me/.pub-cache/hosted/pub.dev/ffigen-18.1.0/ 92 | file:///Users/me/.pub-cache/hosted/pub.dev/ffigen-18.1.0/lib/ 93 | ffmpeg_kit_flutter_android 94 | 3.1 95 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_android-1.4.0/ 96 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_android-1.4.0/lib/ 97 | ffmpeg_kit_flutter_new 98 | 3.1 99 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_new-1.6.1/ 100 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_new-1.6.1/lib/ 101 | ffmpeg_kit_flutter_platform_interface 102 | 2.12 103 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_platform_interface-0.2.1/ 104 | file:///Users/me/.pub-cache/hosted/pub.dev/ffmpeg_kit_flutter_platform_interface-0.2.1/lib/ 105 | file 106 | 3.0 107 | file:///Users/me/.pub-cache/hosted/pub.dev/file-7.0.1/ 108 | file:///Users/me/.pub-cache/hosted/pub.dev/file-7.0.1/lib/ 109 | fixnum 110 | 3.1 111 | file:///Users/me/.pub-cache/hosted/pub.dev/fixnum-1.1.1/ 112 | file:///Users/me/.pub-cache/hosted/pub.dev/fixnum-1.1.1/lib/ 113 | flutter_riverpod 114 | 2.17 115 | file:///Users/me/.pub-cache/hosted/pub.dev/flutter_riverpod-2.6.1/ 116 | file:///Users/me/.pub-cache/hosted/pub.dev/flutter_riverpod-2.6.1/lib/ 117 | freezed 118 | 3.6 119 | file:///Users/me/.pub-cache/hosted/pub.dev/freezed-3.0.6/ 120 | file:///Users/me/.pub-cache/hosted/pub.dev/freezed-3.0.6/lib/ 121 | freezed_annotation 122 | 3.0 123 | file:///Users/me/.pub-cache/hosted/pub.dev/freezed_annotation-3.0.0/ 124 | file:///Users/me/.pub-cache/hosted/pub.dev/freezed_annotation-3.0.0/lib/ 125 | frontend_server_client 126 | 3.0 127 | file:///Users/me/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0/ 128 | file:///Users/me/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0/lib/ 129 | glob 130 | 3.3 131 | file:///Users/me/.pub-cache/hosted/pub.dev/glob-2.1.3/ 132 | file:///Users/me/.pub-cache/hosted/pub.dev/glob-2.1.3/lib/ 133 | graphs 134 | 3.4 135 | file:///Users/me/.pub-cache/hosted/pub.dev/graphs-2.3.2/ 136 | file:///Users/me/.pub-cache/hosted/pub.dev/graphs-2.3.2/lib/ 137 | http 138 | 3.4 139 | file:///Users/me/.pub-cache/hosted/pub.dev/http-1.3.0/ 140 | file:///Users/me/.pub-cache/hosted/pub.dev/http-1.3.0/lib/ 141 | http_multi_server 142 | 3.2 143 | file:///Users/me/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2/ 144 | file:///Users/me/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2/lib/ 145 | http_parser 146 | 3.4 147 | file:///Users/me/.pub-cache/hosted/pub.dev/http_parser-4.1.2/ 148 | file:///Users/me/.pub-cache/hosted/pub.dev/http_parser-4.1.2/lib/ 149 | io 150 | 3.4 151 | file:///Users/me/.pub-cache/hosted/pub.dev/io-1.0.5/ 152 | file:///Users/me/.pub-cache/hosted/pub.dev/io-1.0.5/lib/ 153 | js 154 | 3.1 155 | file:///Users/me/.pub-cache/hosted/pub.dev/js-0.7.1/ 156 | file:///Users/me/.pub-cache/hosted/pub.dev/js-0.7.1/lib/ 157 | json_annotation 158 | 3.0 159 | file:///Users/me/.pub-cache/hosted/pub.dev/json_annotation-4.9.0/ 160 | file:///Users/me/.pub-cache/hosted/pub.dev/json_annotation-4.9.0/lib/ 161 | json_serializable 162 | 3.6 163 | file:///Users/me/.pub-cache/hosted/pub.dev/json_serializable-6.9.5/ 164 | file:///Users/me/.pub-cache/hosted/pub.dev/json_serializable-6.9.5/lib/ 165 | logging 166 | 3.4 167 | file:///Users/me/.pub-cache/hosted/pub.dev/logging-1.3.0/ 168 | file:///Users/me/.pub-cache/hosted/pub.dev/logging-1.3.0/lib/ 169 | matcher 170 | 3.4 171 | file:///Users/me/.pub-cache/hosted/pub.dev/matcher-0.12.17/ 172 | file:///Users/me/.pub-cache/hosted/pub.dev/matcher-0.12.17/lib/ 173 | material_color_utilities 174 | 2.17 175 | file:///Users/me/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/ 176 | file:///Users/me/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1/lib/ 177 | meta 178 | 2.12 179 | file:///Users/me/.pub-cache/hosted/pub.dev/meta-1.16.0/ 180 | file:///Users/me/.pub-cache/hosted/pub.dev/meta-1.16.0/lib/ 181 | mime 182 | 3.2 183 | file:///Users/me/.pub-cache/hosted/pub.dev/mime-2.0.0/ 184 | file:///Users/me/.pub-cache/hosted/pub.dev/mime-2.0.0/lib/ 185 | package_config 186 | 3.4 187 | file:///Users/me/.pub-cache/hosted/pub.dev/package_config-2.2.0/ 188 | file:///Users/me/.pub-cache/hosted/pub.dev/package_config-2.2.0/lib/ 189 | path 190 | 3.4 191 | file:///Users/me/.pub-cache/hosted/pub.dev/path-1.9.1/ 192 | file:///Users/me/.pub-cache/hosted/pub.dev/path-1.9.1/lib/ 193 | path_provider 194 | 3.4 195 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider-2.1.5/ 196 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider-2.1.5/lib/ 197 | path_provider_android 198 | 3.6 199 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_android-2.2.16/ 200 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_android-2.2.16/lib/ 201 | path_provider_foundation 202 | 3.3 203 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/ 204 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.1/lib/ 205 | path_provider_linux 206 | 2.19 207 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ 208 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/lib/ 209 | path_provider_platform_interface 210 | 3.0 211 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/ 212 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2/lib/ 213 | path_provider_windows 214 | 3.2 215 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/ 216 | file:///Users/me/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/lib/ 217 | platform 218 | 3.2 219 | file:///Users/me/.pub-cache/hosted/pub.dev/platform-3.1.6/ 220 | file:///Users/me/.pub-cache/hosted/pub.dev/platform-3.1.6/lib/ 221 | plugin_platform_interface 222 | 3.0 223 | file:///Users/me/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/ 224 | file:///Users/me/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8/lib/ 225 | pool 226 | 2.12 227 | file:///Users/me/.pub-cache/hosted/pub.dev/pool-1.5.1/ 228 | file:///Users/me/.pub-cache/hosted/pub.dev/pool-1.5.1/lib/ 229 | pub_semver 230 | 3.4 231 | file:///Users/me/.pub-cache/hosted/pub.dev/pub_semver-2.2.0/ 232 | file:///Users/me/.pub-cache/hosted/pub.dev/pub_semver-2.2.0/lib/ 233 | pubspec_parse 234 | 3.6 235 | file:///Users/me/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0/ 236 | file:///Users/me/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0/lib/ 237 | quiver 238 | 2.17 239 | file:///Users/me/.pub-cache/hosted/pub.dev/quiver-3.2.2/ 240 | file:///Users/me/.pub-cache/hosted/pub.dev/quiver-3.2.2/lib/ 241 | riverpod 242 | 2.17 243 | file:///Users/me/.pub-cache/hosted/pub.dev/riverpod-2.6.1/ 244 | file:///Users/me/.pub-cache/hosted/pub.dev/riverpod-2.6.1/lib/ 245 | shelf 246 | 3.4 247 | file:///Users/me/.pub-cache/hosted/pub.dev/shelf-1.4.2/ 248 | file:///Users/me/.pub-cache/hosted/pub.dev/shelf-1.4.2/lib/ 249 | shelf_web_socket 250 | 3.5 251 | file:///Users/me/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0/ 252 | file:///Users/me/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0/lib/ 253 | source_gen 254 | 3.6 255 | file:///Users/me/.pub-cache/hosted/pub.dev/source_gen-2.0.0/ 256 | file:///Users/me/.pub-cache/hosted/pub.dev/source_gen-2.0.0/lib/ 257 | source_helper 258 | 3.4 259 | file:///Users/me/.pub-cache/hosted/pub.dev/source_helper-1.3.5/ 260 | file:///Users/me/.pub-cache/hosted/pub.dev/source_helper-1.3.5/lib/ 261 | source_span 262 | 3.1 263 | file:///Users/me/.pub-cache/hosted/pub.dev/source_span-1.10.1/ 264 | file:///Users/me/.pub-cache/hosted/pub.dev/source_span-1.10.1/lib/ 265 | stack_trace 266 | 3.4 267 | file:///Users/me/.pub-cache/hosted/pub.dev/stack_trace-1.12.1/ 268 | file:///Users/me/.pub-cache/hosted/pub.dev/stack_trace-1.12.1/lib/ 269 | state_notifier 270 | 2.12 271 | file:///Users/me/.pub-cache/hosted/pub.dev/state_notifier-1.0.0/ 272 | file:///Users/me/.pub-cache/hosted/pub.dev/state_notifier-1.0.0/lib/ 273 | stream_channel 274 | 3.3 275 | file:///Users/me/.pub-cache/hosted/pub.dev/stream_channel-2.1.4/ 276 | file:///Users/me/.pub-cache/hosted/pub.dev/stream_channel-2.1.4/lib/ 277 | stream_transform 278 | 3.1 279 | file:///Users/me/.pub-cache/hosted/pub.dev/stream_transform-2.1.1/ 280 | file:///Users/me/.pub-cache/hosted/pub.dev/stream_transform-2.1.1/lib/ 281 | string_scanner 282 | 3.1 283 | file:///Users/me/.pub-cache/hosted/pub.dev/string_scanner-1.4.1/ 284 | file:///Users/me/.pub-cache/hosted/pub.dev/string_scanner-1.4.1/lib/ 285 | term_glyph 286 | 3.1 287 | file:///Users/me/.pub-cache/hosted/pub.dev/term_glyph-1.2.2/ 288 | file:///Users/me/.pub-cache/hosted/pub.dev/term_glyph-1.2.2/lib/ 289 | test_api 290 | 3.5 291 | file:///Users/me/.pub-cache/hosted/pub.dev/test_api-0.7.4/ 292 | file:///Users/me/.pub-cache/hosted/pub.dev/test_api-0.7.4/lib/ 293 | timing 294 | 3.4 295 | file:///Users/me/.pub-cache/hosted/pub.dev/timing-1.0.2/ 296 | file:///Users/me/.pub-cache/hosted/pub.dev/timing-1.0.2/lib/ 297 | typed_data 298 | 3.5 299 | file:///Users/me/.pub-cache/hosted/pub.dev/typed_data-1.4.0/ 300 | file:///Users/me/.pub-cache/hosted/pub.dev/typed_data-1.4.0/lib/ 301 | universal_io 302 | 2.17 303 | file:///Users/me/.pub-cache/hosted/pub.dev/universal_io-2.2.2/ 304 | file:///Users/me/.pub-cache/hosted/pub.dev/universal_io-2.2.2/lib/ 305 | vector_math 306 | 2.14 307 | file:///Users/me/.pub-cache/hosted/pub.dev/vector_math-2.1.4/ 308 | file:///Users/me/.pub-cache/hosted/pub.dev/vector_math-2.1.4/lib/ 309 | very_good_analysis 310 | 3.5 311 | file:///Users/me/.pub-cache/hosted/pub.dev/very_good_analysis-7.0.0/ 312 | file:///Users/me/.pub-cache/hosted/pub.dev/very_good_analysis-7.0.0/lib/ 313 | watcher 314 | 3.1 315 | file:///Users/me/.pub-cache/hosted/pub.dev/watcher-1.1.1/ 316 | file:///Users/me/.pub-cache/hosted/pub.dev/watcher-1.1.1/lib/ 317 | web 318 | 3.4 319 | file:///Users/me/.pub-cache/hosted/pub.dev/web-1.1.1/ 320 | file:///Users/me/.pub-cache/hosted/pub.dev/web-1.1.1/lib/ 321 | web_socket 322 | 3.3 323 | file:///Users/me/.pub-cache/hosted/pub.dev/web_socket-0.1.6/ 324 | file:///Users/me/.pub-cache/hosted/pub.dev/web_socket-0.1.6/lib/ 325 | web_socket_channel 326 | 3.3 327 | file:///Users/me/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.2/ 328 | file:///Users/me/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.2/lib/ 329 | xdg_directories 330 | 3.3 331 | file:///Users/me/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/ 332 | file:///Users/me/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0/lib/ 333 | yaml 334 | 3.4 335 | file:///Users/me/.pub-cache/hosted/pub.dev/yaml-3.1.3/ 336 | file:///Users/me/.pub-cache/hosted/pub.dev/yaml-3.1.3/lib/ 337 | yaml_edit 338 | 3.1 339 | file:///Users/me/.pub-cache/hosted/pub.dev/yaml_edit-2.2.2/ 340 | file:///Users/me/.pub-cache/hosted/pub.dev/yaml_edit-2.2.2/lib/ 341 | whisper_ggml 342 | 3.1 343 | file:///Users/me/StudioProjects/whisper_ggml/ 344 | file:///Users/me/StudioProjects/whisper_ggml/lib/ 345 | sky_engine 346 | 3.7 347 | file:///Users/me/flutter/bin/cache/pkg/sky_engine/ 348 | file:///Users/me/flutter/bin/cache/pkg/sky_engine/lib/ 349 | flutter 350 | 3.7 351 | file:///Users/me/flutter/packages/flutter/ 352 | file:///Users/me/flutter/packages/flutter/lib/ 353 | 2 354 | --------------------------------------------------------------------------------