support moonshine v2 (#837)

* support moonshine v2

* format

* add translations for models
This commit is contained in:
CJ Pais 2026-02-17 11:44:10 +08:00 committed by GitHub
parent 203ba1dbc2
commit 83e6f5c492
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 602 additions and 79 deletions

4
src-tauri/Cargo.lock generated
View file

@ -7083,9 +7083,9 @@ dependencies = [
[[package]]
name = "transcribe-rs"
version = "0.2.3"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2039bf80d6497655ecdef8ebfa10583862fad3cc017077e105bc1c18b7502ff8"
checksum = "23e3bf6e1dd4909268796bdf3794fb6fda70f4a0e5a80e2e56cd3fc213a11586"
dependencies = [
"base64 0.22.1",
"derive_builder",

View file

@ -68,7 +68,7 @@ chrono = "0.4"
rusqlite = { version = "0.37", features = ["bundled"] }
tar = "0.4.44"
flate2 = "1.0"
transcribe-rs = { version = "0.2.3", features = ["whisper", "parakeet", "moonshine", "sense_voice"] }
transcribe-rs = { version = "0.2.5", features = ["whisper", "parakeet", "moonshine", "sense_voice"] }
handy-keys = "0.2.0"
ferrous-opencc = "0.2.3"
specta = "=2.0.0-rc.22"

View file

@ -21,6 +21,7 @@ pub enum EngineType {
Whisper,
Parakeet,
Moonshine,
MoonshineStreaming,
SenseVoice,
}
@ -290,6 +291,81 @@ impl ModelManager {
},
);
available_models.insert(
"moonshine-tiny-streaming-en".to_string(),
ModelInfo {
id: "moonshine-tiny-streaming-en".to_string(),
name: "Moonshine V2 Tiny".to_string(),
description: "Ultra-fast, English only".to_string(),
filename: "moonshine-tiny-streaming-en".to_string(),
url: Some(
"https://blob.handy.computer/moonshine-tiny-streaming-en.tar.gz".to_string(),
),
size_mb: 31,
is_downloaded: false,
is_downloading: false,
partial_size: 0,
is_directory: true,
engine_type: EngineType::MoonshineStreaming,
accuracy_score: 0.55,
speed_score: 0.95,
supports_translation: false,
is_recommended: false,
supported_languages: vec!["en".to_string()],
is_custom: false,
},
);
available_models.insert(
"moonshine-small-streaming-en".to_string(),
ModelInfo {
id: "moonshine-small-streaming-en".to_string(),
name: "Moonshine V2 Small".to_string(),
description: "Fast, English only. Good balance of speed and accuracy.".to_string(),
filename: "moonshine-small-streaming-en".to_string(),
url: Some(
"https://blob.handy.computer/moonshine-small-streaming-en.tar.gz".to_string(),
),
size_mb: 100,
is_downloaded: false,
is_downloading: false,
partial_size: 0,
is_directory: true,
engine_type: EngineType::MoonshineStreaming,
accuracy_score: 0.65,
speed_score: 0.90,
supports_translation: false,
is_recommended: false,
supported_languages: vec!["en".to_string()],
is_custom: false,
},
);
available_models.insert(
"moonshine-medium-streaming-en".to_string(),
ModelInfo {
id: "moonshine-medium-streaming-en".to_string(),
name: "Moonshine V2 Medium".to_string(),
description: "English only. High quality.".to_string(),
filename: "moonshine-medium-streaming-en".to_string(),
url: Some(
"https://blob.handy.computer/moonshine-medium-streaming-en.tar.gz".to_string(),
),
size_mb: 192,
is_downloaded: false,
is_downloading: false,
partial_size: 0,
is_directory: true,
engine_type: EngineType::MoonshineStreaming,
accuracy_score: 0.75,
speed_score: 0.80,
supports_translation: false,
is_recommended: false,
supported_languages: vec!["en".to_string()],
is_custom: false,
},
);
// SenseVoice supported languages
let sense_voice_languages: Vec<String> =
vec!["zh", "zh-Hans", "zh-Hant", "en", "yue", "ja", "ko"]

View file

@ -4,14 +4,18 @@ use crate::settings::{get_settings, ModelUnloadTimeout};
use anyhow::Result;
use log::{debug, error, info, warn};
use serde::Serialize;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Condvar, Mutex};
use std::sync::{Arc, Condvar, Mutex, MutexGuard};
use std::thread;
use std::time::{Duration, SystemTime};
use tauri::{AppHandle, Emitter};
use transcribe_rs::{
engines::{
moonshine::{ModelVariant, MoonshineEngine, MoonshineModelParams},
moonshine::{
ModelVariant, MoonshineEngine, MoonshineModelParams, MoonshineStreamingEngine,
StreamingModelParams,
},
parakeet::{
ParakeetEngine, ParakeetInferenceParams, ParakeetModelParams, TimestampGranularity,
},
@ -36,6 +40,7 @@ enum LoadedEngine {
Whisper(WhisperEngine),
Parakeet(ParakeetEngine),
Moonshine(MoonshineEngine),
MoonshineStreaming(MoonshineStreamingEngine),
SenseVoice(SenseVoiceEngine),
}
@ -134,8 +139,16 @@ impl TranscriptionManager {
Ok(manager)
}
/// Lock the engine mutex, recovering from poison if a previous transcription panicked.
fn lock_engine(&self) -> MutexGuard<'_, Option<LoadedEngine>> {
self.engine.lock().unwrap_or_else(|poisoned| {
warn!("Engine mutex was poisoned by a previous panic, recovering");
poisoned.into_inner()
})
}
pub fn is_model_loaded(&self) -> bool {
let engine = self.engine.lock().unwrap();
let engine = self.lock_engine();
engine.is_some()
}
@ -144,12 +157,13 @@ impl TranscriptionManager {
debug!("Starting to unload model");
{
let mut engine = self.engine.lock().unwrap();
let mut engine = self.lock_engine();
if let Some(ref mut loaded_engine) = *engine {
match loaded_engine {
LoadedEngine::Whisper(ref mut e) => e.unload_model(),
LoadedEngine::Parakeet(ref mut e) => e.unload_model(),
LoadedEngine::Moonshine(ref mut e) => e.unload_model(),
LoadedEngine::MoonshineStreaming(ref mut e) => e.unload_model(),
LoadedEngine::SenseVoice(ref mut e) => e.unload_model(),
}
}
@ -290,6 +304,28 @@ impl TranscriptionManager {
})?;
LoadedEngine::Moonshine(engine)
}
EngineType::MoonshineStreaming => {
let mut engine = MoonshineStreamingEngine::new();
engine
.load_model_with_params(&model_path, StreamingModelParams::default())
.map_err(|e| {
let error_msg = format!(
"Failed to load moonshine streaming model {}: {}",
model_id, e
);
let _ = self.app_handle.emit(
"model-state-changed",
ModelStateEvent {
event_type: "loading_failed".to_string(),
model_id: Some(model_id.to_string()),
model_name: Some(model_info.name.clone()),
error: Some(error_msg.clone()),
},
);
anyhow::anyhow!(error_msg)
})?;
LoadedEngine::MoonshineStreaming(engine)
}
EngineType::SenseVoice => {
let mut engine = SenseVoiceEngine::new();
engine
@ -314,7 +350,7 @@ impl TranscriptionManager {
// Update the current engine and model ID
{
let mut engine = self.engine.lock().unwrap();
let mut engine = self.lock_engine();
*engine = Some(loaded_engine);
}
{
@ -395,7 +431,7 @@ impl TranscriptionManager {
is_loading = self.loading_condvar.wait(is_loading).unwrap();
}
let engine_guard = self.engine.lock().unwrap();
let engine_guard = self.lock_engine();
if engine_guard.is_none() {
return Err(anyhow::anyhow!("Model is not loaded for transcription."));
}
@ -404,70 +440,141 @@ impl TranscriptionManager {
// Get current settings for configuration
let settings = get_settings(&self.app_handle);
// Perform transcription with the appropriate engine
// Perform transcription with the appropriate engine.
// We use catch_unwind to prevent engine panics from poisoning the mutex,
// which would make the app hang indefinitely on subsequent operations.
let result = {
let mut engine_guard = self.engine.lock().unwrap();
let engine = engine_guard.as_mut().ok_or_else(|| {
anyhow::anyhow!(
"Model failed to load after auto-load attempt. Please check your model settings."
)
})?;
let mut engine_guard = self.lock_engine();
match engine {
LoadedEngine::Whisper(whisper_engine) => {
// Normalize language code for Whisper
// Convert zh-Hans and zh-Hant to zh since Whisper uses ISO 639-1 codes
let whisper_language = if settings.selected_language == "auto" {
None
// Take the engine out so we own it during transcription.
// If the engine panics, we simply don't put it back (effectively unloading it)
// instead of poisoning the mutex.
let mut engine = match engine_guard.take() {
Some(e) => e,
None => {
return Err(anyhow::anyhow!(
"Model failed to load after auto-load attempt. Please check your model settings."
));
}
};
// Release the lock before transcribing — no mutex held during the engine call
drop(engine_guard);
let transcribe_result = catch_unwind(AssertUnwindSafe(
|| -> Result<transcribe_rs::TranscriptionResult> {
match &mut engine {
LoadedEngine::Whisper(whisper_engine) => {
let whisper_language = if settings.selected_language == "auto" {
None
} else {
let normalized = if settings.selected_language == "zh-Hans"
|| settings.selected_language == "zh-Hant"
{
"zh".to_string()
} else {
settings.selected_language.clone()
};
Some(normalized)
};
let params = WhisperInferenceParams {
language: whisper_language,
translate: settings.translate_to_english,
..Default::default()
};
whisper_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| anyhow::anyhow!("Whisper transcription failed: {}", e))
}
LoadedEngine::Parakeet(parakeet_engine) => {
let params = ParakeetInferenceParams {
timestamp_granularity: TimestampGranularity::Segment,
..Default::default()
};
parakeet_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| {
anyhow::anyhow!("Parakeet transcription failed: {}", e)
})
}
LoadedEngine::Moonshine(moonshine_engine) => moonshine_engine
.transcribe_samples(audio, None)
.map_err(|e| anyhow::anyhow!("Moonshine transcription failed: {}", e)),
LoadedEngine::MoonshineStreaming(streaming_engine) => streaming_engine
.transcribe_samples(audio, None)
.map_err(|e| {
anyhow::anyhow!("Moonshine streaming transcription failed: {}", e)
}),
LoadedEngine::SenseVoice(sense_voice_engine) => {
let language = match settings.selected_language.as_str() {
"zh" | "zh-Hans" | "zh-Hant" => SenseVoiceLanguage::Chinese,
"en" => SenseVoiceLanguage::English,
"ja" => SenseVoiceLanguage::Japanese,
"ko" => SenseVoiceLanguage::Korean,
"yue" => SenseVoiceLanguage::Cantonese,
_ => SenseVoiceLanguage::Auto,
};
let params = SenseVoiceInferenceParams {
language,
use_itn: true,
};
sense_voice_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| {
anyhow::anyhow!("SenseVoice transcription failed: {}", e)
})
}
}
},
));
match transcribe_result {
Ok(inner_result) => {
// Success or normal error — put the engine back
let mut engine_guard = self.lock_engine();
*engine_guard = Some(engine);
inner_result?
}
Err(panic_payload) => {
// Engine panicked — do NOT put it back (it's in an unknown state).
// The engine is dropped here, effectively unloading it.
let panic_msg = if let Some(s) = panic_payload.downcast_ref::<&str>() {
s.to_string()
} else if let Some(s) = panic_payload.downcast_ref::<String>() {
s.clone()
} else {
let normalized = if settings.selected_language == "zh-Hans"
|| settings.selected_language == "zh-Hant"
{
"zh".to_string()
} else {
settings.selected_language.clone()
};
Some(normalized)
"unknown panic".to_string()
};
error!(
"Transcription engine panicked: {}. Model has been unloaded.",
panic_msg
);
let params = WhisperInferenceParams {
language: whisper_language,
translate: settings.translate_to_english,
..Default::default()
};
// Clear the model ID so it will be reloaded on next attempt
{
let mut current_model = self
.current_model_id
.lock()
.unwrap_or_else(|e| e.into_inner());
*current_model = None;
}
whisper_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| anyhow::anyhow!("Whisper transcription failed: {}", e))?
}
LoadedEngine::Parakeet(parakeet_engine) => {
let params = ParakeetInferenceParams {
timestamp_granularity: TimestampGranularity::Segment,
..Default::default()
};
parakeet_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| anyhow::anyhow!("Parakeet transcription failed: {}", e))?
}
LoadedEngine::Moonshine(moonshine_engine) => moonshine_engine
.transcribe_samples(audio, None)
.map_err(|e| anyhow::anyhow!("Moonshine transcription failed: {}", e))?,
LoadedEngine::SenseVoice(sense_voice_engine) => {
let language = match settings.selected_language.as_str() {
"zh" | "zh-Hans" | "zh-Hant" => SenseVoiceLanguage::Chinese,
"en" => SenseVoiceLanguage::English,
"ja" => SenseVoiceLanguage::Japanese,
"ko" => SenseVoiceLanguage::Korean,
"yue" => SenseVoiceLanguage::Cantonese,
_ => SenseVoiceLanguage::Auto,
};
let params = SenseVoiceInferenceParams {
language,
use_itn: true,
};
sense_voice_engine
.transcribe_samples(audio, Some(params))
.map_err(|e| anyhow::anyhow!("SenseVoice transcription failed: {}", e))?
let _ = self.app_handle.emit(
"model-state-changed",
ModelStateEvent {
event_type: "unloaded".to_string(),
model_id: None,
model_name: None,
error: Some(format!("Engine panicked: {}", panic_msg)),
},
);
return Err(anyhow::anyhow!(
"Transcription engine panicked: {}. The model has been unloaded and will reload on next attempt.",
panic_msg
));
}
}
};

View file

@ -736,7 +736,7 @@ export type AutoSubmitKey = "enter" | "ctrl_enter" | "cmd_enter"
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" | "SenseVoice"
export type EngineType = "Whisper" | "Parakeet" | "Moonshine" | "MoonshineStreaming" | "SenseVoice"
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 }
/**
* Result of changing keyboard implementation

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": ".سريع جداً، الإنجليزية فقط. يتعامل جيداً مع اللهجات"
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "سريع للغاية، الإنجليزية فقط"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "سريع، الإنجليزية فقط. توازن جيد بين السرعة والدقة."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "الإنجليزية فقط. جودة عالية."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "محسّن للماندرين التايوانية. دعم التبديل بين اللغات."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "سريع جداً. الصينية، الإنجليزية، اليابانية، الكورية، الكانتونية."
}
},
"errors": {

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": "Velmi rychlý, pouze angličtina. Dobře zvládá přízvuky."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultrarychlý, pouze angličtina"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Rychlý, pouze angličtina. Dobrý poměr rychlosti a přesnosti."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Pouze angličtina. Vysoká kvalita."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Optimalizováno pro tchajwanskou mandarínštinu. Podpora přepínání jazyků."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Velmi rychlý. Čínština, angličtina, japonština, korejština, kantonština."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Sehr schnell, nur Englisch. Verarbeitet Akzente gut."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultraschnell, nur Englisch"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Schnell, nur Englisch. Gute Balance zwischen Geschwindigkeit und Genauigkeit."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Nur Englisch. Hohe Qualität."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Optimiert für taiwanesisches Mandarin. Unterstützung für Code-Switching."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Sehr schnell. Chinesisch, Englisch, Japanisch, Koreanisch, Kantonesisch."
}
},
"errors": {

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultra-fast, English only"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Fast, English only. Good balance of speed and accuracy."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "English only. High quality."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Optimized for Taiwanese Mandarin. Code-switching support."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Very fast. Chinese, English, Japanese, Korean, Cantonese."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Muy rápido, solo inglés. Maneja bien los acentos."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultrarrápido, solo inglés"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Rápido, solo inglés. Buen equilibrio entre velocidad y precisión."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Solo inglés. Alta calidad."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Optimizado para mandarín taiwanés. Soporte para cambio de código."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Muy rápido. Chino, inglés, japonés, coreano, cantonés."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Très rapide, anglais uniquement. Gère bien les accents."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultra-rapide, anglais uniquement"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Rapide, anglais uniquement. Bon équilibre entre vitesse et précision."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Anglais uniquement. Haute qualité."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Optimisé pour le mandarin taïwanais. Prise en charge de l'alternance codique."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Très rapide. Chinois, anglais, japonais, coréen, cantonais."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Molto veloce, solo inglese. Gestisce bene gli accenti."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultra-veloce, solo inglese"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Veloce, solo inglese. Buon equilibrio tra velocità e precisione."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Solo inglese. Alta qualità."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Ottimizzato per il mandarino taiwanese. Supporto per il code-switching."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Molto veloce. Cinese, inglese, giapponese, coreano, cantonese."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "非常に高速、英語のみ。アクセントにも対応。"
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "超高速、英語のみ"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "高速、英語のみ。速度と精度のバランスが良い。"
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "英語のみ。高品質。"
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "台湾華語に最適化。コードスイッチングに対応。"
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "非常に高速。中国語、英語、日本語、韓国語、広東語。"
}
},
"errors": {

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": "매우 빠름, 영어 전용. 억양을 잘 처리합니다."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "초고속, 영어 전용"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "빠름, 영어 전용. 속도와 정확도의 균형이 좋음."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "영어 전용. 높은 품질."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "대만 만다린에 최적화. 코드 스위칭 지원."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "매우 빠름. 중국어, 영어, 일본어, 한국어, 광둥어."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Bardzo szybki, tylko angielski. Dobrze radzi sobie z akcentami."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultraszybki, tylko angielski"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Szybki, tylko angielski. Dobra równowaga między szybkością a dokładnością."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Tylko angielski. Wysoka jakość."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Zoptymalizowany dla tajwańskiego mandaryńskiego. Obsługa przełączania języków."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Bardzo szybki. Chiński, angielski, japoński, koreański, kantoński."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Muito rápido, apenas inglês. Lida bem com sotaques."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultrarrápido, apenas inglês"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Rápido, apenas inglês. Bom equilíbrio entre velocidade e precisão."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Apenas inglês. Alta qualidade."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Otimizado para mandarim taiwanês. Suporte para alternância de código."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Muito rápido. Chinês, inglês, japonês, coreano, cantonês."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Очень быстрый, только английский. Хорошо справляется с акцентами."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Сверхбыстрый, только английский"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Быстрый, только английский. Хороший баланс скорости и точности."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Только английский. Высокое качество."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Оптимизирован для тайваньского мандаринского. Поддержка переключения языков."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Очень быстрый. Китайский, английский, японский, корейский, кантонский."
}
},
"errors": {

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": "Çok hızlı, yalnızca İngilizce. Aksanları iyi işler."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Ultra hızlı, yalnızca İngilizce"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Hızlı, yalnızca İngilizce. Hız ve doğruluk arasında iyi denge."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Yalnızca İngilizce. Yüksek kalite."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Tayvan Mandarin Çincesi için optimize edilmiş. Dil değiştirme desteği."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Çok hızlı. Çince, İngilizce, Japonca, Korece, Kantonca."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Дуже швидкий, лише англійська. Добре справляється з акцентами."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Надшвидкий, лише англійська"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Швидкий, лише англійська. Добрий баланс швидкості та точності."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Лише англійська. Висока якість."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Оптимізовано для тайванської мандаринської. Підтримка перемикання мов."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Дуже швидкий. Китайська, англійська, японська, корейська, кантонська."
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "Rất nhanh, chỉ tiếng Anh. Xử lý tốt các giọng nói."
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "Cực nhanh, chỉ tiếng Anh"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "Nhanh, chỉ tiếng Anh. Cân bằng tốt giữa tốc độ và độ chính xác."
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "Chỉ tiếng Anh. Chất lượng cao."
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "Tối ưu hóa cho tiếng Quan Thoại Đài Loan. Hỗ trợ chuyển đổi ngôn ngữ."
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "Rất nhanh. Tiếng Trung, tiếng Anh, tiếng Nhật, tiếng Hàn, tiếng Quảng Đông."
}
},
"errors": {

View file

@ -55,6 +55,26 @@
"moonshine-base": {
"name": "Moonshine Base",
"description": "速度極快,僅支援英語,擅長處理各種口音"
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "超快速,僅支援英語"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "快速,僅支援英語。速度與準確度的良好平衡。"
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "僅支援英語。高品質。"
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "針對臺灣華語最佳化。支援語碼轉換。"
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "速度極快。支援中文、英語、日語、韓語、粵語。"
}
},
"errors": {

View file

@ -54,7 +54,27 @@
},
"moonshine-base": {
"name": "Moonshine Base",
"description": "Very fast, English only. Handles accents well."
"description": "非常快速,仅支持英语。口音处理良好。"
},
"moonshine-tiny-streaming-en": {
"name": "Moonshine V2 Tiny",
"description": "超快速,仅支持英语"
},
"moonshine-small-streaming-en": {
"name": "Moonshine V2 Small",
"description": "快速,仅支持英语。速度与准确度的良好平衡。"
},
"moonshine-medium-streaming-en": {
"name": "Moonshine V2 Medium",
"description": "仅支持英语。高质量。"
},
"breeze-asr": {
"name": "Breeze ASR",
"description": "针对台湾国语优化。支持语码转换。"
},
"sense-voice-int8": {
"name": "SenseVoice",
"description": "非常快速。支持中文、英语、日语、韩语、粤语。"
}
},
"errors": {