@bryan-gc/transcribe-cli 1.0.6 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,93 +1,11 @@
1
1
  import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { useState, useRef, useEffect, useCallback } from 'react';
3
2
  import { Box, Text, useInput } from 'ink';
4
- import path from 'path';
5
- import fs from 'fs';
6
- import { AudioRecorder } from '../audio/recorder.js';
7
- import { playAudio, stopPlayback } from '../audio/audioPlayer.js';
8
- import { RECORDING_TICK_MS, ActionHotkey, TestStatus, getPaths } from '../constants.js';
9
- const AUTO_STOP_SECS = 5;
3
+ import { useMicTest } from '../hooks/useMicTest.js';
4
+ import { ActionHotkey, TestStatus } from '../constants.js';
10
5
  export function MicTest({ mic, basePath, onConfirm, onCancel }) {
11
- const [status, setStatus] = useState(TestStatus.IDLE);
12
- const [hasRecording, setHasRecording] = useState(false);
13
- const [elapsed, setElapsed] = useState(0);
14
- const [errorText, setErrorText] = useState('');
15
- const testFilePath = getPaths(basePath).TEST_FILE;
16
- const recorderRef = useRef(new AudioRecorder());
17
- const timerRef = useRef(null);
18
- const stoppingRef = useRef(false);
19
- useEffect(() => {
20
- const recorderInstance = recorderRef.current;
21
- return () => {
22
- clearTimer();
23
- stoppingRef.current = true;
24
- recorderInstance.stop().catch(() => { });
25
- stopPlayback();
26
- };
27
- }, []);
28
- function clearTimer() {
29
- if (timerRef.current) {
30
- clearInterval(timerRef.current);
31
- timerRef.current = null;
32
- }
33
- }
34
- function startRecording() {
35
- if (status === TestStatus.RECORDING)
36
- return;
37
- try {
38
- const tmpDir = path.dirname(testFilePath);
39
- if (!fs.existsSync(tmpDir))
40
- fs.mkdirSync(tmpDir, { recursive: true });
41
- recorderRef.current.setDevice(mic.id);
42
- recorderRef.current.start(testFilePath);
43
- setStatus(TestStatus.RECORDING);
44
- setElapsed(0);
45
- setErrorText('');
46
- timerRef.current = setInterval(() => {
47
- setElapsed((prev) => {
48
- const next = prev + 1;
49
- if (next >= AUTO_STOP_SECS)
50
- stopRecording();
51
- return next;
52
- });
53
- }, RECORDING_TICK_MS);
54
- }
55
- catch (e) {
56
- setErrorText(`Recording error: ${e instanceof Error ? e.message : String(e)}`);
57
- }
58
- }
59
- const stopRecording = useCallback(async () => {
60
- if (stoppingRef.current)
61
- return;
62
- stoppingRef.current = true;
63
- clearTimer();
64
- setStatus(TestStatus.SAVING);
65
- await recorderRef.current.stop();
66
- stoppingRef.current = false;
67
- setStatus(TestStatus.RECORDED);
68
- setHasRecording(true);
69
- }, []);
70
- async function handlePlayback() {
71
- if (!hasRecording || !fs.existsSync(testFilePath)) {
72
- setErrorText('No test recording found. Record first.');
73
- return;
74
- }
75
- setStatus(TestStatus.PLAYING);
76
- setErrorText('');
77
- try {
78
- await playAudio(testFilePath);
79
- }
80
- catch (e) {
81
- setErrorText(`Playback error: ${e instanceof Error ? e.message : String(e)}`);
82
- }
83
- finally {
84
- setStatus(TestStatus.RECORDED);
85
- }
86
- }
87
- function handleStopPlayback() {
88
- stopPlayback();
89
- setStatus(TestStatus.RECORDED);
90
- }
6
+ const { state, actions } = useMicTest(mic, basePath);
7
+ const { status, hasRecording, elapsed, errorText, AUTO_STOP_SECS } = state;
8
+ const { startRecording, stopRecording, handlePlayback, handleStopPlayback } = actions;
91
9
  useInput((input, key) => {
92
10
  const k = input.toLowerCase();
93
11
  if (key.escape || k === ActionHotkey.CANCEL_C) {
@@ -133,7 +51,7 @@ export function MicTest({ mic, basePath, onConfirm, onCancel }) {
133
51
  }
134
52
  };
135
53
  // ─── Action list ──────────────────────────────────────────────────────────
136
- const actions = () => {
54
+ const actionList = () => {
137
55
  switch (status) {
138
56
  case TestStatus.RECORDING:
139
57
  return _jsxs(Text, { color: "yellow", children: ["[", ActionHotkey.STOP, "] Stop recording early"] });
@@ -145,6 +63,6 @@ export function MicTest({ mic, basePath, onConfirm, onCancel }) {
145
63
  return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: "cyan", children: ["[", ActionHotkey.RECORD, "]", ' ', status === TestStatus.RECORDED ? 'Record Again' : 'Record Test', ' ', _jsxs(Text, { dimColor: true, children: ["(auto-stops at ", AUTO_STOP_SECS, "s)"] })] }), hasRecording && _jsxs(Text, { color: "cyan", children: ["[", ActionHotkey.PLAYBACK, "] Play Back"] }), _jsxs(Text, { color: "green", children: ["[", ActionHotkey.CONFIRM, "] Confirm \u2014 use this microphone"] }), _jsxs(Text, { color: "red", children: ["[", ActionHotkey.CANCEL_C, "] Cancel \u2014 choose a different mic"] })] }));
146
64
  }
