# Fix HQ Upgrade, Audio Playback, and Waveform **Date:** 2026-09-21 20:01 **Task:** Fix three bugs reported after the previous batch of changes ## Changes Made ### 1. Waveform Truncation Fix **File:** `src-tauri/src/services/waveform_generator.rs` **Root cause:** `compute_peaks` used `peaks.resize(target_count, 0.0)` to pad the peaks array to exactly `target_count` entries. But when `chunk_size = ceil(samples / target_count)` rounds up (e.g., 201439 samples / 200000 target = chunk_size 2), the actual number of chunks produced is far less than `target_count` (100720 vs 200000). The resize pads ~50% of the array with zeros, compressing the real waveform into the first half and leaving the rest flat. **Fix:** Removed the `peaks.resize(target_count, 0.0)` call. The downstream rendering code already handles arrays of any length — the peak count from chunking is the correct count. ### 2. Export Format Fix (HQ Upgrade Black Screen) **File:** `src/lib/stores/videoSession.svelte.ts` **Root cause:** `EXPORT_FORMAT = 'bv*+ba/b'` allowed yt-dlp to pick the best format regardless of codec — which resulted in AV1+Opus in WebM. WKWebView on macOS cannot decode AV1 or Opus, so upgrading to the HQ preview produced a black screen with no playback. **Fix:** Changed `EXPORT_FORMAT` to `'bv*[vcodec^=avc1]+ba[acodec^=mp4a]/b[ext=mp4]/best[ext=mp4]'` to force H.264+AAC in MP4, matching what WKWebView can play. Deleted the cached `.webm` export file so the next run re-downloads in the correct format. ### 3. Volume Controls + Audio Diagnostics **File:** `src/lib/components/VideoPlayer.svelte` - Added `volume` and `isMuted` state variables with reactive sync to the video element - Added mute toggle button (speaker emoji) and volume slider in a new bottom controls bar - Added diagnostic `console.log` in `handleLoadedData` to print muted, volume, readyState, audioTracks length, and dimensions — this will help trace the audio issue if it persists - Reorganized the bottom overlay: volume controls on the left, CC/settings on the right ## Lessons Learned - When `samples.chunks(chunk_size)` is used with a `chunk_size > 1`, the number of resulting chunks is `ceil(samples / chunk_size)`, which is strictly less than `target_count` when `chunk_size = ceil(samples / target_count)`. Never pad with zeros — it corrupts the waveform mapping to time. - yt-dlp's `bv*+ba/b` format spec can pick any codec. On macOS, always constrain to H.264+AAC for WKWebView compatibility. - The audio issue may be related to mixed content (HTTPS frontend loading HTTP media) — the diagnostic logging added here will help isolate whether the issue is mute state, volume, or something lower-level in WebKit. ## Verification - `cargo build`: OK (only pre-existing warnings) - `cargo test`: 37 tests pass - `npm run check`: OK (only pre-existing vite.config.ts errors) ## Follow-up - Run `npx tauri dev` and verify waveform renders across the full timeline - Verify HQ upgrade no longer produces a black screen - Check console output from `handleLoadedData` diagnostic to trace audio issue - If audio still doesn't play, investigate mixed content blocking in WKWebView