experimental: pick between cpu/gpu acceleration + enable directml on windows (#1058)
* first pass at gpu acceleration * unload the model when changing * mock accelerator * translations and build fix * format * clean up helptext * type cleanup * format * lint
This commit is contained in:
parent
f8bbcd791c
commit
cafc2b7208
28 changed files with 484 additions and 64 deletions
69
src-tauri/Cargo.lock
generated
69
src-tauri/Cargo.lock
generated
|
|
@ -114,9 +114,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.13"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
|
||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
|
|
@ -823,9 +823,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "1.0.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
|
||||
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
|
|
@ -892,9 +892,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.4"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
|
||||
|
||||
[[package]]
|
||||
name = "combine"
|
||||
|
|
@ -1777,8 +1777,8 @@ dependencies = [
|
|||
"clap",
|
||||
"ferrous-opencc-compiler",
|
||||
"fst",
|
||||
"phf 0.13.1",
|
||||
"phf_codegen 0.13.1",
|
||||
"phf 0.11.3",
|
||||
"phf_codegen 0.11.3",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
|
|
@ -4246,17 +4246,6 @@ dependencies = [
|
|||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf"
|
||||
dependencies = [
|
||||
"phf_macros 0.13.1",
|
||||
"phf_shared 0.13.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.8.0"
|
||||
|
|
@ -4277,16 +4266,6 @@ dependencies = [
|
|||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1"
|
||||
dependencies = [
|
||||
"phf_generator 0.13.1",
|
||||
"phf_shared 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
|
|
@ -4317,16 +4296,6 @@ dependencies = [
|
|||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"phf_shared 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.10.0"
|
||||
|
|
@ -4354,19 +4323,6 @@ dependencies = [
|
|||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef"
|
||||
dependencies = [
|
||||
"phf_generator 0.13.1",
|
||||
"phf_shared 0.13.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.117",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
|
|
@ -4394,15 +4350,6 @@ dependencies = [
|
|||
"siphasher 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266"
|
||||
dependencies = [
|
||||
"siphasher 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.16"
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ tauri-plugin-single-instance = "2.3.2"
|
|||
tauri-plugin-updater = "2.10.0"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
transcribe-rs = { version = "0.3.1", features = ["ort-directml"] }
|
||||
windows = { version = "0.61.3", features = [
|
||||
"Win32_Media_Audio_Endpoints",
|
||||
"Win32_System_Com_StructuredStorage",
|
||||
|
|
|
|||
|
|
@ -156,6 +156,9 @@ fn initialize_core_logic(app_handle: &AppHandle) {
|
|||
let history_manager =
|
||||
Arc::new(HistoryManager::new(app_handle).expect("Failed to initialize history manager"));
|
||||
|
||||
// Apply accelerator preferences before any model loads
|
||||
managers::transcription::apply_accelerator_settings(app_handle);
|
||||
|
||||
// Add managers to Tauri's managed state
|
||||
app_handle.manage(recording_manager.clone());
|
||||
app_handle.manage(model_manager.clone());
|
||||
|
|
@ -360,6 +363,9 @@ pub fn run(cli_args: CliArgs) {
|
|||
shortcut::change_keyboard_implementation_setting,
|
||||
shortcut::get_keyboard_implementation,
|
||||
shortcut::change_show_tray_icon_setting,
|
||||
shortcut::change_whisper_accelerator_setting,
|
||||
shortcut::change_ort_accelerator_setting,
|
||||
shortcut::get_available_accelerators,
|
||||
shortcut::handy_keys::start_handy_keys_recording,
|
||||
shortcut::handy_keys::stop_handy_keys_recording,
|
||||
trigger_update_check,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
use crate::audio_toolkit::{apply_custom_words, filter_transcription_output};
|
||||
use crate::managers::model::{EngineType, ModelManager};
|
||||
use crate::settings::{get_settings, ModelUnloadTimeout};
|
||||
use crate::settings::{
|
||||
get_settings, ModelUnloadTimeout, OrtAcceleratorSetting, WhisperAcceleratorSetting,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use log::{debug, error, info, warn};
|
||||
use serde::Serialize;
|
||||
use specta::Type;
|
||||
use std::panic::{catch_unwind, AssertUnwindSafe};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex, MutexGuard};
|
||||
|
|
@ -717,6 +720,55 @@ impl TranscriptionManager {
|
|||
}
|
||||
}
|
||||
|
||||
/// Apply the user's accelerator preferences to the transcribe-rs global atomics.
|
||||
/// Called on startup and whenever the user changes the setting.
|
||||
pub fn apply_accelerator_settings(app: &tauri::AppHandle) {
|
||||
use transcribe_rs::accel;
|
||||
|
||||
let settings = get_settings(app);
|
||||
|
||||
let whisper_pref = match settings.whisper_accelerator {
|
||||
WhisperAcceleratorSetting::Auto => accel::WhisperAccelerator::Auto,
|
||||
WhisperAcceleratorSetting::Cpu => accel::WhisperAccelerator::CpuOnly,
|
||||
WhisperAcceleratorSetting::Gpu => accel::WhisperAccelerator::Gpu,
|
||||
};
|
||||
accel::set_whisper_accelerator(whisper_pref);
|
||||
info!("Whisper accelerator set to: {}", whisper_pref);
|
||||
|
||||
let ort_pref = match settings.ort_accelerator {
|
||||
OrtAcceleratorSetting::Auto => accel::OrtAccelerator::Auto,
|
||||
OrtAcceleratorSetting::Cpu => accel::OrtAccelerator::CpuOnly,
|
||||
OrtAcceleratorSetting::Cuda => accel::OrtAccelerator::Cuda,
|
||||
OrtAcceleratorSetting::DirectMl => accel::OrtAccelerator::DirectMl,
|
||||
OrtAcceleratorSetting::Rocm => accel::OrtAccelerator::Rocm,
|
||||
};
|
||||
accel::set_ort_accelerator(ort_pref);
|
||||
info!("ORT accelerator set to: {}", ort_pref);
|
||||
}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, Type)]
|
||||
pub struct AvailableAccelerators {
|
||||
pub whisper: Vec<String>,
|
||||
pub ort: Vec<String>,
|
||||
}
|
||||
|
||||
/// Return which accelerators are compiled into this build.
|
||||
pub fn get_available_accelerators() -> AvailableAccelerators {
|
||||
use transcribe_rs::accel::OrtAccelerator;
|
||||
|
||||
let ort_options: Vec<String> = OrtAccelerator::available()
|
||||
.into_iter()
|
||||
.map(|a| a.to_string())
|
||||
.collect();
|
||||
|
||||
let whisper_options = vec!["auto".to_string(), "cpu".to_string(), "gpu".to_string()];
|
||||
|
||||
AvailableAccelerators {
|
||||
whisper: whisper_options,
|
||||
ort: ort_options,
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TranscriptionManager {
|
||||
fn drop(&mut self) {
|
||||
debug!("Shutting down TranscriptionManager");
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
use crate::managers::model::ModelManager;
|
||||
use anyhow::Result;
|
||||
use serde::Serialize;
|
||||
use specta::Type;
|
||||
use std::sync::Arc;
|
||||
use tauri::AppHandle;
|
||||
|
||||
|
|
@ -60,3 +61,20 @@ impl TranscriptionManager {
|
|||
Ok(String::new())
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op in CI mock.
|
||||
pub fn apply_accelerator_settings(_app: &tauri::AppHandle) {}
|
||||
|
||||
#[derive(Serialize, Clone, Debug, Type)]
|
||||
pub struct AvailableAccelerators {
|
||||
pub whisper: Vec<String>,
|
||||
pub ort: Vec<String>,
|
||||
}
|
||||
|
||||
/// Returns empty lists in CI mock.
|
||||
pub fn get_available_accelerators() -> AvailableAccelerators {
|
||||
AvailableAccelerators {
|
||||
whisper: vec![],
|
||||
ort: vec![],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,6 +273,37 @@ impl Default for TypingTool {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Type)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum WhisperAcceleratorSetting {
|
||||
Auto,
|
||||
Cpu,
|
||||
Gpu,
|
||||
}
|
||||
|
||||
impl Default for WhisperAcceleratorSetting {
|
||||
fn default() -> Self {
|
||||
WhisperAcceleratorSetting::Auto
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Type)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum OrtAcceleratorSetting {
|
||||
Auto,
|
||||
Cpu,
|
||||
Cuda,
|
||||
#[serde(rename = "directml")]
|
||||
DirectMl,
|
||||
Rocm,
|
||||
}
|
||||
|
||||
impl Default for OrtAcceleratorSetting {
|
||||
fn default() -> Self {
|
||||
OrtAcceleratorSetting::Auto
|
||||
}
|
||||
}
|
||||
|
||||
/* still handy for composing the initial JSON in the store ------------- */
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, Type)]
|
||||
pub struct AppSettings {
|
||||
|
|
@ -360,6 +391,10 @@ pub struct AppSettings {
|
|||
pub external_script_path: Option<String>,
|
||||
#[serde(default)]
|
||||
pub custom_filler_words: Option<Vec<String>>,
|
||||
#[serde(default)]
|
||||
pub whisper_accelerator: WhisperAcceleratorSetting,
|
||||
#[serde(default)]
|
||||
pub ort_accelerator: OrtAcceleratorSetting,
|
||||
}
|
||||
|
||||
fn default_model() -> String {
|
||||
|
|
@ -725,6 +760,8 @@ pub fn get_default_settings() -> AppSettings {
|
|||
typing_tool: default_typing_tool(),
|
||||
external_script_path: None,
|
||||
custom_filler_words: None,
|
||||
whisper_accelerator: WhisperAcceleratorSetting::default(),
|
||||
ort_accelerator: OrtAcceleratorSetting::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1067,3 +1067,48 @@ pub fn change_show_tray_icon_setting(app: AppHandle, enabled: bool) -> Result<()
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Save accelerator settings, re-apply globals, and unload the model so it
|
||||
/// reloads with the new backend on next transcription.
|
||||
fn apply_and_reload_accelerator(app: &AppHandle, s: settings::AppSettings) {
|
||||
settings::write_settings(app, s);
|
||||
crate::managers::transcription::apply_accelerator_settings(app);
|
||||
|
||||
let tm = app.state::<std::sync::Arc<crate::managers::transcription::TranscriptionManager>>();
|
||||
if tm.is_model_loaded() {
|
||||
if let Err(e) = tm.unload_model() {
|
||||
log::warn!("Failed to unload model after accelerator change: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_whisper_accelerator_setting(
|
||||
app: AppHandle,
|
||||
accelerator: settings::WhisperAcceleratorSetting,
|
||||
) -> Result<(), String> {
|
||||
let mut s = settings::get_settings(&app);
|
||||
s.whisper_accelerator = accelerator;
|
||||
apply_and_reload_accelerator(&app, s);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_ort_accelerator_setting(
|
||||
app: AppHandle,
|
||||
accelerator: settings::OrtAcceleratorSetting,
|
||||
) -> Result<(), String> {
|
||||
let mut s = settings::get_settings(&app);
|
||||
s.ort_accelerator = accelerator;
|
||||
apply_and_reload_accelerator(&app, s);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return which ORT accelerators are compiled into this build.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn get_available_accelerators() -> crate::managers::transcription::AvailableAccelerators {
|
||||
crate::managers::transcription::get_available_accelerators()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,6 +339,28 @@ async changeShowTrayIconSetting(enabled: boolean) : Promise<Result<null, string>
|
|||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async changeWhisperAcceleratorSetting(accelerator: WhisperAcceleratorSetting) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_whisper_accelerator_setting", { accelerator }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async changeOrtAcceleratorSetting(accelerator: OrtAcceleratorSetting) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_ort_accelerator_setting", { accelerator }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Return which ORT accelerators are compiled into this build.
|
||||
*/
|
||||
async getAvailableAccelerators() : Promise<AvailableAccelerators> {
|
||||
return await TAURI_INVOKE("get_available_accelerators");
|
||||
},
|
||||
/**
|
||||
* Start key recording mode
|
||||
*/
|
||||
|
|
@ -757,9 +779,10 @@ async isLaptop() : Promise<Result<boolean, string>> {
|
|||
|
||||
/** user-defined types **/
|
||||
|
||||
export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; experimental_enabled?: boolean; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number; typing_tool?: TypingTool; external_script_path: string | null; custom_filler_words?: string[] | null }
|
||||
export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; auto_submit?: boolean; auto_submit_key?: AutoSubmitKey; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string; experimental_enabled?: boolean; keyboard_implementation?: KeyboardImplementation; show_tray_icon?: boolean; paste_delay_ms?: number; typing_tool?: TypingTool; external_script_path: string | null; custom_filler_words?: string[] | null; whisper_accelerator?: WhisperAcceleratorSetting; ort_accelerator?: OrtAcceleratorSetting }
|
||||
export type AudioDevice = { index: string; name: string; is_default: boolean }
|
||||
export type AutoSubmitKey = "enter" | "ctrl_enter" | "cmd_enter"
|
||||
export type AvailableAccelerators = { whisper: string[]; ort: string[] }
|
||||
export type BindingResponse = { success: boolean; binding: ShortcutBinding | null; error: string | null }
|
||||
export type ClipboardHandling = "dont_modify" | "copy_to_clipboard"
|
||||
export type CustomSounds = { start: boolean; stop: boolean }
|
||||
|
|
@ -779,6 +802,7 @@ export type LogLevel = "trace" | "debug" | "info" | "warn" | "error"
|
|||
export type ModelInfo = { id: string; name: string; description: string; filename: string; url: string | null; size_mb: number; is_downloaded: boolean; is_downloading: boolean; partial_size: number; is_directory: boolean; engine_type: EngineType; accuracy_score: number; speed_score: number; supports_translation: boolean; is_recommended: boolean; supported_languages: string[]; supports_language_selection: boolean; is_custom: boolean }
|
||||
export type ModelLoadStatus = { is_loaded: boolean; current_model: string | null }
|
||||
export type ModelUnloadTimeout = "never" | "immediately" | "min_2" | "min_5" | "min_10" | "min_15" | "hour_1" | "sec_5"
|
||||
export type OrtAcceleratorSetting = "auto" | "cpu" | "cuda" | "directml" | "rocm"
|
||||
export type OverlayPosition = "none" | "top" | "bottom"
|
||||
export type PasteMethod = "ctrl_v" | "direct" | "none" | "shift_insert" | "ctrl_shift_v" | "external_script"
|
||||
export type PermissionAccess = "allowed" | "denied" | "unknown"
|
||||
|
|
@ -787,6 +811,7 @@ export type RecordingRetentionPeriod = "never" | "preserve_limit" | "days_3" | "
|
|||
export type ShortcutBinding = { id: string; name: string; description: string; default_binding: string; current_binding: string }
|
||||
export type SoundTheme = "marimba" | "pop" | "custom"
|
||||
export type TypingTool = "auto" | "wtype" | "kwtype" | "dotool" | "ydotool" | "xdotool"
|
||||
export type WhisperAcceleratorSetting = "auto" | "cpu" | "gpu"
|
||||
export type WindowsMicrophonePermissionStatus = { supported: boolean; overall_access: PermissionAccess; device_access: PermissionAccess; app_access: PermissionAccess; desktop_app_access: PermissionAccess }
|
||||
|
||||
/** tauri-specta globals **/
|
||||
|
|
|
|||
106
src/components/settings/AccelerationSelector.tsx
Normal file
106
src/components/settings/AccelerationSelector.tsx
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import { type FC, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SettingContainer } from "../ui/SettingContainer";
|
||||
import { Dropdown, type DropdownOption } from "../ui/Dropdown";
|
||||
import { useSettings } from "../../hooks/useSettings";
|
||||
import { commands } from "@/bindings";
|
||||
import type {
|
||||
WhisperAcceleratorSetting,
|
||||
OrtAcceleratorSetting,
|
||||
} from "@/bindings";
|
||||
|
||||
const WHISPER_LABELS: Record<WhisperAcceleratorSetting, string> = {
|
||||
auto: "Auto",
|
||||
cpu: "CPU",
|
||||
gpu: "GPU",
|
||||
};
|
||||
|
||||
const ORT_LABELS: Record<OrtAcceleratorSetting, string> = {
|
||||
auto: "Auto",
|
||||
cpu: "CPU",
|
||||
cuda: "CUDA",
|
||||
directml: "DirectML",
|
||||
rocm: "ROCm",
|
||||
};
|
||||
|
||||
interface AccelerationSelectorProps {
|
||||
descriptionMode?: "tooltip" | "inline";
|
||||
grouped?: boolean;
|
||||
}
|
||||
|
||||
export const AccelerationSelector: FC<AccelerationSelectorProps> = ({
|
||||
descriptionMode = "tooltip",
|
||||
grouped = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { getSetting, updateSetting, isUpdating } = useSettings();
|
||||
|
||||
const [whisperOptions, setWhisperOptions] = useState<DropdownOption[]>([]);
|
||||
const [ortOptions, setOrtOptions] = useState<DropdownOption[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
commands.getAvailableAccelerators().then((available) => {
|
||||
setWhisperOptions(
|
||||
available.whisper.map((v) => ({
|
||||
value: v,
|
||||
label: WHISPER_LABELS[v as WhisperAcceleratorSetting] ?? v,
|
||||
})),
|
||||
);
|
||||
// Always include "auto" for ORT even though available() only returns compiled-in backends
|
||||
const ortVals = available.ort.includes("auto")
|
||||
? available.ort
|
||||
: ["auto", ...available.ort];
|
||||
setOrtOptions(
|
||||
ortVals.map((v) => ({
|
||||
value: v,
|
||||
label: ORT_LABELS[v as OrtAcceleratorSetting] ?? v,
|
||||
})),
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const currentWhisper = getSetting("whisper_accelerator") ?? "auto";
|
||||
const currentOrt = getSetting("ort_accelerator") ?? "auto";
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingContainer
|
||||
title={t("settings.advanced.acceleration.whisper.title")}
|
||||
description={t("settings.advanced.acceleration.whisper.description")}
|
||||
descriptionMode={descriptionMode}
|
||||
grouped={grouped}
|
||||
layout="horizontal"
|
||||
>
|
||||
<Dropdown
|
||||
options={whisperOptions}
|
||||
selectedValue={currentWhisper}
|
||||
onSelect={(value) =>
|
||||
updateSetting(
|
||||
"whisper_accelerator",
|
||||
value as WhisperAcceleratorSetting,
|
||||
)
|
||||
}
|
||||
disabled={isUpdating("whisper_accelerator")}
|
||||
/>
|
||||
</SettingContainer>
|
||||
{ortOptions.length > 2 && (
|
||||
<SettingContainer
|
||||
title={t("settings.advanced.acceleration.ort.title")}
|
||||
description={t("settings.advanced.acceleration.ort.description")}
|
||||
descriptionMode={descriptionMode}
|
||||
grouped={grouped}
|
||||
layout="horizontal"
|
||||
>
|
||||
<Dropdown
|
||||
options={ortOptions}
|
||||
selectedValue={currentOrt}
|
||||
onSelect={(value) =>
|
||||
updateSetting("ort_accelerator", value as OrtAcceleratorSetting)
|
||||
}
|
||||
disabled={isUpdating("ort_accelerator")}
|
||||
/>
|
||||
</SettingContainer>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -18,6 +18,7 @@ import { RecordingRetentionPeriodSelector } from "../RecordingRetentionPeriod";
|
|||
import { ExperimentalToggle } from "../ExperimentalToggle";
|
||||
import { useSettings } from "../../../hooks/useSettings";
|
||||
import { KeyboardImplementationSelector } from "../debug/KeyboardImplementationSelector";
|
||||
import { AccelerationSelector } from "../AccelerationSelector";
|
||||
|
||||
export const AdvancedSettings: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
|
|
@ -62,6 +63,7 @@ export const AdvancedSettings: React.FC = () => {
|
|||
descriptionMode="tooltip"
|
||||
grouped={true}
|
||||
/>
|
||||
<AccelerationSelector descriptionMode="tooltip" grouped={true} />
|
||||
</SettingsGroup>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -223,6 +223,16 @@
|
|||
"label": "الميزات التجريبية",
|
||||
"description": ".تمكين الميزات التجريبية التي لا تزال قيد التطوير"
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "تسريع Whisper",
|
||||
"description": "تسريع الأجهزة لنماذج Whisper. الوضع التلقائي يستخدم GPU إن توفر (Metal على macOS، Vulkan على Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "تسريع ONNX",
|
||||
"description": "تسريع الأجهزة لنماذج ONNX (Parakeet، Canary، Moonshine، إلخ). DirectML على Windows تجريبي. قد تفشل النماذج في النسخ."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "بدء مخفي",
|
||||
"description": ".التشغيل في صينية النظام دون فتح النافذة"
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Experimentální funkce",
|
||||
"description": "Povolit experimentální funkce, které jsou stále ve vývoji."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Akcelerace Whisper",
|
||||
"description": "Hardwarová akcelerace pro modely Whisper. Automatický režim používá GPU, pokud je k dispozici (Metal na macOS, Vulkan na Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Akcelerace ONNX",
|
||||
"description": "Hardwarová akcelerace pro modely ONNX (Parakeet, Canary, Moonshine atd.). DirectML na Windows je experimentální. Modely nemusí správně přepisovat."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Spouštět skrytě",
|
||||
"description": "Spustit do systémové lišty bez otevření okna."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Experimentelle Funktionen",
|
||||
"description": "Experimentelle Funktionen aktivieren, die sich noch in Entwicklung befinden."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper-Beschleunigung",
|
||||
"description": "Hardwarebeschleunigung für Whisper-Modelle. Automatisch nutzt GPU falls verfügbar (Metal auf macOS, Vulkan auf Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX-Beschleunigung",
|
||||
"description": "Hardwarebeschleunigung für ONNX-Modelle (Parakeet, Canary, Moonshine usw.). DirectML unter Windows ist experimentell. Modelle können bei der Transkription fehlschlagen."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Versteckt starten",
|
||||
"description": "In den Systembereich starten, ohne das Fenster zu öffnen."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Experimental Features",
|
||||
"description": "Enable experimental features that are still in development."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper Acceleration",
|
||||
"description": "Hardware acceleration for Whisper models. Auto uses GPU if available (Metal on macOS, Vulkan on Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX Acceleration",
|
||||
"description": "Hardware acceleration for ONNX models (Parakeet, Canary, Moonshine, etc.). DirectML on Windows is experimental. Models may fail to transcribe."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Start Hidden",
|
||||
"description": "Launch to system tray without opening the window."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Funciones Experimentales",
|
||||
"description": "Habilitar funciones experimentales que aún están en desarrollo."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Aceleración de Whisper",
|
||||
"description": "Aceleración por hardware para modelos Whisper. Auto usa GPU si está disponible (Metal en macOS, Vulkan en Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Aceleración de ONNX",
|
||||
"description": "Aceleración por hardware para modelos ONNX (Parakeet, Canary, Moonshine, etc.). DirectML en Windows es experimental. Los modelos pueden fallar al transcribir."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Iniciar Oculto",
|
||||
"description": "Lanzar en la bandeja del sistema sin abrir la ventana."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Fonctionnalités Expérimentales",
|
||||
"description": "Activer les fonctionnalités expérimentales encore en développement."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Accélération Whisper",
|
||||
"description": "Accélération matérielle pour les modèles Whisper. Auto utilise le GPU si disponible (Metal sur macOS, Vulkan sur Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Accélération ONNX",
|
||||
"description": "Accélération matérielle pour les modèles ONNX (Parakeet, Canary, Moonshine, etc.). DirectML sur Windows est expérimental. Les modèles peuvent échouer à transcrire."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Démarrer masqué",
|
||||
"description": "Lancer dans la barre système sans ouvrir la fenêtre."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Funzionalità Sperimentali",
|
||||
"description": "Abilita le funzionalità sperimentali ancora in fase di sviluppo."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Accelerazione Whisper",
|
||||
"description": "Accelerazione hardware per i modelli Whisper. Auto utilizza la GPU se disponibile (Metal su macOS, Vulkan su Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Accelerazione ONNX",
|
||||
"description": "Accelerazione hardware per i modelli ONNX (Parakeet, Canary, Moonshine, ecc.). DirectML su Windows è sperimentale. I modelli potrebbero non riuscire a trascrivere."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Avvia in Background",
|
||||
"description": "Avvia l'applicazione in background senza aprire la finestra."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "実験的機能",
|
||||
"description": "まだ開発中の実験的機能を有効にします。"
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper アクセラレーション",
|
||||
"description": "Whisper モデルのハードウェアアクセラレーション。自動モードでは利用可能な場合 GPU を使用します(macOS では Metal、Windows/Linux では Vulkan)。"
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX アクセラレーション",
|
||||
"description": "ONNX モデルのハードウェアアクセラレーション(Parakeet、Canary、Moonshine など)。Windows の DirectML は実験的です。モデルの文字起こしに失敗する場合があります。"
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "非表示で起動",
|
||||
"description": "ウィンドウを開かずにシステムトレイに起動。"
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "실험적 기능",
|
||||
"description": "개발 중인 실험적 기능을 활성화합니다."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper 가속",
|
||||
"description": "Whisper 모델의 하드웨어 가속. 자동 모드는 GPU를 사용합니다 (macOS에서는 Metal, Windows/Linux에서는 Vulkan)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX 가속",
|
||||
"description": "ONNX 모델의 하드웨어 가속 (Parakeet, Canary, Moonshine 등). Windows의 DirectML은 실험적입니다. 모델이 전사에 실패할 수 있습니다."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "숨김으로 시작",
|
||||
"description": "창을 열지 않고 시스템 트레이에서 실행합니다."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Funkcje Eksperymentalne",
|
||||
"description": "Włącz funkcje eksperymentalne, które są jeszcze w fazie rozwoju."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Akceleracja Whisper",
|
||||
"description": "Akceleracja sprzętowa dla modeli Whisper. Tryb automatyczny używa GPU, jeśli jest dostępny (Metal na macOS, Vulkan na Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Akceleracja ONNX",
|
||||
"description": "Akceleracja sprzętowa dla modeli ONNX (Parakeet, Canary, Moonshine itp.). DirectML na Windows jest eksperymentalne. Modele mogą nie transkrybować poprawnie."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Uruchom ukryty",
|
||||
"description": "Uruchom w zasobniku systemowym bez otwierania okna."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Recursos Experimentais",
|
||||
"description": "Ativar recursos experimentais que ainda estão em desenvolvimento."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Aceleração Whisper",
|
||||
"description": "Aceleração por hardware para modelos Whisper. Auto usa GPU se disponível (Metal no macOS, Vulkan no Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Aceleração ONNX",
|
||||
"description": "Aceleração por hardware para modelos ONNX (Parakeet, Canary, Moonshine, etc.). DirectML no Windows é experimental. Os modelos podem falhar na transcrição."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Iniciar Oculto",
|
||||
"description": "Iniciar na bandeja do sistema sem abrir a janela."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Экспериментальные функции",
|
||||
"description": "Включить экспериментальные функции, которые находятся в разработке."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Ускорение Whisper",
|
||||
"description": "Аппаратное ускорение для моделей Whisper. Автоматический режим использует GPU при наличии (Metal на macOS, Vulkan на Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Ускорение ONNX",
|
||||
"description": "Аппаратное ускорение для моделей ONNX (Parakeet, Canary, Moonshine и др.). DirectML на Windows является экспериментальным. Модели могут не выполнять транскрипцию."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Скрыть при запуске",
|
||||
"description": "Запускать в системный трей, не открывая окно."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Deneysel Özellikler",
|
||||
"description": "Hala geliştirme aşamasında olan deneysel özellikleri etkinleştir."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper Hızlandırma",
|
||||
"description": "Whisper modelleri için donanım hızlandırma. Otomatik mod, mevcutsa GPU kullanır (macOS'ta Metal, Windows/Linux'ta Vulkan)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX Hızlandırma",
|
||||
"description": "ONNX modelleri için donanım hızlandırma (Parakeet, Canary, Moonshine vb.). Windows'ta DirectML deneyseldir. Modeller transkripsiyon yapamayabilir."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Gizli Başlat",
|
||||
"description": "Pencereyi açmadan sistem tepsisinde başlatır."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Експериментальні функції",
|
||||
"description": "Увімкнути експериментальні функції, які ще в розробці."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Прискорення Whisper",
|
||||
"description": "Апаратне прискорення для моделей Whisper. Автоматичний режим використовує GPU за наявності (Metal на macOS, Vulkan на Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Прискорення ONNX",
|
||||
"description": "Апаратне прискорення для моделей ONNX (Parakeet, Canary, Moonshine тощо). DirectML на Windows є експериментальним. Моделі можуть не виконувати транскрипцію."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Запуск у фоні",
|
||||
"description": "Запускати в системному треї без відкриття вікна"
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "Tính năng thử nghiệm",
|
||||
"description": "Bật các tính năng thử nghiệm đang trong quá trình phát triển."
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Tăng tốc Whisper",
|
||||
"description": "Tăng tốc phần cứng cho các mô hình Whisper. Chế độ tự động sử dụng GPU nếu có (Metal trên macOS, Vulkan trên Windows/Linux)."
|
||||
},
|
||||
"ort": {
|
||||
"title": "Tăng tốc ONNX",
|
||||
"description": "Tăng tốc phần cứng cho các mô hình ONNX (Parakeet, Canary, Moonshine, v.v.). DirectML trên Windows là thử nghiệm. Các mô hình có thể không chuyển đổi giọng nói được."
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "Khởi động ẩn",
|
||||
"description": "Khởi động vào khay hệ thống mà không mở cửa sổ."
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "實驗性功能",
|
||||
"description": "啟用仍在開發中的實驗性功能"
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper 加速",
|
||||
"description": "Whisper 模型的硬體加速。自動模式在可用時使用 GPU(macOS 上使用 Metal,Windows/Linux 上使用 Vulkan)。"
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX 加速",
|
||||
"description": "ONNX 模型的硬體加速(Parakeet、Canary、Moonshine 等)。Windows 上的 DirectML 為實驗性功能。模型可能無法正常轉錄。"
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "隱藏啟動",
|
||||
"description": "啟動至系統匣而不開啟視窗"
|
||||
|
|
|
|||
|
|
@ -245,6 +245,16 @@
|
|||
"label": "实验性功能",
|
||||
"description": "启用仍在开发中的实验性功能。"
|
||||
},
|
||||
"acceleration": {
|
||||
"whisper": {
|
||||
"title": "Whisper 加速",
|
||||
"description": "Whisper 模型的硬件加速。自动模式在可用时使用 GPU(macOS 上使用 Metal,Windows/Linux 上使用 Vulkan)。"
|
||||
},
|
||||
"ort": {
|
||||
"title": "ONNX 加速",
|
||||
"description": "ONNX 模型的硬件加速(Parakeet、Canary、Moonshine 等)。Windows 上的 DirectML 为实验性功能。模型可能无法正常转录。"
|
||||
}
|
||||
},
|
||||
"startHidden": {
|
||||
"label": "隐藏启动",
|
||||
"description": "启动到系统托盘而不打开窗口。"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
import { create } from "zustand";
|
||||
import { subscribeWithSelector } from "zustand/middleware";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import type { AppSettings as Settings, AudioDevice } from "@/bindings";
|
||||
import type {
|
||||
AppSettings as Settings,
|
||||
AudioDevice,
|
||||
WhisperAcceleratorSetting,
|
||||
OrtAcceleratorSetting,
|
||||
} from "@/bindings";
|
||||
import { commands } from "@/bindings";
|
||||
|
||||
interface SettingsStore {
|
||||
|
|
@ -136,6 +141,12 @@ const settingUpdaters: {
|
|||
commands.changeExperimentalEnabledSetting(value as boolean),
|
||||
show_tray_icon: (value) =>
|
||||
commands.changeShowTrayIconSetting(value as boolean),
|
||||
whisper_accelerator: (value) =>
|
||||
commands.changeWhisperAcceleratorSetting(
|
||||
value as WhisperAcceleratorSetting,
|
||||
),
|
||||
ort_accelerator: (value) =>
|
||||
commands.changeOrtAcceleratorSetting(value as OrtAcceleratorSetting),
|
||||
};
|
||||
|
||||
export const useSettingsStore = create<SettingsStore>()(
|
||||
|
|
|
|||
Loading…
Reference in a new issue