147
65
  };
148
- return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: '=== Microphone Test ===' }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: ["Microphone: ", _jsx(Text, { color: "magenta", children: mic.label })] }), _jsxs(Text, { children: ["Device ID: ", _jsx(Text, { dimColor: true, children: mic.id })] })] }), _jsx(Box, { marginTop: 1, marginBottom: 1, children: statusLine() }), actions(), errorText !== '' && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u26A0\uFE0F ", errorText] }) })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Esc/[", ActionHotkey.CANCEL_C, "] cancel \u00B7 [", ActionHotkey.CONFIRM, "]/Enter confirm"] }) })] }));
66
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { bold: true, children: '=== Microphone Test ===' }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsxs(Text, { children: ["Microphone: ", _jsx(Text, { color: "magenta", children: mic.label })] }), _jsxs(Text, { children: ["Device ID: ", _jsx(Text, { dimColor: true, children: mic.id })] })] }), _jsx(Box, { marginTop: 1, marginBottom: 1, children: statusLine() }), actionList(), errorText !== '' && (_jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: "red", children: ["\u26A0\uFE0F ", errorText] }) })), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Esc/[", ActionHotkey.CANCEL_C, "] cancel \u00B7 [", ActionHotkey.CONFIRM, "]/Enter confirm"] }) })] }));
149
67
  }
150
68
  //# sourceMappingURL=MicTest.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MicTest.js","sourceRoot":"","sources":["../../src/components/MicTest.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MicTest.js","sourceRoot":"","sources":["../../src/components/MicTest.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { AppConfig } from '../config/configManager.js';
