whisper_ggml 2.8.1
whisper_ggml: ^2.8.1 copied to clipboard
OpenAI Whisper ASR (Automatic Speech Recognition) for Flutter
2.8.1 #
- Fixed the iOS podspec overriding the host app's build settings (#32): it declared
IPHONEOS_DEPLOYMENT_TARGET = 15.6andCLANG_CXX_LANGUAGE_STANDARD = c++20ins.xcconfig, which CocoaPods applies to the app'sPods-Runnerxcconfig as well as to the plugin. On iOS that xcconfig outranks project-level build settings, and Flutter's template sets the deployment target at the project level. An app targeting iOS 16 or later this way was built for 15.6 and failed to compile wherever it called iOS 16 APIs without#availablechecks. Both settings now apply only to the plugin's own target, which still builds for iOS 15.6 with C++20. Thanks @TechupBusiness for the report and the suggested fix - If your Xcode project's iOS deployment target is below 15.6, raise it to 15.6 (Runner → General → Minimum Deployments): the leaked setting used to raise it silently. Such an app still builds, but the linker warns that
whisper_ggml.frameworkwas built for a newer iOS version, and the app would claim to support iOS versions the plugin doesn't - macOS:
CLANG_CXX_LANGUAGE_STANDARDmoved out ofs.xcconfigthe same way. Flutter's macOS template already overrode the leaked value with its own project setting
2.8.0 #
- Opt-in cap on how much earlier text conditions each window of
transcribe(#31): passmaxContext(controller and low-level API) to set whisper.cpp'sn_max_text_ctx, the CLI's--max-context/-mc.maxContext: 0decodes every 30-second window without the text decoded before it — the closest match to Python whisper'scondition_on_previous_text=False— which stops one hallucinated phrase from repeating window after window on long recordings. On a ~3 h recording withggml-base-q5_1, the share of segments inside runs of five or more identical segments fell from 71% to 1.4%. whisper.cpp feedsinitialPromptthrough the same budget, so0also disables it. Off by default; implemented in all three native shims. Contributed by @TechupBusiness - Corrected the
noContextdocs: it clears text that an earlier transcription left on the model context, but never stopped the windows of one recording from conditioning on each other, so it was not equivalent tocondition_on_previous_text=Falseas previously documented - README: the decoding-options table now says which options
transcribeLiveaccepts (it never tooknoContext)
2.7.1 #
- Fixed Android builds failing at
checkDebugAarMetadataon newer toolchains (#30): the plugin compiled againstcompileSdk 34while its own dependencyffmpeg_kit_flutter_new_min2.1.0 requires consumers to compile against 35 or later, and an app cannot override a plugin'scompileSdk. The plugin now usescompileSdk 36, Flutter's own default. Thanks @d4kr for the report - Corrected the Android minimum to API 24 (
minSdkVersion21 → 24, README updated). ffmpeg-kit already required API 24, so apps below it never built; the plugin's declaration now says so instead of advertising API 21 - Example app: bumped the Android Gradle Plugin from 8.4.0 to 8.7.0 (Flutter 3.44 rejects AGP below 8.6.0, so the example no longer built for Android)
2.7.0 #
- Opt-in Silero voice-activity detection for
transcribe(#29): passvadModelPath(controller and low-level API) to run whisper.cpp's built-in VAD before decoding, so only detected speech is transcribed — the standard defence against whisper hallucinating or looping over the leading/trailing silence of push-to-talk recordings.vadSpeechPadMsoptionally overrides the padding kept around speech. Off by default; implemented in all three native shims. Contributed by @Ranjan-Bhagat - Segment timestamps keep referring to the original recording; speech-free audio returns an empty transcript; a VAD model path that cannot be opened fails the request with
failed to open VAD model …instead of a generic error - Composes with
keepModelLoaded: whisper.cpp keeps VAD state on the model context and only resets it when VAD runs again, so a parked model that has run VAD is only reused by requests with the same VAD model. Without that guard, a non-VAD request on such a context got its timestamps remapped through the previous request's speech map, and a request with a different VAD model silently used the first one - Fixed
keepModelLoaded/releaseModelbeing silently ignored on macOS: the 2.6.0 resident-model support never reached the macOS shim, so macOS callers still reloaded the model on every request and live sessions never borrowed a parked model. The macOS shim now matches the iOS one - Verified on host builds of all three native shims (21 scenarios each: VAD, resident model, live sessions borrowing a VAD-used model, concurrent requests) with zero leaked bytes under
leaks --atExit, plus an end-to-end run of the macOS example app through the public Dart API
2.6.0 #
- Opt-in resident model between transcriptions (#26): pass
keepModelLoaded: truetotranscribe(controller and low-level API) and the loadedwhisper_contextis parked in the native layer instead of freed, so the next request with the same model file skips the multi-second load — the difference between usable and not for push-to-talk dictation. Free it with the newreleaseModel()(controller andWhisper), or by transcribing once more with the flag off. Implemented on all five platforms (the Android/Windows/Linux shim and the iOS/macOS shim) - Warm requests are guaranteed independent: a reused context force-clears whisper's rolling text history (
no_context) before decoding, so a warm transcription is byte-identical to a cold one and one request's output can never condition (or leak a hallucination into) the next.initialPromptstill applies per request - The cache uses checkout semantics — the parked context is taken while in use and parked again afterwards — so the lock is never held during a decode and concurrent transcriptions keep running in parallel, each on its own context, exactly as before. Error paths (bad WAV, failed inference) park the model too: a bad recording doesn't cost the next request a reload
- Live sessions join the same scheme:
transcribeLive/startWhisperLiveSessionacceptkeepModelLoaded, which parks the session's model onstop()so session-per-utterance callers skip the per-session load too. A session also borrows an already-parked model automatically when the path matches — and always returns it on stop, so a one-shot caller that parked a model never silently loses it to a live session. Cross-session independence needs nothing extra: every stream decode already runs withno_context - Verified on a host build of the native layer: warm requests skip the load with byte-identical output, the parked model survives failed requests,
releaseModelfrees it (and is a safe no-op when nothing is parked), and 3 rounds of concurrent transcriptions passleaks --atExitwith zero leaked bytes
2.5.0 #
- Live transcription now works with locally provided model files (#25):
WhisperController.transcribeLiveacceptsmodelPathas an alternative tomodel, andstartWhisperLiveSessionis now part of the public API — it takes amodelPathand leaves audio delivery to the caller viaWhisperLiveSession.feed - Raised the declared SDK floor to what the package already required in practice:
sdk: '>=3.7.0 <4.0.0'andflutter: '>=3.29.0'. Since 2.4.0,ffi ^2.1.4has needed Dart 3.7, but the stale>=3.1.0constraint madepub getfail with a version-solving error on older SDKs instead of a clear SDK-requirement message. Verified on the floor (Flutter 3.29.3 / Dart 3.7.2) and on current stable (3.44.8)
2.4.0 #
- Added transcription progress reporting (#6):
transcribe(controller and low-level API) takes an optionalonProgresscallback invoked with whisper.cpp's inference progress as a 0–100 percentage (coarse steps). Implemented via aNativeCallable.listenerhanded towhisper_full_params.progress_callback, so events arrive on the calling isolate without blocking inference
2.3.0 #
WhisperController.transcribenow exposeswithSegmentsandsplitOnWord(#14): passwithSegments: trueto get per-segment timestamps inresult.transcription.segments(fromTs/toTsasDuration), and addsplitOnWord: truefor one segment per word. Previously segments were only reachable through the low-levelWhisper.transcribeAPI- The
diarizeparameter now actually does something (#13): it enables whisper.cpp's tinydiarize speaker-turn detection. Use the newWhisperModel.smallEnTdrzmodel (English only) together withdiarize: trueandwithSegments: true— segments after which the speaker changes carryspeakerTurnNext == true. With regular (non-tdrz) models the flag remains a no-op, as it silently was since 1.7.0
2.2.0 #
- Added Linux support (x64): the vendored whisper.cpp v1.9.1 builds into
libwhisper_ggml.sothrough the standard Flutter Linux CMake toolchain — both one-shot (transcribe) and live (transcribeLive) transcription work - Removed the stale prebuilt
libggml*.sobinaries fromlinux/— leftovers that never constituted a working implementation (no whisper code, wrong bundling variable) and only inflated the package - Like Windows, Linux x64 targets AVX2 by default (
-DWHISPER_GGML_AVX2=OFFfor baseline SSE2) and uses anffmpegexecutable fromPATHfor non-WAV input - Example app: added the Linux runner; the Record button captures 16 kHz WAV directly on Linux
- Fixed a native crash (SIGSEGV) on all platforms when the model file is missing or corrupt:
transcribecalledwhisper_fullwith a null context instead of returning an error response (found by the new Linux test suite) - Fixed a native memory leak on all platforms: error paths in
transcribe(unreadable/wrong-format WAV, failed inference) returned without freeing the loaded model — ~150 MB leaked per failed call with thebasemodel
2.1.0 #
- Added Windows support (x64): the vendored whisper.cpp v1.9.1 now also builds into
whisper_ggml.dllthrough the standard Flutter Windows CMake toolchain — both one-shot (transcribe) and live (transcribeLive) transcription work - Windows builds target AVX2 by default (matching upstream whisper.cpp's standard x64 binaries); pass
-DWHISPER_GGML_AVX2=OFFto the plugin CMake for a baseline SSE2 build - Audio conversion on Windows uses an
ffmpegexecutable fromPATHwhen available (ffmpeg_kit has no Windows implementation); without it, input must already be 16 kHz mono WAV - Native inference stays optimized (
/O2) in Windows debug builds, matching the iOS/macOS behaviour - Example app: added the Windows runner; the Record button captures 16 kHz WAV directly on Windows so no ffmpeg is needed
2.0.0 #
- Upgraded the vendored whisper.cpp from a 2023-era snapshot to v1.9.1 — roughly 15× faster transcription (an 11-second clip takes ~0.4 s with the
basemodel on Apple Silicon), with Accelerate enabled on iOS/macOS - The model-loading code that crashed on some physical iPhones was rewritten upstream (#22); verified working on the iOS simulator
- Removed the
-march=armv8.2-a+fp16Android compile flags that caused SIGILL crashes on armv8.0 devices (#15) - Native code now compiles with
-O3in debug builds on iOS/macOS, so development-time transcription is no longer unusably slow - Rewrote the README
- Note: while the Dart API is unchanged, the native engine swap is significant — hence the major version bump
1.9.2 #
- Removed the
windowsandlinuxplatform declarations — neither has a native whisper implementation, and pub.dev advertised support that failed at runtime. Unsupported platforms now throw a clearUnsupportedError(#20) - Ship consumer ProGuard rules so Android release builds no longer strip the bundled ffmpeg-kit classes, which broke plugin registration and surfaced as
channel-erroron unrelated plugins like path_provider (#16)
1.9.1 #
- Fixed a native crash (SIGABRT) when whisper emits text containing invalid UTF-8 — e.g. a token boundary splitting a multi-byte character, common with non-English audio. Invalid bytes are now replaced with U+FFFD instead of aborting the app (#21)
1.9.0 #
- Added live (streaming) transcription:
WhisperController.transcribeLivetakes a stream of 16 kHz mono PCM16 audio and returns aWhisperLiveSessionthat emits progressively refined partial transcripts while the user speaks;stop()returns the final text - Live sessions load the model once and keep it in memory (new native
stream_start/stream_feed/stream_stopAPI on Android, iOS, and macOS); inference runs on a dedicated isolate and never blocks the UI - Adaptive energy gate keeps silence — digital or room tone — away from the decoder, preventing
[BLANK_AUDIO]markers and hallucinated repetition; tunable per session viagateRmsMin,gateVoiceRatio, andgateNoiseFloorCap - Added
suppressNonSpeechTokensparameter (whisper_full_params.suppress_non_speech_tokens) toTranscribeRequest,transcribe, andtranscribeLive - Fixed a native memory leak: FFI response buffers were never freed — one small leak per one-shot transcription, unbounded growth for streaming
- Example app: redesigned UI with dedicated Live and Record microphone buttons and a JFK sample button; live transcripts update on screen while speaking
- Fixed macOS example: added the missing microphone entitlement
1.8.0 #
- Added
initialPromptparameter toTranscribeRequestandWhisperController.transcribe - Wired
initial_promptthrough towhisper_full_params.initial_prompton Android, iOS, and macOS to bias decoding toward domain-specific vocabulary, names, and punctuation - Added
noContextparameter (whisper_full_params.no_context, equivalent to Python whisper'scondition_on_previous_text=False) on Android, iOS, and macOS to disable cross-segment text conditioning — helps against hallucinated repetition on short utterances - Empty / null prompt and
noContext: falseleave whisper.cpp defaults, so existing callers see no behaviour change - Removed unused
flutter_riverpoddependency, which was constraining consumers to riverpod 2.x even though the package never imported it - Fixed example app crash on macOS when transcribing the bundled jfk.wav (temporary directory did not exist)
1.7.0 #
- Connected
diarizetranscribe parameter to the underlying whisper C++ code - Added
diarizeparameter to thetranscribemethod
1.6.0 #
- Fixed iOS issues
- Added
autolanguage support for iOS - Fixed
exampleproject - Increased NDK version in order to support Google 16 KB requirement
1.5.0 #
- Switched main FFmpeg from heavy
ffmpeg_kit_flutter_new: ^1.6.1to lightweightffmpeg_kit_flutter_new_min: ^2.1.0 - Upgraded
recorderdependency forexampleproject fromv5.2.1tov6.0.0 - Updated main code files
1.4.0 #
- Added ability to use "auto" language detection
- Upgraded
pubspec.yamldependencies
1.3.0 #
- Upgraded Android bindings to work with Flutter 3.29
- Added new FFmpeg kit dependency
1.2.0 #
- Fixed Android v1 embedding issue by adding override for ffmpeg_kit_flutter_full_gpl
- Upgraded dependencies
1.1.1 #
- Cleaned up code
1.1.0 #
- Added support for MacOS
1.0.0 #
- Added support for Android and iOS