feat: Integrate ffmpeg_kit_extended_flutter for audio conversion on Windows, and update whisper_ggml_plus dependency to git.

This commit is contained in:
lml committed 2026-03-15 16:51:27 +08:00
1 parent 55ae8a5378
commit 25e9beaeef
12 files changed
+206 -82

No files matched your search

+71
View File
@@ -0,0 +1,71 @@
import 'package:ffmpeg_kit_extended_flutter/ffmpeg_kit_extended_flutter.dart';
import 'package:flutter/foundation.dart';
import 'package:universal_io/io.dart';
import 'package:whisper_ggml_plus/whisper_ggml_plus.dart';
/// FFmpeg-based implementation of [WhisperAudioConverter] for Windows.
class FFmpegWindowsConverter implements WhisperAudioConverter {
/// Internal private constructor.
FFmpegWindowsConverter._();
/// Registers this FFmpeg converter to the [WhisperController].
static void register() {
WhisperController.registerAudioConverter(FFmpegWindowsConverter._());
}
@override
Future<File?> convert(File input) async {
// Generate output path by appending .wav to the original filename
final String outputPath = '${input.path}.wav';
final File audioOutput = File(outputPath);
// Clean up if the output file already exists from a previous failed run
if (await audioOutput.exists()) {
await audioOutput.delete();
}
// FFmpeg arguments optimized for Whisper.cpp:
// -ar 16000 : 16kHz sampling rate
// -ac 1 : Mono channel
// -c:a pcm_s16le : 16-bit little-endian PCM (WAV)
final List<String> arguments = [
'-y',
'-i',
'"${input.path}"',
'-ar',
'16000',
'-ac',
'1',
'-c:a',
'pcm_s16le',
'"$outputPath"',
];
debugPrint(
'⚙️ [WHISPER FFMPEG WINDOWS] Starting conversion: ${input.path} -> $outputPath',
);
// Execute FFmpeg command
final FFmpegSession session = FFmpegKit.execute(arguments.join(' '));
final int returnCode = session.getReturnCode();
if (returnCode == 0) {
debugPrint('[WHISPER FFMPEG WINDOWS] Conversion successful');
return audioOutput;
} else if (returnCode == 255) {
debugPrint('[WHISPER FFMPEG WINDOWS] Conversion canceled by user');
} else {
debugPrint(
'[WHISPER FFMPEG WINDOWS] Conversion failed with returnCode $returnCode',
);
final String? logs = session.getOutput();
if (logs != null) {
debugPrint('--- FFmpeg Logs ---');
debugPrint(logs);
debugPrint('-------------------');
}
}
return null;
}
}
+3
View File
@@ -1,6 +1,7 @@
import 'dart:io';
import 'package:caption_trans/converter/ffmpeg_macos.dart';
import 'package:caption_trans/converter/ffmpeg_windows.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
@@ -19,6 +20,8 @@ void main() async {
// so it works within the macOS sandbox.
if (Platform.isMacOS) {
FFmpegMacOsConverter.register();
} else if (Platform.isWindows) {
FFmpegWindowsConverter.register();
}
runApp(CaptionTransApp(settingsService: settingsService));
@@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h"
#include <ffmpeg_kit_extended_flutter/ffmpeg_kit_extended_flutter_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) ffmpeg_kit_extended_flutter_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FfmpegKitExtendedFlutterPlugin");
ffmpeg_kit_extended_flutter_plugin_register_with_registrar(ffmpeg_kit_extended_flutter_registrar);
}
+1
View File
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
ffmpeg_kit_extended_flutter
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
+18 -7
View File
@@ -5,18 +5,18 @@ packages:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: c209688d9f5a5f26b2fb47a188131a6fb9e876ae9e47af3737c0b4f58a93470d
sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "91.0.0"
version: "93.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: f51c8499b35f9b26820cfe914828a6a98a94efd5cc78b37bb7d03debae3a1d08
sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.4.1"
version: "10.0.1"
args:
dependency: transitive
description:
@@ -153,6 +153,15 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
ffmpeg_kit_extended_flutter:
dependency: "direct main"
description:
path: flutter
ref: HEAD
resolved-ref: efab14f66152feeaa528bfd7d8b7c5fa4f1043c0
url: "https://github.com/cddqssc/ffmpeg-kit-extended.git"
source: git
version: "0.2.0"
ffmpeg_kit_flutter_new_min:
dependency: "direct main"
description:
@@ -797,9 +806,11 @@ packages:
whisper_ggml_plus:
dependency: "direct main"
description:
path: whisper_ggml_plus
relative: true
source: path
path: "."
ref: HEAD
resolved-ref: b57159c40d3356e51b32279c6cab12a9cb65cde3
url: "https://github.com/cddqssc/whisper_ggml_plus.git"
source: git
version: "1.4.1"
win32:
dependency: transitive
+12 -3
View File
@@ -15,10 +15,13 @@ dependencies:
# Whisper / Audio
whisper_ggml_plus:
path: whisper_ggml_plus
git:
url: https://github.com/cddqssc/whisper_ggml_plus.git
ffmpeg_kit_flutter_new_min: ^3.1.0
universal_io: ^2.3.1
ffmpeg_kit_extended_flutter:
git:
url: https://github.com/cddqssc/ffmpeg-kit-extended.git
path: flutter
# State Management
flutter_bloc: ^8.1.5
@@ -37,6 +40,12 @@ dependencies:
cupertino_icons: ^1.0.8
openai_dart: ^1.4.0
universal_io: ^2.3.1
ffmpeg_kit_extended_config:
linux: "https://github.com/akashskypatel/ffmpeg-kit-builders/releases/download/v0.8.2-linux/bundle-base-linux-x86_64-shared-small-gpl.zip"
windows: "https://github.com/akashskypatel/ffmpeg-kit-builders/releases/download/v0.8.2-windows/bundle-base-windows-x86_64-shared-small-gpl.zip"
dev_dependencies:
flutter_test:
sdk: flutter
+13 -60
View File
@@ -2,41 +2,27 @@
cmake_minimum_required(VERSION 3.14)
project(caption_trans LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "caption_trans")
# Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(VERSION 3.14...3.25)
# Define build configuration option.
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTICONFIG)
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
CACHE STRING "" FORCE)
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" CACHE STRING "" FORCE)
else()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Debug" CACHE
STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Profile" "Release")
set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Flutter build mode" FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Profile" "Release")
endif()
endif()
# Define settings for the Profile build mode.
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
# Use Unicode for all projects.
add_definitions(-DUNICODE -D_UNICODE)
# Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_17)
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
@@ -45,64 +31,31 @@ function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
endfunction()
# Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR})
# Application build; see runner/CMakeLists.txt.
add_subdirectory("runner")
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
include(flutter/generated_plugins.cmake)
# === Installation ===
# Support files are copied into place next to the executable, so that it can
# run in place. This is done instead of making a separate bundle (as on Linux)
# so that building and running from within Visual Studio will work.
set(BUILD_BUNDLE_DIR "$<TARGET_FILE_DIR:${BINARY_NAME}>")
# Make the "install" step default, as it's required to run.
set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
endif()
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "..." FORCE)
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}")
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" COMPONENT Runtime)
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime)
if(PLUGIN_BUNDLED_LIBRARIES)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime)
endif()
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(DIRECTORY "${NATIVE_ASSETS_DIR}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
install(CODE "
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
install(CODE "file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")" COMPONENT Runtime)
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
# Install the AOT library on non-Debug builds only.
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
CONFIGURATIONS Profile;Release
COMPONENT Runtime)
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" CONFIGURATIONS Profile;Release COMPONENT Runtime)
@@ -6,6 +6,9 @@
#include "generated_plugin_registrant.h"
#include <ffmpeg_kit_extended_flutter/ffmpeg_kit_extended_flutter_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
FfmpegKitExtendedFlutterPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FfmpegKitExtendedFlutterPlugin"));
}
+1
View File
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
ffmpeg_kit_extended_flutter
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
+14 -12
View File
@@ -1,11 +1,6 @@
cmake_minimum_required(VERSION 3.14)
project(runner LANGUAGES CXX)
# Define the application target. To change its name, change BINARY_NAME in the
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
# work.
#
# Any new source files that you add to the application should be added here.
add_executable(${BINARY_NAME} WIN32
"flutter_window.cpp"
"main.cpp"
@@ -16,25 +11,32 @@ add_executable(${BINARY_NAME} WIN32
"runner.exe.manifest"
)
# Apply the standard set of build settings. This can be removed for applications
# that need different build settings.
apply_standard_settings(${BINARY_NAME})
# Add preprocessor definitions for the build version.
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
# Disable Windows macros that collide with C++ standard library functions.
target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
# Add dependency libraries and include directories. Add any application-specific
# dependencies here.
target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
# Run the Flutter tool portions of the build. This must not be removed.
add_dependencies(${BINARY_NAME} flutter_assemble)
# Unified build-time dependency copy script
add_custom_command(TARGET ${BINARY_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-D "BINARY_DIR=${CMAKE_BINARY_DIR}"
-D "SOURCE_DIR=${CMAKE_CURRENT_SOURCE_DIR}"
-D "OUTPUT_DIR=$<TARGET_FILE_DIR:${BINARY_NAME}>"
-D "FLUTTER_LIBRARY=${FLUTTER_LIBRARY}"
-D "FLUTTER_ICU_DATA_FILE=${FLUTTER_ICU_DATA_FILE}"
-D "PROJECT_BUILD_DIR=${PROJECT_BUILD_DIR}"
-D "BUILD_TYPE=$<CONFIG>"
-P "${CMAKE_CURRENT_SOURCE_DIR}/copy_dependencies.cmake"
VERBATIM
)
+50
View File
@@ -0,0 +1,50 @@
# Robust build-time dependency copy script
message(STATUS "DEBUG: Running copy_dependencies.cmake")
message(STATUS "DEBUG: BINARY_DIR: ${BINARY_DIR}")
message(STATUS "DEBUG: OUTPUT_DIR: ${OUTPUT_DIR}")
# 1. Copy Core Flutter DLLs
if(EXISTS "${FLUTTER_LIBRARY}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FLUTTER_LIBRARY}" "${OUTPUT_DIR}")
endif()
if(EXISTS "${FLUTTER_ICU_DATA_FILE}")
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_DIR}/data")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${FLUTTER_ICU_DATA_FILE}" "${OUTPUT_DIR}/data")
endif()
# 1.1 Copy AOT Data (app.so) for Release/Profile
if(NOT BUILD_TYPE STREQUAL "Debug")
file(GLOB_RECURSE app_so "${BINARY_DIR}/*/app.so")
if(app_so)
list(GET app_so 0 first_app_so)
message(STATUS "DEBUG: Found app.so at ${first_app_so}")
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_DIR}/data")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${first_app_so}" "${OUTPUT_DIR}/data")
endif()
endif()
# 2. Copy Assets
if(EXISTS "${PROJECT_BUILD_DIR}/flutter_assets")
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_DIR}/data/flutter_assets")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory "${PROJECT_BUILD_DIR}/flutter_assets" "${OUTPUT_DIR}/data/flutter_assets")
endif()
# 3. Copy Plugin DLLs (Search and find)
set(DLL_NAMES
"whisper_ggml_plus.dll"
"ffmpeg_kit_extended_flutter_plugin.dll"
"libffmpegkit.dll"
)
foreach(dll ${DLL_NAMES})
file(GLOB_RECURSE found_dll "${BINARY_DIR}/*/${dll}")
if(found_dll)
list(GET found_dll 0 first_found) # Take the first one found
message(STATUS "DEBUG: Found ${dll} at ${first_found}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${first_found}" "${OUTPUT_DIR}")
else()
message(STATUS "DEBUG: Could not find ${dll} in ${BINARY_DIR}")
endif()
endforeach()
+16
View File
@@ -0,0 +1,16 @@
set(SEARCH_PATHS
"${CMAKE_BINARY_DIR}/plugins/ffmpeg_kit_extended_flutter/libffmpegkit.dll"
"${CMAKE_BINARY_DIR}/install/libffmpegkit.dll"
"${CMAKE_BINARY_DIR}/runner/Debug/libffmpegkit.dll"
)
foreach(path ${SEARCH_PATHS})
if(EXISTS "${path}")
message(STATUS "DEBUG: Found libffmpegkit.dll at ${path}")
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${path}"
"${CMAKE_BINARY_DIR}/runner/${BUILD_TYPE}"
)
return()
endif()
endforeach()