2
+ export declare function useAutoRecord(appConfig: AppConfig, exit: () => void): {
3
+ state: {
4
+ statusText: string;
5
+ isRecording: boolean;
6
+ isTranscribing: boolean;
7
+ transcriptionResult: string;
8
+ activeLanguage: import("../constants.js").LanguageCode;
9
+ activeMic: import("../audio/micDevices.js").MicDevice;
10
+ activeGlossary: string;
11
+ currentTextPath: string;
12
+ };
13
+ actions: {
14
+ handleStopAndTranscribe: () => Promise<void>;
15
+ forceStop: () => void;
16
+ };
17
+ };
18
+ //# sourceMappingURL=useAutoRecord.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutoRecord.d.ts","sourceRoot":"","sources":["../../src/hooks/useAutoRecord.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAK5D,wBAAgB,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,IAAI;;;;;;;;;;;;;;;EA8HnE"}
@@ -0,0 +1,110 @@
1
+ import { useState, useEffect, useRef } from 'react';
2
+ import fs from 'fs';
3
+ import { AudioRecorder } from '../audio/recorder.js';
4
+ import { WhisperTranscriber } from '../transcriber/WhisperTranscriber.js';
5
+ import { extractTextFromSrt } from '../utils/srtParser.js';
6
+ import { copyTextToClipboard } from '../utils/clipboard.js';
7
+ import { listMicDevices } from '../audio/micDevices.js';
8
+ import { getTimestampPaths, readGlossaryContent, getInitialGlossary } from '../utils/fileUtils.js';
9
+ import { Encoding, LANGUAGE_NAMES, TranscriptionFormat } from '../constants.js';
10
+ export function useAutoRecord(appConfig, exit) {
11
+ const [statusText, setStatusText] = useState('Initializing recording...');
12
+ const [isRecording, setIsRecording] = useState(false);
13
+ const [isTranscribing, setIsTranscribing] = useState(false);
14
+ const [transcriptionResult, setTranscriptionResult] = useState('');
15
+ const [currentAudioPath, setCurrentAudioPath] = useState('');
16
+ const [currentSrtPath, setCurrentSrtPath] = useState('');
17
+ const [currentTextPath, setCurrentTextPath] = useState('');
18
+ const recorderRef = useRef(null);
19
+ const transcriberRef = useRef(null);
20
+ const activeLanguage = appConfig.selectedLanguage;
21
+ const activeMicId = appConfig.selectedMicrophone;
22
+ const mics = listMicDevices();
23
+ const activeMic = mics.find((m) => m.id === activeMicId) ?? {
24
+ id: activeMicId,
25
+ label: activeMicId,
26
+ };
27
+ const activeGlossary = getInitialGlossary(appConfig.basePath);
28
+ useEffect(() => {
29
+ const recorder = new AudioRecorder();
30
+ recorderRef.current = recorder;
31
+ transcriberRef.current = new WhisperTranscriber(appConfig.apiKey);
32
+ try {
33
+ recorder.setDevice(activeMic.id);
34
+ }
35
+ catch {
36
+ // Ignore if device fails, recorder will try default
37
+ }
38
+ const p = getTimestampPaths(appConfig.basePath);
39
+ setCurrentAudioPath(p.audioPath);
40
+ setCurrentSrtPath(p.srtPath);
41
+ setCurrentTextPath(p.textPath);
42
+ recorder.start(p.audioPath);
43
+ setIsRecording(true);
44
+ setStatusText('🔴 Recording... Press [Enter] to stop and transcribe.');
45
+ return () => {
46
+ if (recorderRef.current) {
47
+ recorderRef.current.stop().catch(() => { });
48
+ }
49
+ };
50
+ }, [appConfig, activeMic.id]);
51
+ const handleStopAndTranscribe = async () => {
52
+ if (!recorderRef.current || !transcriberRef.current || !isRecording || isTranscribing) {
53
+ return;
54
+ }
55
+ try {
56
+ setIsRecording(false);
57
+ setIsTranscribing(true);
58
+ setStatusText('⏹️ Stopped recording. Saving file...');
59
+ await recorderRef.current.stop();
60
+ recorderRef.current = null;
61
+ if (!fs.existsSync(currentAudioPath)) {
62
+ setStatusText('❌ Error: Audio file was not generated.');
63
+ setTimeout(exit, 2000);
64
+ return;
65
+ }
66
+ const glossaryPrompt = readGlossaryContent(appConfig.basePath, activeGlossary);
67
+ setStatusText(`⏳ Transcribing (${LANGUAGE_NAMES[activeLanguage]}${glossaryPrompt ? ' + glossary' : ''})...`);
68
+ const srtContent = await transcriberRef.current.transcribe(currentAudioPath, activeLanguage, TranscriptionFormat.SRT, glossaryPrompt, (msg) => setStatusText(`⏳ Transcribing: ${msg}`));
69
+ setStatusText('⏳ Formatting text and saving files...');
70
+ fs.writeFileSync(currentSrtPath, srtContent, Encoding.UTF8);
71
+ const cleanText = extractTextFromSrt(srtContent);
72
+ fs.writeFileSync(currentTextPath, cleanText, Encoding.UTF8);
73
+ setTranscriptionResult(cleanText);
74
+ if (appConfig.autoCopy) {
75
+ copyTextToClipboard(cleanText);
76
+ setStatusText('✅ Transcription done — copied to clipboard.');
77
+ }
78
+ else {
79
+ setStatusText('✅ Transcription completed and saved.');
80
+ }
81
+ setTimeout(exit, 500);
82
+ }
83
+ catch (err) {
84
+ setStatusText(`❌ Error: ${err instanceof Error ? err.message : String(err)}`);
85
+ setIsTranscribing(false);
86
+ setTimeout(exit, 3000);
87
+ }
88
+ };
89
+ const forceStop = () => {
90
+ if (recorderRef.current)
91
+ recorderRef.current.stop().catch(() => { });
92
+ };
93
+ return {
94
+ state: {
95
+ statusText,
96
+ isRecording,
97
+ isTranscribing,
98
+ transcriptionResult,
99
+ activeLanguage,
100
+ activeMic,
101
+ activeGlossary,
102
+ currentTextPath,
103
+ },
104
+ actions: {
105
+ handleStopAndTranscribe,
106
+ forceStop,
107
+ },
108
+ };
109
+ }
110
+ //# sourceMappingURL=useAutoRecord.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutoRecord.js","sourceRoot":"","sources":["../../src/hooks/useAutoRecord.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,sCAAsC,CAAC;AAC1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACnG,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEhF,MAAM,UAAU,aAAa,CAAC,SAAoB,EAAE,IAAgB;IAClE,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,2BAA2B,CAAC,CAAC;IAC1E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,CAAC,mBAAmB,EAAE,sBAAsB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEnE,MAAM,CAAC,gBAAgB,EAAE,mBAAmB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC7D,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAE3D,MAAM,WAAW,GAAG,MAAM,CAAuB,IAAI,CAAC,CAAC;IACvD,MAAM,cAAc,GAAG,MAAM,CAA4B,IAAI,CAAC,CAAC;IAE/D,MAAM,cAAc,GAAG,SAAS,CAAC,gBAAgB,CAAC;IAClD,MAAM,WAAW,GAAG,SAAS,CAAC,kBAAkB,CAAC;IAEjD,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,IAAI;QAC1D,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,WAAW;KACnB,CAAC;IAEF,MAAM,cAAc,GAAG,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAE9D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACrC,WAAW,CAAC,OAAO,GAAG,QAAQ,CAAC;QAC/B,cAAc,CAAC,OAAO,GAAG,IAAI,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAElE,IAAI,CAAC;YACH,QAAQ,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,oDAAoD;QACtD,CAAC;QAED,MAAM,CAAC,GAAG,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChD,mBAAmB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACjC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC7B,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAE/B,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC5B,cAAc,CAAC,IAAI,CAAC,CAAC;QACrB,aAAa,CAAC,uDAAuD,CAAC,CAAC;QAEvE,OAAO,GAAG,EAAE;YACV,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;gBACxB,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAE9B,MAAM,uBAAuB,GAAG,KAAK,IAAI,EAAE;QACzC,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI,CAAC,WAAW,IAAI,cAAc,EAAE,CAAC;YACtF,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,cAAc,CAAC,KAAK,CAAC,CAAC;YACtB,iBAAiB,CAAC,IAAI,CAAC,CAAC;YACxB,aAAa,CAAC,uCAAuC,CAAC,CAAC;YAEvD,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YACjC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAC;YAE3B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBACrC,aAAa,CAAC,wCAAwC,CAAC,CAAC;gBACxD,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACvB,OAAO;YACT,CAAC;YAED,MAAM,cAAc,GAAG,mBAAmB,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAE/E,aAAa,CACX,mBAAmB,cAAc,CAAC,cAAc,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,CAC9F,CAAC;YAEF,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,UAAU,CACxD,gBAAgB,EAChB,cAAc,EACd,mBAAmB,CAAC,GAAG,EACvB,cAAc,EACd,CAAC,GAAG,EAAE,EAAE,CAAC,aAAa,CAAC,mBAAmB,GAAG,EAAE,CAAC,CACjD,CAAC;YAEF,aAAa,CAAC,uCAAuC,CAAC,CAAC;YACvD,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,kBAAkB,CAAC,UAAU,CAAC,CAAC;YACjD,EAAE,CAAC,aAAa,CAAC,eAAe,EAAE,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAE5D,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAElC,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;gBACvB,mBAAmB,CAAC,SAAS,CAAC,CAAC;gBAC/B,aAAa,CAAC,6CAA6C,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,aAAa,CAAC,sCAAsC,CAAC,CAAC;YACxD,CAAC;YAED,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACxB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,aAAa,CAAC,YAAY,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9E,iBAAiB,CAAC,KAAK,CAAC,CAAC;YACzB,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,IAAI,WAAW,CAAC,OAAO;YAAE,WAAW,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE;YACL,UAAU;YACV,WAAW;YACX,cAAc;YACd,mBAAmB;YACnB,cAAc;YACd,SAAS;YACT,cAAc;YACd,eAAe;SAChB;QACD,OAAO,EAAE;YACP,uBAAuB;YACvB,SAAS;SACV;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { MicDevice } from '../audio/micDevices.js';
2
+ import { TestStatus } from '../constants.js';
3
+ export declare function useMicTest(mic: MicDevice, basePath: string): {
4
+ state: {
5
+ status: TestStatus;
6
+ hasRecording: boolean;
7
+ elapsed: number;
8
+ errorText: string;
9
+ AUTO_STOP_SECS: number;
10
+ };
11
+ actions: {
12
+ startRecording: () => void;
13
+ stopRecording: () => Promise<void>;
14
+ handlePlayback: () => Promise<void>;
15
+ handleStopPlayback: () => void;
16
+ };
17
+ };
18
+ //# sourceMappingURL=useMicTest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMicTest.d.ts","sourceRoot":"","sources":["../../src/hooks/useMicTest.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAqB,UAAU,EAAY,MAAM,iBAAiB,CAAC;AAE1E,wBAAgB,UAAU,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;;;;;;;;;8BA6B9B,IAAI;;8BAmCE,OAAO,CAAC,IAAI,CAAC;kCAgBf,IAAI;;EAoBpC"}
@@ -0,0 +1,105 @@
1
+ import { useState, useRef, useEffect, useCallback } from 'react';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { AudioRecorder } from '../audio/recorder.js';
5
+ import { playAudio, stopPlayback } from '../audio/audioPlayer.js';
6
+ import { RECORDING_TICK_MS, TestStatus, getPaths } from '../constants.js';
7
+ export function useMicTest(mic, basePath) {
8
+ const AUTO_STOP_SECS = 5;
9
+ const [status, setStatus] = useState(TestStatus.IDLE);
10
+ const [hasRecording, setHasRecording] = useState(false);
11
+ const [elapsed, setElapsed] = useState(0);
12
+ const [errorText, setErrorText] = useState('');
13
+ const testFilePath = getPaths(basePath).TEST_FILE;
14
+ const recorderRef = useRef(new AudioRecorder());
15
+ const timerRef = useRef(null);
16
+ const stoppingRef = useRef(false);
17
+ useEffect(() => {
18
+ const recorderInstance = recorderRef.current;
19
+ return () => {
20
+ clearTimer();
21
+ stoppingRef.current = true;
22
+ recorderInstance.stop().catch(() => { });
23
+ stopPlayback();
24
+ };
25
+ }, []);
26
+ function clearTimer() {
27
+ if (timerRef.current) {
28
+ clearInterval(timerRef.current);
29
+ timerRef.current = null;
30
+ }
31
+ }
32
+ function startRecording() {
33
+ if (status === TestStatus.RECORDING)
34
+ return;
35
+ try {
36
+ const tmpDir = path.dirname(testFilePath);
37
+ if (!fs.existsSync(tmpDir))
38
+ fs.mkdirSync(tmpDir, { recursive: true });
39
+ recorderRef.current.setDevice(mic.id);
40
+ recorderRef.current.start(testFilePath);
41
+ setStatus(TestStatus.RECORDING);
42
+ setElapsed(0);
43
+ setErrorText('');
44
+ timerRef.current = setInterval(() => {
45
+ setElapsed((prev) => {
46
+ const next = prev + 1;
47
+ if (next >= AUTO_STOP_SECS)
48
+ stopRecording();
49
+ return next;
50
+ });
51
+ }, RECORDING_TICK_MS);
52
+ }
53
+ catch (e) {
54
+ setErrorText(`Recording error: ${e instanceof Error ? e.message : String(e)}`);
55
+ }
56
+ }
57
+ const stopRecording = useCallback(async () => {
58
+ if (stoppingRef.current)
59
+ return;
60
+ stoppingRef.current = true;
61
+ clearTimer();
62
+ setStatus(TestStatus.SAVING);
63
+ await recorderRef.current.stop();
64
+ stoppingRef.current = false;
65
+ setStatus(TestStatus.RECORDED);
66
+ setHasRecording(true);
67
+ }, []);
68
+ async function handlePlayback() {
69
+ if (!hasRecording || !fs.existsSync(testFilePath)) {
70
+ setErrorText('No test recording found. Record first.');
71
+ return;
72
+ }
73
+ setStatus(TestStatus.PLAYING);
74
+ setErrorText('');
75
+ try {
76
+ await playAudio(testFilePath);
77
+ }
78
+ catch (e) {
79
+ setErrorText(`Playback error: ${e instanceof Error ? e.message : String(e)}`);
80
+ }
81
+ finally {
82
+ setStatus(TestStatus.RECORDED);
83
+ }
84
+ }
85
+ function handleStopPlayback() {
86
+ stopPlayback();
87
+ setStatus(TestStatus.RECORDED);
88
+ }
89
+ return {
90
+ state: {
91
+ status,
92
+ hasRecording,
93
+ elapsed,
94
+ errorText,
95
+ AUTO_STOP_SECS,
96
+ },
97
+ actions: {
98
+ startRecording,
99
+ stopRecording,
100
+ handlePlayback,
101
+ handleStopPlayback,
102
+ },
103
+ };
104
+ }
105
+ //# sourceMappingURL=useMicTest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMicTest.js","sourceRoot":"","sources":["../../src/hooks/useMicTest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ import { AudioRecorder } from '../audio/recorder.js';
2
+ import { type MicDevice } from '../audio/micDevices.js';
3
+ import { type AppConfig } from '../config/configManager.js';
4
+ import { LanguageCode, ViewMode, MenuAction } from '../constants.js';
5
+ export declare function useTranscriberApp(appConfig: AppConfig, exit: () => void): {
6
+ state: {
7
+ viewMode: ViewMode;
8
+ selectedIndex: number;
9
+ statusText: string;
10
+ isRecording: boolean;
11
+ isPaused: boolean;
12
+ isTranscribing: boolean;
13
+ transcriptionResult: string;
14
+ clipboardEnabled: boolean;
15
+ currentTextPath: string;
16
+ activeLanguage: LanguageCode;
17
+ activeGlossary: string;
18
+ activeMic: MicDevice;
19
+ pendingMic: MicDevice;
20
+ micDevices: MicDevice[];
21
+ glossaryFiles: string[];
22
+ recorder: AudioRecorder;
23
+ };
24
+ actions: {
25
+ setViewMode: import("react").Dispatch<import("react").SetStateAction<ViewMode>>;
26
+ setSelectedIndex: import("react").Dispatch<import("react").SetStateAction<number>>;
27
+ setStatusText: import("react").Dispatch<import("react").SetStateAction<string>>;
28
+ setActiveLanguage: import("react").Dispatch<import("react").SetStateAction<LanguageCode>>;
29
+ setActiveGlossary: import("react").Dispatch<import("react").SetStateAction<string>>;
30
+ setActiveMic: import("react").Dispatch<import("react").SetStateAction<MicDevice>>;
31
+ setPendingMic: import("react").Dispatch<import("react").SetStateAction<MicDevice>>;
32
+ handleAction: (actionId: MenuAction) => Promise<void>;
33
+ saveConfig: (updates: Partial<AppConfig>) => void;
34
+ };
35
+ };
36
+ //# sourceMappingURL=useTranscriberApp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTranscriberApp.d.ts","sourceRoot":"","sources":["../../src/hooks/useTranscriberApp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAkB,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAIxE,OAAO,EAAE,KAAK,SAAS,EAAiB,MAAM,4BAA4B,CAAC;AAE3E,OAAO,EAIL,YAAY,EAIZ,QAAQ,EACR,UAAU,EACX,MAAM,iBAAiB,CAAC;AAEzB,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;iCAqDnD,UAAU;8BApBjB,OAAO,CAAC,SAAS,CAAC;;EA4L/B"}