got cpu based backend working; trying python/gpu solution bc faster probs
This commit is contained in:
@ -13,7 +13,6 @@ import {
|
||||
Settings,
|
||||
Sparkles,
|
||||
Download,
|
||||
Loader2,
|
||||
FolderSearch,
|
||||
FileInput,
|
||||
} from 'lucide-react';
|
||||
@ -28,6 +27,7 @@ export default function App() {
|
||||
words,
|
||||
isTranscribing,
|
||||
transcriptionProgress,
|
||||
transcriptionStatus,
|
||||
loadVideo,
|
||||
setBackendUrl,
|
||||
setTranscription,
|
||||
@ -88,15 +88,19 @@ export default function App() {
|
||||
};
|
||||
|
||||
const transcribeVideo = async (path: string) => {
|
||||
setTranscribing(true, 0);
|
||||
setTranscribing(true, 0, 'Checking model...');
|
||||
try {
|
||||
const res = await fetch(`${backendUrl}/transcribe`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ file_path: path, model: whisperModel }),
|
||||
});
|
||||
if (!res.ok) throw new Error(`Transcription failed: ${res.statusText}`);
|
||||
const data = await res.json();
|
||||
if (!window.electronAPI?.transcribe) {
|
||||
throw new Error('Transcription not available');
|
||||
}
|
||||
// Step 1: ensure model is downloaded (may take a while on first run)
|
||||
const modelLabel = whisperModel === 'tiny' ? '~75 MB' : whisperModel === 'base' ? '~140 MB' : '~460 MB';
|
||||
setTranscribing(true, 5, `Downloading ${whisperModel} model (${modelLabel})...`);
|
||||
await window.electronAPI.ensureModel(whisperModel);
|
||||
|
||||
// Step 2: run transcription
|
||||
setTranscribing(true, 20, 'Transcribing audio...');
|
||||
const data = await window.electronAPI.transcribe(path, whisperModel);
|
||||
setTranscription(data);
|
||||
} catch (err) {
|
||||
console.error('Transcription error:', err);
|
||||
@ -244,11 +248,24 @@ export default function App() {
|
||||
{/* Transcript */}
|
||||
<div className="w-1/2 border-l border-editor-border flex flex-col min-h-0">
|
||||
{isTranscribing ? (
|
||||
<div className="flex-1 flex flex-col items-center justify-center gap-4">
|
||||
<Loader2 className="w-8 h-8 text-editor-accent animate-spin" />
|
||||
<p className="text-sm text-editor-text-muted">
|
||||
Transcribing... {Math.round(transcriptionProgress)}%
|
||||
</p>
|
||||
<div className="flex-1 flex flex-col items-center justify-center gap-5">
|
||||
{/* Animated waveform */}
|
||||
<div className="flex items-end gap-[3px] h-10">
|
||||
{[35, 60, 45, 80, 55, 70, 40, 65, 50, 75, 40, 58].map((h, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className="w-[5px] rounded-full bg-editor-accent wave-bar"
|
||||
style={{
|
||||
height: `${h}%`,
|
||||
animationDelay: `${i * 75}ms`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-center space-y-1">
|
||||
<p className="text-sm font-medium text-editor-text">Processing audio</p>
|
||||
<p className="text-xs text-editor-text-muted">{transcriptionStatus || 'Please wait...'}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : words.length > 0 ? (
|
||||
<TranscriptEditor />
|
||||
|
||||
@ -2,6 +2,17 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@keyframes waveBar {
|
||||
0% { transform: scaleY(0.3); opacity: 0.5; }
|
||||
50% { transform: scaleY(1); opacity: 1; }
|
||||
100% { transform: scaleY(0.3); opacity: 0.5; }
|
||||
}
|
||||
|
||||
.wave-bar {
|
||||
animation: waveBar 0.9s ease-in-out infinite;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@ -59,6 +59,14 @@ window.electronAPI = {
|
||||
return invoke<string>('decrypt_string', { encrypted });
|
||||
},
|
||||
|
||||
ensureModel: (modelName: string): Promise<string> => {
|
||||
return invoke<string>('ensure_model', { modelName });
|
||||
},
|
||||
|
||||
transcribe: (filePath: string, modelName: string, language?: string): Promise<any> => {
|
||||
return invoke('transcribe_audio', { filePath, modelName, language });
|
||||
},
|
||||
|
||||
readFile: (path: string): Promise<string> => {
|
||||
return readTextFile(path);
|
||||
},
|
||||
|
||||
@ -19,6 +19,7 @@ interface EditorState {
|
||||
|
||||
isTranscribing: boolean;
|
||||
transcriptionProgress: number;
|
||||
transcriptionStatus: string;
|
||||
isExporting: boolean;
|
||||
exportProgress: number;
|
||||
|
||||
@ -37,7 +38,7 @@ interface EditorActions {
|
||||
deleteSelectedWords: () => void;
|
||||
deleteWordRange: (startIndex: number, endIndex: number) => void;
|
||||
restoreRange: (rangeId: string) => void;
|
||||
setTranscribing: (active: boolean, progress?: number) => void;
|
||||
setTranscribing: (active: boolean, progress?: number, status?: string) => void;
|
||||
setExporting: (active: boolean, progress?: number) => void;
|
||||
getKeepSegments: () => Array<{ start: number; end: number }>;
|
||||
getWordAtTime: (time: number) => number;
|
||||
@ -59,6 +60,7 @@ const initialState: EditorState = {
|
||||
hoveredWordIndex: null,
|
||||
isTranscribing: false,
|
||||
transcriptionProgress: 0,
|
||||
transcriptionStatus: '',
|
||||
isExporting: false,
|
||||
exportProgress: 0,
|
||||
backendUrl: 'http://localhost:8642',
|
||||
@ -147,10 +149,11 @@ export const useEditorStore = create<EditorState & EditorActions>()(
|
||||
set({ deletedRanges: deletedRanges.filter((r) => r.id !== rangeId) });
|
||||
},
|
||||
|
||||
setTranscribing: (active, progress) =>
|
||||
setTranscribing: (active, progress, status) =>
|
||||
set({
|
||||
isTranscribing: active,
|
||||
transcriptionProgress: progress ?? (active ? 0 : 100),
|
||||
transcriptionStatus: status ?? (active ? '' : ''),
|
||||
}),
|
||||
|
||||
setExporting: (active, progress) =>
|
||||
|
||||
2
frontend/src/vite-env.d.ts
vendored
2
frontend/src/vite-env.d.ts
vendored
@ -7,6 +7,8 @@ interface ElectronAPI {
|
||||
getBackendUrl: () => Promise<string>;
|
||||
encryptString: (data: string) => Promise<string>;
|
||||
decryptString: (encrypted: string) => Promise<string>;
|
||||
ensureModel: (modelName: string) => Promise<string>;
|
||||
transcribe: (filePath: string, modelName: string, language?: string) => Promise<any>;
|
||||
readFile: (path: string) => Promise<string>;
|
||||
writeFile: (path: string, content: string) => Promise<boolean>;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user