fix: keep Windows microphone guidance Windows-only (#1032)
* fix windows-only mic permission guidance * don't hardcode error strings in rust * format --------- Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
2a528d8d10
commit
a6e8fc8651
23 changed files with 186 additions and 14 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
||||
use crate::apple_intelligence;
|
||||
use crate::audio_feedback::{play_feedback_sound, play_feedback_sound_blocking, SoundType};
|
||||
use crate::audio_toolkit::is_microphone_access_denied;
|
||||
use crate::managers::audio::AudioRecordingManager;
|
||||
use crate::managers::history::HistoryManager;
|
||||
use crate::managers::transcription::TranscriptionManager;
|
||||
|
|
@ -20,6 +21,12 @@ use std::time::Instant;
|
|||
use tauri::Manager;
|
||||
use tauri::{AppHandle, Emitter};
|
||||
|
||||
#[derive(Clone, serde::Serialize)]
|
||||
struct RecordingErrorEvent {
|
||||
error_type: String,
|
||||
detail: Option<String>,
|
||||
}
|
||||
|
||||
/// Drop guard that notifies the [`TranscriptionCoordinator`] when the
|
||||
/// transcription pipeline finishes — whether it completes normally or panics.
|
||||
struct FinishGuard(AppHandle);
|
||||
|
|
@ -381,7 +388,18 @@ impl ShortcutAction for TranscribeAction {
|
|||
utils::hide_recording_overlay(app);
|
||||
change_tray_icon(app, TrayIconState::Idle);
|
||||
if let Some(err) = recording_error {
|
||||
let _ = app.emit("recording-error", err);
|
||||
let error_type = if is_microphone_access_denied(&err) {
|
||||
"microphone_permission_denied"
|
||||
} else {
|
||||
"unknown"
|
||||
};
|
||||
let _ = app.emit(
|
||||
"recording-error",
|
||||
RecordingErrorEvent {
|
||||
error_type: error_type.to_string(),
|
||||
detail: Some(err),
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ mod utils;
|
|||
mod visualizer;
|
||||
|
||||
pub use device::{list_input_devices, list_output_devices, CpalDeviceInfo};
|
||||
pub use recorder::AudioRecorder;
|
||||
pub use recorder::{is_microphone_access_denied, AudioRecorder};
|
||||
pub use resampler::FrameResampler;
|
||||
pub use utils::save_wav_file;
|
||||
pub use visualizer::AudioVisualiser;
|
||||
|
|
|
|||
|
|
@ -148,9 +148,8 @@ impl AudioRecorder {
|
|||
drop(stream);
|
||||
}
|
||||
Err(error_message) => {
|
||||
let normalized_error = normalize_microphone_error(error_message);
|
||||
log::error!("{normalized_error}");
|
||||
let _ = init_tx.send(Err(normalized_error));
|
||||
log::error!("{error_message}");
|
||||
let _ = init_tx.send(Err(error_message));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -292,19 +291,36 @@ impl AudioRecorder {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_microphone_access_denied(error_message: &str) -> bool {
|
||||
pub fn is_microphone_access_denied(error_message: &str) -> bool {
|
||||
let normalized = error_message.to_lowercase();
|
||||
normalized.contains("access is denied")
|
||||
|| normalized.contains("permission denied")
|
||||
|| normalized.contains("0x80070005")
|
||||
}
|
||||
|
||||
fn normalize_microphone_error(error_message: String) -> String {
|
||||
if is_microphone_access_denied(&error_message) {
|
||||
return "Microphone access was denied by the operating system. On Windows, enable Settings → Privacy & security → Microphone (including desktop app access), then restart Handy.".to_string();
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::is_microphone_access_denied;
|
||||
|
||||
#[test]
|
||||
fn detects_access_is_denied() {
|
||||
assert!(is_microphone_access_denied("Access is denied"));
|
||||
}
|
||||
|
||||
error_message
|
||||
#[test]
|
||||
fn detects_permission_denied() {
|
||||
assert!(is_microphone_access_denied("permission denied"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detects_windows_error_code() {
|
||||
assert!(is_microphone_access_denied("WASAPI error: 0x80070005"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_not_match_unrelated_errors() {
|
||||
assert!(!is_microphone_access_denied("device not found"));
|
||||
}
|
||||
}
|
||||
|
||||
fn run_consumer(
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ pub mod utils;
|
|||
pub mod vad;
|
||||
|
||||
pub use audio::{
|
||||
list_input_devices, list_output_devices, save_wav_file, AudioRecorder, CpalDeviceInfo,
|
||||
is_microphone_access_denied, list_input_devices, list_output_devices, save_wav_file,
|
||||
AudioRecorder, CpalDeviceInfo,
|
||||
};
|
||||
pub use text::{apply_custom_words, filter_transcription_output};
|
||||
pub use utils::get_cpal_host;
|
||||
|
|
|
|||
19
src/App.tsx
19
src/App.tsx
|
|
@ -7,7 +7,7 @@ import {
|
|||
checkAccessibilityPermission,
|
||||
checkMicrophonePermission,
|
||||
} from "tauri-plugin-macos-permissions-api";
|
||||
import { ModelStateEvent } from "./lib/types/events";
|
||||
import { ModelStateEvent, RecordingErrorEvent } from "./lib/types/events";
|
||||
import "./App.css";
|
||||
import AccessibilityPermissions from "./components/AccessibilityPermissions";
|
||||
import Footer from "./components/footer";
|
||||
|
|
@ -97,8 +97,21 @@ function App() {
|
|||
|
||||
// Listen for recording errors from the backend and show a toast
|
||||
useEffect(() => {
|
||||
const unlisten = listen<string>("recording-error", (event) => {
|
||||
toast.error(t("errors.recordingFailed", { error: event.payload }));
|
||||
const unlisten = listen<RecordingErrorEvent>("recording-error", (event) => {
|
||||
const { error_type, detail } = event.payload;
|
||||
|
||||
if (error_type === "microphone_permission_denied") {
|
||||
const currentPlatform = platform();
|
||||
const platformKey = `errors.micPermissionDenied.${currentPlatform}`;
|
||||
const description = t(platformKey, {
|
||||
defaultValue: t("errors.micPermissionDenied.generic"),
|
||||
});
|
||||
toast.error(t("errors.micPermissionDeniedTitle"), { description });
|
||||
} else {
|
||||
toast.error(
|
||||
t("errors.recordingFailed", { error: detail ?? "Unknown error" }),
|
||||
);
|
||||
}
|
||||
});
|
||||
return () => {
|
||||
unlisten.then((fn) => fn());
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "خطأ في تحميل المجلد: {{error}}",
|
||||
"micPermissionDeniedTitle": "تم رفض الوصول إلى الميكروفون",
|
||||
"micPermissionDenied": {
|
||||
"generic": "تم رفض الوصول إلى الميكروفون من قبل نظام التشغيل. يرجى منح إذن الميكروفون في إعدادات النظام.",
|
||||
"windows": "قم بتمكين الوصول إلى الميكروفون في الإعدادات ← الخصوصية والأمان ← الميكروفون (بما في ذلك وصول تطبيقات سطح المكتب).",
|
||||
"macos": "امنح الوصول إلى الميكروفون في إعدادات النظام ← الخصوصية والأمان ← الميكروفون.",
|
||||
"linux": "امنح الوصول إلى الميكروفون في إعدادات الصوت أو الخصوصية في نظامك."
|
||||
},
|
||||
"recordingFailed": "فشل في بدء التسجيل: {{error}}",
|
||||
"modelLoadFailed": "فشل في تحميل النموذج: {{model}}",
|
||||
"modelLoadFailedUnknown": "نموذج غير معروف"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Chyba při načítání adresáře: {{error}}",
|
||||
"micPermissionDeniedTitle": "Přístup k mikrofonu byl odepřen",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Přístup k mikrofonu byl odepřen operačním systémem. Povolte prosím přístup k mikrofonu v nastavení systému.",
|
||||
"windows": "Povolte přístup k mikrofonu v Nastavení → Soukromí a zabezpečení → Mikrofon (včetně přístupu desktopových aplikací).",
|
||||
"macos": "Povolte přístup k mikrofonu v Nastavení systému → Soukromí a zabezpečení → Mikrofon.",
|
||||
"linux": "Povolte přístup k mikrofonu v nastavení zvuku nebo soukromí vašeho systému."
|
||||
},
|
||||
"recordingFailed": "Nepodařilo se spustit nahrávání: {{error}}",
|
||||
"modelLoadFailed": "Nepodařilo se načíst model: {{model}}",
|
||||
"modelLoadFailedUnknown": "neznámý model"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Fehler beim Laden des Verzeichnisses: {{error}}",
|
||||
"micPermissionDeniedTitle": "Mikrofonzugriff verweigert",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Der Mikrofonzugriff wurde vom Betriebssystem verweigert. Bitte erteilen Sie die Mikrofonberechtigung in Ihren Systemeinstellungen.",
|
||||
"windows": "Aktivieren Sie den Mikrofonzugriff unter Einstellungen → Datenschutz und Sicherheit → Mikrofon (einschließlich Desktop-App-Zugriff).",
|
||||
"macos": "Erteilen Sie den Mikrofonzugriff in Systemeinstellungen → Datenschutz & Sicherheit → Mikrofon.",
|
||||
"linux": "Erteilen Sie den Mikrofonzugriff in den Sound- oder Datenschutzeinstellungen Ihres Systems."
|
||||
},
|
||||
"recordingFailed": "Aufnahme konnte nicht gestartet werden: {{error}}",
|
||||
"modelLoadFailed": "Modell konnte nicht geladen werden: {{model}}",
|
||||
"modelLoadFailedUnknown": "unbekanntes Modell"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Error loading directory: {{error}}",
|
||||
"micPermissionDeniedTitle": "Microphone Access Denied",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Microphone access was denied by the operating system. Please grant microphone permission in your system settings.",
|
||||
"windows": "Enable microphone access in Settings → Privacy & security → Microphone (including desktop app access).",
|
||||
"macos": "Grant microphone access in System Settings → Privacy & Security → Microphone.",
|
||||
"linux": "Grant microphone access in your system's sound or privacy settings."
|
||||
},
|
||||
"recordingFailed": "Failed to start recording: {{error}}",
|
||||
"modelLoadFailed": "Failed to load model: {{model}}",
|
||||
"modelLoadFailedUnknown": "unknown model"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Error al cargar el directorio: {{error}}",
|
||||
"micPermissionDeniedTitle": "Acceso al micrófono denegado",
|
||||
"micPermissionDenied": {
|
||||
"generic": "El sistema operativo denegó el acceso al micrófono. Por favor, conceda el permiso del micrófono en la configuración del sistema.",
|
||||
"windows": "Active el acceso al micrófono en Configuración → Privacidad y seguridad → Micrófono (incluido el acceso de aplicaciones de escritorio).",
|
||||
"macos": "Conceda el acceso al micrófono en Ajustes del Sistema → Privacidad y seguridad → Micrófono.",
|
||||
"linux": "Conceda el acceso al micrófono en la configuración de sonido o privacidad de su sistema."
|
||||
},
|
||||
"recordingFailed": "Error al iniciar la grabación: {{error}}",
|
||||
"modelLoadFailed": "Error al cargar el modelo: {{model}}",
|
||||
"modelLoadFailedUnknown": "modelo desconocido"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Erreur lors du chargement du répertoire : {{error}}",
|
||||
"micPermissionDeniedTitle": "Accès au microphone refusé",
|
||||
"micPermissionDenied": {
|
||||
"generic": "L'accès au microphone a été refusé par le système d'exploitation. Veuillez accorder l'autorisation du microphone dans les paramètres système.",
|
||||
"windows": "Activez l'accès au microphone dans Paramètres → Confidentialité et sécurité → Microphone (y compris l'accès des applications de bureau).",
|
||||
"macos": "Accordez l'accès au microphone dans Réglages du système → Confidentialité et sécurité → Microphone.",
|
||||
"linux": "Accordez l'accès au microphone dans les paramètres de son ou de confidentialité de votre système."
|
||||
},
|
||||
"recordingFailed": "Échec du démarrage de l'enregistrement : {{error}}",
|
||||
"modelLoadFailed": "Échec du chargement du modèle : {{model}}",
|
||||
"modelLoadFailedUnknown": "modèle inconnu"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Errore di caricamento cartella: {{error}}",
|
||||
"micPermissionDeniedTitle": "Accesso al microfono negato",
|
||||
"micPermissionDenied": {
|
||||
"generic": "L'accesso al microfono è stato negato dal sistema operativo. Concedi l'autorizzazione al microfono nelle impostazioni di sistema.",
|
||||
"windows": "Abilita l'accesso al microfono in Impostazioni → Privacy e sicurezza → Microfono (incluso l'accesso delle app desktop).",
|
||||
"macos": "Concedi l'accesso al microfono in Impostazioni di Sistema → Privacy e sicurezza → Microfono.",
|
||||
"linux": "Concedi l'accesso al microfono nelle impostazioni audio o sulla privacy del tuo sistema."
|
||||
},
|
||||
"recordingFailed": "Impossibile avviare la registrazione: {{error}}",
|
||||
"modelLoadFailed": "Impossibile caricare il modello: {{model}}",
|
||||
"modelLoadFailedUnknown": "modello sconosciuto"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "ディレクトリの読み込みエラー: {{error}}",
|
||||
"micPermissionDeniedTitle": "マイクへのアクセスが拒否されました",
|
||||
"micPermissionDenied": {
|
||||
"generic": "オペレーティングシステムによりマイクへのアクセスが拒否されました。システム設定でマイクの許可を付与してください。",
|
||||
"windows": "設定 → プライバシーとセキュリティ → マイク(デスクトップアプリのアクセスを含む)でマイクへのアクセスを有効にしてください。",
|
||||
"macos": "システム設定 → プライバシーとセキュリティ → マイクでマイクへのアクセスを許可してください。",
|
||||
"linux": "システムのサウンドまたはプライバシー設定でマイクへのアクセスを許可してください。"
|
||||
},
|
||||
"recordingFailed": "録音の開始に失敗しました: {{error}}",
|
||||
"modelLoadFailed": "モデルの読み込みに失敗しました: {{model}}",
|
||||
"modelLoadFailedUnknown": "不明なモデル"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "디렉토리 로딩 오류: {{error}}",
|
||||
"micPermissionDeniedTitle": "마이크 접근이 거부되었습니다",
|
||||
"micPermissionDenied": {
|
||||
"generic": "운영 체제에서 마이크 접근을 거부했습니다. 시스템 설정에서 마이크 권한을 허용해 주세요.",
|
||||
"windows": "설정 → 개인 정보 및 보안 → 마이크(데스크톱 앱 접근 포함)에서 마이크 접근을 활성화하세요.",
|
||||
"macos": "시스템 설정 → 개인 정보 보호 및 보안 → 마이크에서 마이크 접근을 허용하세요.",
|
||||
"linux": "시스템의 소리 또는 개인 정보 설정에서 마이크 접근을 허용하세요."
|
||||
},
|
||||
"recordingFailed": "녹음을 시작하지 못했습니다: {{error}}",
|
||||
"modelLoadFailed": "모델을 불러오지 못했습니다: {{model}}",
|
||||
"modelLoadFailedUnknown": "알 수 없는 모델"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Błąd wczytywania katalogu: {{error}}",
|
||||
"micPermissionDeniedTitle": "Odmowa dostępu do mikrofonu",
|
||||
"micPermissionDenied": {
|
||||
"generic": "System operacyjny odmówił dostępu do mikrofonu. Przyznaj uprawnienia do mikrofonu w ustawieniach systemowych.",
|
||||
"windows": "Włącz dostęp do mikrofonu w Ustawienia → Prywatność i zabezpieczenia → Mikrofon (w tym dostęp aplikacji klasycznych).",
|
||||
"macos": "Przyznaj dostęp do mikrofonu w Ustawienia systemowe → Prywatność i ochrona → Mikrofon.",
|
||||
"linux": "Przyznaj dostęp do mikrofonu w ustawieniach dźwięku lub prywatności systemu."
|
||||
},
|
||||
"recordingFailed": "Nie udało się rozpocząć nagrywania: {{error}}",
|
||||
"modelLoadFailed": "Nie udało się załadować modelu: {{model}}",
|
||||
"modelLoadFailedUnknown": "nieznany model"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Erro ao carregar diretório: {{error}}",
|
||||
"micPermissionDeniedTitle": "Acesso ao microfone negado",
|
||||
"micPermissionDenied": {
|
||||
"generic": "O acesso ao microfone foi negado pelo sistema operacional. Conceda a permissão do microfone nas configurações do sistema.",
|
||||
"windows": "Ative o acesso ao microfone em Configurações → Privacidade e segurança → Microfone (incluindo acesso de aplicativos da área de trabalho).",
|
||||
"macos": "Conceda o acesso ao microfone em Ajustes do Sistema → Privacidade e Segurança → Microfone.",
|
||||
"linux": "Conceda o acesso ao microfone nas configurações de som ou privacidade do seu sistema."
|
||||
},
|
||||
"recordingFailed": "Falha ao iniciar a gravação: {{error}}",
|
||||
"modelLoadFailed": "Falha ao carregar o modelo: {{model}}",
|
||||
"modelLoadFailedUnknown": "modelo desconhecido"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Ошибка загрузки каталога: {{error}}.",
|
||||
"micPermissionDeniedTitle": "Доступ к микрофону запрещён",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Доступ к микрофону был запрещён операционной системой. Предоставьте разрешение на использование микрофона в настройках системы.",
|
||||
"windows": "Включите доступ к микрофону в Параметры → Конфиденциальность и безопасность → Микрофон (включая доступ классических приложений).",
|
||||
"macos": "Предоставьте доступ к микрофону в Системные настройки → Конфиденциальность и безопасность → Микрофон.",
|
||||
"linux": "Предоставьте доступ к микрофону в настройках звука или конфиденциальности вашей системы."
|
||||
},
|
||||
"recordingFailed": "Не удалось начать запись: {{error}}",
|
||||
"modelLoadFailed": "Не удалось загрузить модель: {{model}}",
|
||||
"modelLoadFailedUnknown": "неизвестная модель"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Dizin yüklenirken hata oluştu: {{error}}",
|
||||
"micPermissionDeniedTitle": "Mikrofon erişimi reddedildi",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Mikrofon erişimi işletim sistemi tarafından reddedildi. Lütfen sistem ayarlarından mikrofon iznini verin.",
|
||||
"windows": "Ayarlar → Gizlilik ve güvenlik → Mikrofon (masaüstü uygulama erişimi dahil) bölümünden mikrofon erişimini etkinleştirin.",
|
||||
"macos": "Sistem Ayarları → Gizlilik ve Güvenlik → Mikrofon bölümünden mikrofon erişimini verin.",
|
||||
"linux": "Sisteminizin ses veya gizlilik ayarlarından mikrofon erişimini verin."
|
||||
},
|
||||
"recordingFailed": "Kayıt başlatılamadı: {{error}}",
|
||||
"modelLoadFailed": "Model yüklenemedi: {{model}}",
|
||||
"modelLoadFailedUnknown": "bilinmeyen model"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Помилка завантаження папки: {{error}}",
|
||||
"micPermissionDeniedTitle": "Доступ до мікрофона заборонено",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Доступ до мікрофона було заборонено операційною системою. Надайте дозвіл на використання мікрофона в налаштуваннях системи.",
|
||||
"windows": "Увімкніть доступ до мікрофона в Параметри → Конфіденційність і безпека → Мікрофон (включно з доступом класичних програм).",
|
||||
"macos": "Надайте доступ до мікрофона в Системні налаштування → Конфіденційність і безпека → Мікрофон.",
|
||||
"linux": "Надайте доступ до мікрофона в налаштуваннях звуку або конфіденційності вашої системи."
|
||||
},
|
||||
"recordingFailed": "Не вдалося розпочати запис: {{error}}",
|
||||
"modelLoadFailed": "Не вдалося завантажити модель: {{model}}",
|
||||
"modelLoadFailedUnknown": "невідома модель"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "Lỗi khi tải thư mục: {{error}}",
|
||||
"micPermissionDeniedTitle": "Quyền truy cập micrô bị từ chối",
|
||||
"micPermissionDenied": {
|
||||
"generic": "Quyền truy cập micrô đã bị hệ điều hành từ chối. Vui lòng cấp quyền micrô trong cài đặt hệ thống.",
|
||||
"windows": "Bật quyền truy cập micrô trong Cài đặt → Quyền riêng tư & bảo mật → Micrô (bao gồm quyền truy cập ứng dụng máy tính).",
|
||||
"macos": "Cấp quyền truy cập micrô trong Cài đặt hệ thống → Quyền riêng tư & Bảo mật → Micrô.",
|
||||
"linux": "Cấp quyền truy cập micrô trong cài đặt âm thanh hoặc quyền riêng tư của hệ thống."
|
||||
},
|
||||
"recordingFailed": "Không thể bắt đầu ghi âm: {{error}}",
|
||||
"modelLoadFailed": "Không thể tải mô hình: {{model}}",
|
||||
"modelLoadFailedUnknown": "mô hình không xác định"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "載入目錄時發生錯誤: {{error}}",
|
||||
"micPermissionDeniedTitle": "麥克風存取被拒絕",
|
||||
"micPermissionDenied": {
|
||||
"generic": "作業系統拒絕了麥克風存取。請在系統設定中授予麥克風權限。",
|
||||
"windows": "在設定 → 隱私與安全性 → 麥克風(包括桌面應用程式存取)中啟用麥克風存取。",
|
||||
"macos": "在系統設定 → 隱私與安全性 → 麥克風中授予麥克風存取權限。",
|
||||
"linux": "在系統的聲音或隱私設定中授予麥克風存取權限。"
|
||||
},
|
||||
"recordingFailed": "錄音啟動失敗: {{error}}",
|
||||
"modelLoadFailed": "載入模型失敗: {{model}}",
|
||||
"modelLoadFailedUnknown": "未知模型"
|
||||
|
|
|
|||
|
|
@ -542,6 +542,13 @@
|
|||
},
|
||||
"errors": {
|
||||
"loadDirectory": "加载目录时出错: {{error}}",
|
||||
"micPermissionDeniedTitle": "麦克风访问被拒绝",
|
||||
"micPermissionDenied": {
|
||||
"generic": "操作系统拒绝了麦克风访问。请在系统设置中授予麦克风权限。",
|
||||
"windows": "在设置 → 隐私和安全性 → 麦克风(包括桌面应用访问)中启用麦克风访问。",
|
||||
"macos": "在系统设置 → 隐私与安全性 → 麦克风中授予麦克风访问权限。",
|
||||
"linux": "在系统的声音或隐私设置中授予麦克风访问权限。"
|
||||
},
|
||||
"recordingFailed": "录音启动失败: {{error}}",
|
||||
"modelLoadFailed": "加载模型失败: {{model}}",
|
||||
"modelLoadFailedUnknown": "未知模型"
|
||||
|
|
|
|||
|
|
@ -4,3 +4,8 @@ export interface ModelStateEvent {
|
|||
model_name?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface RecordingErrorEvent {
|
||||
error_type: string;
|
||||
detail?: string;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue