add extra recording buffer (#1089)
* add extra recording buffer * translations
This commit is contained in:
parent
012e066697
commit
5a3e6e33d1
26 changed files with 142 additions and 3 deletions
|
|
@ -335,6 +335,7 @@ pub fn run(cli_args: CliArgs) {
|
|||
shortcut::change_overlay_position_setting,
|
||||
shortcut::change_debug_mode_setting,
|
||||
shortcut::change_word_correction_threshold_setting,
|
||||
shortcut::change_extra_recording_buffer_setting,
|
||||
shortcut::change_paste_method_setting,
|
||||
shortcut::get_available_typing_tools,
|
||||
shortcut::change_typing_tool_setting,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::settings::{get_settings, AppSettings};
|
|||
use crate::utils;
|
||||
use log::{debug, error, info};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::time::Instant;
|
||||
use std::time::{Duration, Instant};
|
||||
use tauri::Manager;
|
||||
|
||||
fn set_mute(mute: bool) {
|
||||
|
|
@ -380,6 +380,16 @@ impl AudioRecordingManager {
|
|||
*state = RecordingState::Idle;
|
||||
drop(state);
|
||||
|
||||
// Optionally keep recording for a bit longer to capture trailing audio
|
||||
let settings = get_settings(&self.app_handle);
|
||||
if settings.extra_recording_buffer_ms > 0 {
|
||||
debug!(
|
||||
"Extra recording buffer: sleeping {}ms before stopping",
|
||||
settings.extra_recording_buffer_ms
|
||||
);
|
||||
std::thread::sleep(Duration::from_millis(settings.extra_recording_buffer_ms));
|
||||
}
|
||||
|
||||
let samples = if let Some(rec) = self.recorder.lock().unwrap().as_ref() {
|
||||
match rec.stop() {
|
||||
Ok(buf) => buf,
|
||||
|
|
|
|||
|
|
@ -395,6 +395,8 @@ pub struct AppSettings {
|
|||
pub whisper_accelerator: WhisperAcceleratorSetting,
|
||||
#[serde(default)]
|
||||
pub ort_accelerator: OrtAcceleratorSetting,
|
||||
#[serde(default)]
|
||||
pub extra_recording_buffer_ms: u64,
|
||||
}
|
||||
|
||||
fn default_model() -> String {
|
||||
|
|
@ -762,6 +764,7 @@ pub fn get_default_settings() -> AppSettings {
|
|||
custom_filler_words: None,
|
||||
whisper_accelerator: WhisperAcceleratorSetting::default(),
|
||||
ort_accelerator: OrtAcceleratorSetting::default(),
|
||||
extra_recording_buffer_ms: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -660,6 +660,15 @@ pub fn change_word_correction_threshold_setting(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_extra_recording_buffer_setting(app: AppHandle, ms: u64) -> Result<(), String> {
|
||||
let mut settings = settings::get_settings(&app);
|
||||
settings.extra_recording_buffer_ms = ms;
|
||||
settings::write_settings(&app, settings);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub fn change_paste_method_setting(app: AppHandle, method: String) -> Result<(), String> {
|
||||
|
|
|
|||
|
|
@ -109,6 +109,14 @@ async changeWordCorrectionThresholdSetting(threshold: number) : Promise<Result<n
|
|||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async changeExtraRecordingBufferSetting(ms: number) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_extra_recording_buffer_setting", { ms }) };
|
||||
} catch (e) {
|
||||
if(e instanceof Error) throw e;
|
||||
else return { status: "error", error: e as any };
|
||||
}
|
||||
},
|
||||
async changePasteMethodSetting(method: string) : Promise<Result<null, string>> {
|
||||
try {
|
||||
return { status: "ok", data: await TAURI_INVOKE("change_paste_method_setting", { method }) };
|
||||
|
|
@ -779,7 +787,7 @@ 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; whisper_accelerator?: WhisperAcceleratorSetting; ort_accelerator?: OrtAcceleratorSetting }
|
||||
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; extra_recording_buffer_ms?: number }
|
||||
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[] }
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { type } from "@tauri-apps/plugin-os";
|
|||
import { WordCorrectionThreshold } from "./WordCorrectionThreshold";
|
||||
import { LogLevelSelector } from "./LogLevelSelector";
|
||||
import { PasteDelay } from "./PasteDelay";
|
||||
import { RecordingBuffer } from "./RecordingBuffer";
|
||||
import { SettingsGroup } from "../../ui/SettingsGroup";
|
||||
import { AlwaysOnMicrophone } from "../AlwaysOnMicrophone";
|
||||
import { SoundPicker } from "../SoundPicker";
|
||||
|
|
@ -29,6 +30,7 @@ export const DebugSettings: React.FC = () => {
|
|||
/>
|
||||
<WordCorrectionThreshold descriptionMode="tooltip" grouped={true} />
|
||||
<PasteDelay descriptionMode="tooltip" grouped={true} />
|
||||
<RecordingBuffer descriptionMode="tooltip" grouped={true} />
|
||||
<AlwaysOnMicrophone descriptionMode="tooltip" grouped={true} />
|
||||
<ClamshellMicrophoneSelector descriptionMode="tooltip" grouped={true} />
|
||||
{/* Cancel shortcut is disabled on Linux due to instability with dynamic shortcut registration */}
|
||||
|
|
|
|||
36
src/components/settings/debug/RecordingBuffer.tsx
Normal file
36
src/components/settings/debug/RecordingBuffer.tsx
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Slider } from "../../ui/Slider";
|
||||
import { useSettings } from "../../../hooks/useSettings";
|
||||
|
||||
interface RecordingBufferProps {
|
||||
descriptionMode?: "tooltip" | "inline";
|
||||
grouped?: boolean;
|
||||
}
|
||||
|
||||
export const RecordingBuffer: React.FC<RecordingBufferProps> = ({
|
||||
descriptionMode = "tooltip",
|
||||
grouped = false,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { settings, updateSetting } = useSettings();
|
||||
|
||||
const handleBufferChange = (value: number) => {
|
||||
updateSetting("extra_recording_buffer_ms", value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Slider
|
||||
value={settings?.extra_recording_buffer_ms ?? 0}
|
||||
onChange={handleBufferChange}
|
||||
min={0}
|
||||
max={1500}
|
||||
step={50}
|
||||
label={t("settings.debug.recordingBuffer.title")}
|
||||
description={t("settings.debug.recordingBuffer.description")}
|
||||
descriptionMode={descriptionMode}
|
||||
grouped={grouped}
|
||||
formatValue={(v) => `${v}ms`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
@ -63,7 +63,7 @@ export const Slider: React.FC<SliderProps> = ({
|
|||
}}
|
||||
/>
|
||||
{showValue && (
|
||||
<span className="text-sm font-medium text-text/90 min-w-10 text-end">
|
||||
<span className="text-sm font-medium text-text/90 w-12 text-end">
|
||||
{formatValue(value)}
|
||||
</span>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -462,6 +462,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "تأخير اللصق",
|
||||
"description": "التأخير قبل إرسال ضغطة مفتاح اللصق (بالمللي ثانية). قم بزيادتها إذا تم لصق نص خاطئ."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "مخزن التسجيل الإضافي",
|
||||
"description": "وقت إضافي (بالمللي ثانية) للاستمرار في التسجيل بعد تحرير المفتاح، لالتقاط الصوت المتبقي. 0 = لا مخزن إضافي."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Zpoždění vložení",
|
||||
"description": "Zpoždění před odesláním klávesy pro vložení (v milisekundách). Zvyšte, pokud se vkládá špatný text."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Extra vyrovnávací paměť nahrávání",
|
||||
"description": "Extra čas (v milisekundách) pro pokračování nahrávání po uvolnění klávesy, pro zachycení zbývajícího zvuku. 0 = žádná extra vyrovnávací paměť."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Einfügeverzögerung",
|
||||
"description": "Verzögerung vor dem Senden des Einfüge-Tastendrucks (in Millisekunden). Erhöhen Sie den Wert, wenn falscher Text eingefügt wird."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Zusätzlicher Aufnahmepuffer",
|
||||
"description": "Zusätzliche Zeit (in Millisekunden), um nach dem Loslassen der Taste weiterzuzeichnen, um nachlaufendes Audio aufzunehmen. 0 = kein zusätzlicher Puffer."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Paste Delay",
|
||||
"description": "Delay before sending paste keystroke (in milliseconds). Increase if wrong text is being pasted."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Extra Recording Buffer",
|
||||
"description": "Extra time (in milliseconds) to keep recording after you release the key, to capture trailing audio. 0 = no extra buffer."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Retraso de pegado",
|
||||
"description": "Retraso antes de enviar la pulsación de tecla de pegar (en milisegundos). Aumente si se está pegando texto incorrecto."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Búfer de grabación adicional",
|
||||
"description": "Tiempo adicional (en milisegundos) para seguir grabando después de soltar la tecla, para capturar el audio restante. 0 = sin búfer adicional."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Délai de collage",
|
||||
"description": "Délai avant l'envoi de la touche de collage (en millisecondes). Augmentez si le mauvais texte est collé."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Tampon d'enregistrement supplémentaire",
|
||||
"description": "Temps supplémentaire (en millisecondes) pour continuer l'enregistrement après avoir relâché la touche, pour capturer l'audio restant. 0 = pas de tampon supplémentaire."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Ritardo incolla",
|
||||
"description": "Ritardo prima dell'invio del tasto incolla (in millisecondi). Aumentare se viene incollato il testo sbagliato."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Buffer di registrazione extra",
|
||||
"description": "Tempo extra (in millisecondi) per continuare a registrare dopo aver rilasciato il tasto, per catturare l'audio finale. 0 = nessun buffer extra."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "貼り付け遅延",
|
||||
"description": "貼り付けキー送信前の遅延(ミリ秒)。間違ったテキストが貼り付けられる場合は増やしてください。"
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "追加録音バッファ",
|
||||
"description": "キーを離した後に録音を続ける追加時間(ミリ秒)。末尾の音声を捕捉するため。0 = 追加バッファなし。"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -480,6 +480,10 @@
|
|||
"title": "붙여넣기 지연",
|
||||
"description": "붙여넣기 키 입력을 보내기 전 지연 시간(밀리초). 잘못된 텍스트가 붙여넣어지면 늘리세요."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "추가 녹음 버퍼",
|
||||
"description": "키를 놓은 후 추가로 녹음을 계속하는 시간(밀리초). 후행 오디오를 캡처하기 위함. 0 = 추가 버퍼 없음."
|
||||
},
|
||||
"paths": {
|
||||
"appData": "앱 데이터:",
|
||||
"models": "모델:",
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Opóźnienie wklejania",
|
||||
"description": "Opóźnienie przed wysłaniem klawisza wklejania (w milisekundach). Zwiększ, jeśli wklejany jest nieprawidłowy tekst."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Dodatkowy bufor nagrywania",
|
||||
"description": "Dodatkowy czas (w milisekundach) na kontynuowanie nagrywania po zwolnieniu klawisza, aby przechwycić końcowy dźwięk. 0 = brak dodatkowego bufora."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Atraso de colagem",
|
||||
"description": "Atraso antes de enviar a tecla de colar (em milissegundos). Aumente se o texto errado estiver sendo colado."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Buffer de gravação extra",
|
||||
"description": "Tempo extra (em milissegundos) para continuar gravando após soltar a tecla, para capturar áudio restante. 0 = sem buffer extra."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Задержка вставки",
|
||||
"description": "Задержка перед отправкой нажатия клавиши вставки (в миллисекундах). Увеличьте, если вставляется неправильный текст."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Дополнительный буфер записи",
|
||||
"description": "Дополнительное время (в миллисекундах) для продолжения записи после отпускания клавиши, чтобы захватить завершающий звук. 0 = без дополнительного буфера."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Yapıştırma gecikmesi",
|
||||
"description": "Yapıştırma tuşu göndermeden önce gecikme (milisaniye cinsinden). Yanlış metin yapıştırılıyorsa artırın."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Ekstra kayıt tamponu",
|
||||
"description": "Tuşu bıraktıktan sonra arka plandaki sesi yakalamak için kaydı sürdürme süresi (milisaniye). 0 = ekstra tampon yok."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Затримка вставки",
|
||||
"description": "Затримка перед надсиланням натискання клавіші вставки (у мілісекундах). Збільшіть, якщо вставляється неправильний текст."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Додатковий буфер запису",
|
||||
"description": "Додатковий час (у мілісекундах) для продовження запису після відпускання клавіші, щоб захопити завершальний звук. 0 = без додаткового буфера."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "Độ trễ dán",
|
||||
"description": "Độ trễ trước khi gửi phím dán (tính bằng mili giây). Tăng nếu văn bản sai đang được dán."
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "Bộ đệm ghi âm thêm",
|
||||
"description": "Thời gian thêm (tính bằng mili giây) để tiếp tục ghi âm sau khi nhả phím, để thu âm thanh cuối. 0 = không có bộ đệm thêm."
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "貼上延遲",
|
||||
"description": "發送貼上按鍵前的延遲(毫秒)。如果貼上了錯誤的文字,請增加此值"
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "額外錄音緩衝",
|
||||
"description": "放開按鍵後繼續錄音的額外時間(毫秒),以捕捉尾音。0 = 無額外緩衝。"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@
|
|||
"pasteDelay": {
|
||||
"title": "粘贴延迟",
|
||||
"description": "发送粘贴按键前的延迟(毫秒)。如果粘贴了错误的文本,请增加此值。"
|
||||
},
|
||||
"recordingBuffer": {
|
||||
"title": "额外录音缓冲",
|
||||
"description": "放开按键后继续录音的额外时间(毫秒),以捕捉尾音。0 = 无额外缓冲。"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
|
|
|
|||
|
|
@ -147,6 +147,8 @@ const settingUpdaters: {
|
|||
),
|
||||
ort_accelerator: (value) =>
|
||||
commands.changeOrtAcceleratorSetting(value as OrtAcceleratorSetting),
|
||||
extra_recording_buffer_ms: (value) =>
|
||||
commands.changeExtraRecordingBufferSetting(value as number),
|
||||
};
|
||||
|
||||
export const useSettingsStore = create<SettingsStore>()(
|
||||
|
|
|
|||
Loading…
Reference in a new issue