diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 45bdeb7..e88db4a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -6992,9 +6992,9 @@ dependencies = [ [[package]] name = "transcribe-rs" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d72db290071cb4c3da90136174b1a108771311a5d506c74738e1a4da71da2c38" +checksum = "b231bc9bd1b20be89583a49c3885dfa7d7323299564ee78eddf83db04f2b337b" dependencies = [ "base64 0.22.1", "derive_builder", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 863acc6..ca2745f 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -69,7 +69,7 @@ rusqlite = { version = "0.37", features = ["bundled"] } tar = "0.4.44" flate2 = "1.0" sha2 = "0.10" -transcribe-rs = { version = "0.3.5", features = ["whisper-cpp", "onnx"] } +transcribe-rs = { version = "0.3.8", features = ["whisper-cpp", "onnx"] } handy-keys = "0.2.4" ferrous-opencc = "0.2.3" clap = { version = "4", features = ["derive"] } diff --git a/src-tauri/src/managers/model.rs b/src-tauri/src/managers/model.rs index bce85d3..6fab71c 100644 --- a/src-tauri/src/managers/model.rs +++ b/src-tauri/src/managers/model.rs @@ -26,6 +26,7 @@ pub enum EngineType { SenseVoice, GigaAM, Canary, + Cohere, } #[derive(Debug, Clone, Serialize, Deserialize, Type)] @@ -133,7 +134,7 @@ impl ModelManager { sha256: Some( "1be3a9b2063867b937e64e2ec7483364a79917e157fa98c5d94b5c1fffea987b".to_string(), ), - size_mb: 487, + size_mb: 465, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -161,7 +162,7 @@ impl ModelManager { sha256: Some( "79283fc1f9fe12ca3248543fbd54b73292164d8df5a16e095e2bceeaaabddf57".to_string(), ), - size_mb: 492, // Approximate size + size_mb: 469, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -188,7 +189,7 @@ impl ModelManager { sha256: Some( "1fc70f774d38eb169993ac391eea357ef47c88757ef72ee5943879b7e8e2bc69".to_string(), ), - size_mb: 1600, // Approximate size + size_mb: 1549, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -215,7 +216,7 @@ impl ModelManager { sha256: Some( "d75795ecff3f83b5faa89d1900604ad8c780abd5739fae406de19f23ecd98ad1".to_string(), ), - size_mb: 1100, // Approximate size + size_mb: 1031, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -243,7 +244,7 @@ impl ModelManager { sha256: Some( "8efbf0ce8a3f50fe332b7617da787fb81354b358c288b008d3bdef8359df64c6".to_string(), ), - size_mb: 1080, + size_mb: 1030, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -271,7 +272,7 @@ impl ModelManager { sha256: Some( "ac9b9429984dd565b25097337a887bb7f0f8ac393573661c651f0e7d31563991".to_string(), ), - size_mb: 473, // Approximate size for int8 quantized model + size_mb: 451, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -308,7 +309,7 @@ impl ModelManager { sha256: Some( "43d37191602727524a7d8c6da0eef11c4ba24320f5b4730f1a2497befc2efa77".to_string(), ), - size_mb: 478, // Approximate size for int8 quantized model + size_mb: 456, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -335,7 +336,7 @@ impl ModelManager { sha256: Some( "04bf6ab012cfceebd4ac7cf88c1b31d027bbdd3cd704649b692e2e935236b7e8".to_string(), ), - size_mb: 58, + size_mb: 55, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -393,7 +394,7 @@ impl ModelManager { sha256: Some( "dbb3e1c1832bd88a4ac712f7449a136cc2c9a18c5fe33a12ed1b7cb1cfe9cdd5".to_string(), ), - size_mb: 100, + size_mb: 99, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -457,7 +458,7 @@ impl ModelManager { sha256: Some( "171d611fe5d353a50bbb741b6f3ef42559b1565685684e9aa888ef563ba3e8a4".to_string(), ), - size_mb: 160, + size_mb: 152, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -487,7 +488,7 @@ impl ModelManager { sha256: Some( "d872462268430db140b69b72e0fc4b787b194c1dbe51b58de39444d55b6da45b".to_string(), ), - size_mb: 152, + size_mb: 151, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -558,7 +559,7 @@ impl ModelManager { sha256: Some( "02305b2a25f9cf3e7deaffa7f94df00efa44f442cd55c101c2cb9c000f904666".to_string(), ), - size_mb: 692, + size_mb: 691, is_downloaded: false, is_downloading: false, partial_size: 0, @@ -574,6 +575,41 @@ impl ModelManager { }, ); + let cohere_languages: Vec = vec![ + "en", "fr", "de", "it", "es", "pt", "el", "nl", "pl", "zh", "zh-Hans", "zh-Hant", "ja", + "ko", "vi", "ar", + ] + .into_iter() + .map(String::from) + .collect(); + + available_models.insert( + "cohere-int8".to_string(), + ModelInfo { + id: "cohere-int8".to_string(), + name: "Cohere".to_string(), + description: "A large, slower, but very accurate multilingual model.".to_string(), + filename: "cohere-int8".to_string(), + url: Some("https://blob.handy.computer/cohere-int8.tar.gz".to_string()), + sha256: Some( + "ea2257d52434f3644574f187dcdcf666e302cd11b92866116ab8e14cd9c887f0".to_string(), + ), + size_mb: 1708, + is_downloaded: false, + is_downloading: false, + partial_size: 0, + is_directory: true, + engine_type: EngineType::Cohere, + accuracy_score: 0.90, + speed_score: 0.60, + supports_translation: false, + is_recommended: false, + supported_languages: cohere_languages, + supports_language_selection: true, + is_custom: false, + }, + ); + // Auto-discover custom Whisper models (.bin files) in the models directory if let Err(e) = Self::discover_custom_whisper_models(&models_dir, &mut available_models) { warn!("Failed to discover custom models: {}", e); diff --git a/src-tauri/src/managers/transcription.rs b/src-tauri/src/managers/transcription.rs index 53b3b9f..0844b93 100644 --- a/src-tauri/src/managers/transcription.rs +++ b/src-tauri/src/managers/transcription.rs @@ -17,6 +17,7 @@ use tauri::{AppHandle, Emitter, Manager}; use transcribe_rs::{ onnx::{ canary::CanaryModel, + cohere::CohereModel, gigaam::GigaAMModel, moonshine::{MoonshineModel, MoonshineVariant, StreamingModel}, parakeet::{ParakeetModel, ParakeetParams, TimestampGranularity}, @@ -43,6 +44,7 @@ enum LoadedEngine { SenseVoice(SenseVoiceModel), GigaAM(GigaAMModel), Canary(CanaryModel), + Cohere(CohereModel), } /// RAII guard that clears the `is_loading` flag and notifies waiters on drop. @@ -367,6 +369,14 @@ impl TranscriptionManager { })?; LoadedEngine::Canary(engine) } + EngineType::Cohere => { + let engine = CohereModel::load(&model_path, &Quantization::Int8).map_err(|e| { + let error_msg = format!("Failed to load cohere model {}: {}", model_id, e); + emit_loading_failed(&error_msg); + anyhow::anyhow!(error_msg) + })?; + LoadedEngine::Cohere(engine) + } }; // Update the current engine and model ID @@ -601,6 +611,24 @@ impl TranscriptionManager { .transcribe(&audio, &options) .map_err(|e| anyhow::anyhow!("Canary transcription failed: {}", e)) } + LoadedEngine::Cohere(cohere_engine) => { + let lang = if validated_language == "auto" { + None + } else if validated_language == "zh-Hans" + || validated_language == "zh-Hant" + { + Some("zh".to_string()) + } else { + Some(validated_language.clone()) + }; + let options = TranscribeOptions { + language: lang, + ..Default::default() + }; + cohere_engine + .transcribe(&audio, &options) + .map_err(|e| anyhow::anyhow!("Cohere transcription failed: {}", e)) + } } }, )); diff --git a/src/bindings.ts b/src/bindings.ts index 6d50b1f..378d630 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -834,7 +834,7 @@ export type AvailableAccelerators = { whisper: string[]; ort: string[]; gpu_devi 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 } -export type EngineType = "Whisper" | "Parakeet" | "Moonshine" | "MoonshineStreaming" | "SenseVoice" | "GigaAM" | "Canary" +export type EngineType = "Whisper" | "Parakeet" | "Moonshine" | "MoonshineStreaming" | "SenseVoice" | "GigaAM" | "Canary" | "Cohere" export type GpuDeviceOption = { id: number; name: string; total_vram_mb: number } export type HistoryEntry = { id: number; file_name: string; timestamp: number; saved: boolean; title: string; transcription_text: string; post_processed_text: string | null; post_process_prompt: string | null; post_process_requested: boolean } export type HistoryUpdatePayload = { action: "added"; entry: HistoryEntry } | { action: "updated"; entry: HistoryEntry } | { action: "deleted"; id: number } | { action: "toggled"; id: number } diff --git a/src/i18n/languages.ts b/src/i18n/languages.ts index 5217bd5..e2fe872 100644 --- a/src/i18n/languages.ts +++ b/src/i18n/languages.ts @@ -35,5 +35,5 @@ export const LANGUAGE_METADATA: Record< ar: { name: "Arabic", nativeName: "العربية", priority: 17, direction: "rtl" }, he: { name: "Hebrew", nativeName: "עברית", priority: 18, direction: "rtl" }, sv: { name: "Swedish", nativeName: "Svenska", priority: 19 }, - bg: { name: "Bulgarian", nativeName: "Български", priority: 20 } + bg: { name: "Bulgarian", nativeName: "Български", priority: 20 }, }; diff --git a/src/i18n/locales/ar/translation.json b/src/i18n/locales/ar/translation.json index feb641e..52c52d1 100644 --- a/src/i18n/locales/ar/translation.json +++ b/src/i18n/locales/ar/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "متعدد اللغات ودقيق. 25 لغة أوروبية. يدعم الترجمة." + }, + "cohere-int8": { + "name": "Cohere", + "description": "نموذج كبير وأبطأ، لكنه دقيق جداً ومتعدد اللغات." } }, "errors": { diff --git a/src/i18n/locales/bg/translation.json b/src/i18n/locales/bg/translation.json index 10d6389..fada42f 100644 --- a/src/i18n/locales/bg/translation.json +++ b/src/i18n/locales/bg/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Точен многоезичен. 25 европейски езика. Поддържа превод." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Голям, по-бавен, но много точен многоезичен модел." } }, "errors": { diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index d73a3c6..345bcd4 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Přesný vícejazyčný. 25 evropských jazyků. Podporuje překlad." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Velký, pomalejší, ale velmi přesný vícejazyčný model." } }, "errors": { diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index 1f5acdd..30adc79 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Genaue mehrsprachige Erkennung. 25 europäische Sprachen. Unterstützt Übersetzung." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Ein großes, langsameres, aber sehr genaues mehrsprachiges Modell." } }, "errors": { diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index 775e33c..c3fb449 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Accurate multilingual. 25 European languages. Supports translation." + }, + "cohere-int8": { + "name": "Cohere", + "description": "A large, slower, but very accurate multilingual model." } }, "errors": { diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index ac3c7db..dd4420e 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Multilingüe preciso. 25 idiomas europeos. Soporta traducción." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Un modelo grande, más lento, pero muy preciso y multilingüe." } }, "errors": { diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 58c13b4..9b82798 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Multilingue précis. 25 langues européennes. Supporte la traduction." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Un modèle volumineux, plus lent, mais très précis et multilingue." } }, "errors": { diff --git a/src/i18n/locales/he/translation.json b/src/i18n/locales/he/translation.json index 2a14f50..7c3f792 100644 --- a/src/i18n/locales/he/translation.json +++ b/src/i18n/locales/he/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "רב-לשוני ומדויק. 25 שפות אירופיות. תומך בתרגום." + }, + "cohere-int8": { + "name": "Cohere", + "description": "מודל גדול, איטי יותר, אך מדויק מאוד ורב-לשוני." } }, "errors": { diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index c1fb10e..1754393 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Multilingue accurato. 25 lingue europee. Supporta la traduzione." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Un modello grande, più lento, ma molto accurato e multilingue." } }, "errors": { diff --git a/src/i18n/locales/ja/translation.json b/src/i18n/locales/ja/translation.json index 7aa003a..86313af 100644 --- a/src/i18n/locales/ja/translation.json +++ b/src/i18n/locales/ja/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "高精度な多言語対応。25のヨーロッパ言語。翻訳対応。" + }, + "cohere-int8": { + "name": "Cohere", + "description": "大型で低速ですが、非常に高精度な多言語モデル。" } }, "errors": { diff --git a/src/i18n/locales/ko/translation.json b/src/i18n/locales/ko/translation.json index b8b2bf2..954583f 100644 --- a/src/i18n/locales/ko/translation.json +++ b/src/i18n/locales/ko/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "정확한 다국어 지원. 25개 유럽 언어. 번역 지원." + }, + "cohere-int8": { + "name": "Cohere", + "description": "크고 느리지만 매우 정확한 다국어 모델." } }, "errors": { diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index c90e0b7..dff12ca 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Dokładny wielojęzyczny. 25 języków europejskich. Obsługuje tłumaczenie." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Duży, wolniejszy, ale bardzo dokładny model wielojęzyczny." } }, "errors": { diff --git a/src/i18n/locales/pt/translation.json b/src/i18n/locales/pt/translation.json index 00c3308..fc31887 100644 --- a/src/i18n/locales/pt/translation.json +++ b/src/i18n/locales/pt/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Multilíngue preciso. 25 idiomas europeus. Suporta tradução." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Um modelo grande, mais lento, mas muito preciso e multilíngue." } }, "errors": { diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index 359904b..4c674d7 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Точная многоязычная. 25 европейских языков. Поддержка перевода." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Большая, медленная, но очень точная многоязычная модель." } }, "errors": { diff --git a/src/i18n/locales/sv/translation.json b/src/i18n/locales/sv/translation.json index 413143d..d809651 100644 --- a/src/i18n/locales/sv/translation.json +++ b/src/i18n/locales/sv/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Noggrann flerspråkig. 25 europeiska språk. Stöder översättning." + }, + "cohere-int8": { + "name": "Cohere", + "description": "En stor, långsammare, men mycket noggrann flerspråkig modell." } }, "errors": { diff --git a/src/i18n/locales/tr/translation.json b/src/i18n/locales/tr/translation.json index 5973d23..e81c7a8 100644 --- a/src/i18n/locales/tr/translation.json +++ b/src/i18n/locales/tr/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Doğru çok dilli. 25 Avrupa dili. Çeviri desteği." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Büyük, daha yavaş, ancak çok doğru çok dilli bir model." } }, "errors": { diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index 6c56dab..982a6db 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Точна багатомовна. 25 європейських мов. Підтримує переклад." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Велика, повільніша, але дуже точна багатомовна модель." } }, "errors": { diff --git a/src/i18n/locales/vi/translation.json b/src/i18n/locales/vi/translation.json index 87c4d16..9821039 100644 --- a/src/i18n/locales/vi/translation.json +++ b/src/i18n/locales/vi/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "Đa ngôn ngữ chính xác. 25 ngôn ngữ châu Âu. Hỗ trợ dịch thuật." + }, + "cohere-int8": { + "name": "Cohere", + "description": "Mô hình lớn, chậm hơn, nhưng rất chính xác và đa ngôn ngữ." } }, "errors": { diff --git a/src/i18n/locales/zh-TW/translation.json b/src/i18n/locales/zh-TW/translation.json index bc95dfc..3009cf1 100644 --- a/src/i18n/locales/zh-TW/translation.json +++ b/src/i18n/locales/zh-TW/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "準確的多語言模型。25種歐洲語言。支援翻譯。" + }, + "cohere-int8": { + "name": "Cohere", + "description": "大型模型,速度較慢,但多語言辨識非常準確。" } }, "errors": { diff --git a/src/i18n/locales/zh/translation.json b/src/i18n/locales/zh/translation.json index 5230568..b105580 100644 --- a/src/i18n/locales/zh/translation.json +++ b/src/i18n/locales/zh/translation.json @@ -88,6 +88,10 @@ "canary-1b-v2": { "name": "Canary 1B v2", "description": "准确的多语言模型。25种欧洲语言。支持翻译。" + }, + "cohere-int8": { + "name": "Cohere", + "description": "大型模型,速度较慢,但多语言识别非常准确。" } }, "errors": {