Cross-platform distribution, UI improvements, and performance optimizations

- PyInstaller frozen sidecar: spec file, build script, and ffmpeg path resolver
  for self-contained distribution without Python prerequisites
- Dual-mode sidecar launcher: frozen binary (production) with dev mode fallback
- Parallel transcription + diarization pipeline (~30-40% faster)
- GPU auto-detection for diarization (CUDA when available)
- Async run_pipeline command for real-time progress event delivery
- Web Audio API backend for instant playback and seeking
- OpenAI-compatible provider replacing LiteLLM client-side routing
- Cross-platform RAM detection (Linux/macOS/Windows)
- Settings: speaker count hint, token reveal toggles, dark dropdown styling
- Loading splash screen, flexbox layout fix for viewport overflow
- Gitea Actions CI/CD pipeline (Linux, Windows, macOS ARM)
- Updated README and CLAUDE.md documentation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude
2026-03-20 21:33:43 -07:00
parent 42ccd3e21d
commit 58faa83cb3
27 changed files with 1301 additions and 283 deletions

View File

@@ -13,6 +13,7 @@
let container: HTMLDivElement;
let wavesurfer: WaveSurfer | null = $state(null);
let isReady = $state(false);
let isLoading = $state(false);
let currentTime = $state('0:00');
let totalTime = $state('0:00');
@@ -32,6 +33,7 @@
barWidth: 2,
barGap: 1,
barRadius: 2,
backend: 'WebAudio',
});
wavesurfer.on('timeupdate', (time: number) => {
@@ -41,6 +43,7 @@
wavesurfer.on('ready', () => {
isReady = true;
isLoading = false;
const dur = wavesurfer!.getDuration();
durationMs.set(Math.round(dur * 1000));
totalTime = formatTime(dur);
@@ -55,7 +58,7 @@
});
if (audioUrl) {
wavesurfer.load(audioUrl);
loadAudio(audioUrl);
}
});
@@ -89,16 +92,13 @@
console.warn('[voice-to-notes] seekTo ignored — audio not ready yet');
return;
}
const timeSec = timeMs / 1000;
wavesurfer.setTime(timeSec);
if (!wavesurfer.isPlaying()) {
wavesurfer.play();
}
wavesurfer.setTime(timeMs / 1000);
}
/** Load a new audio file. */
export function loadAudio(url: string) {
isReady = false;
isLoading = true;
wavesurfer?.load(url);
}
</script>