Skip to content

fix(editor): preserve Windows microphone audio during preview#677

Open
sin6626 wants to merge 3 commits into
webadderallorg:mainfrom
sin6626:codex/fix-windows-editor-mic-audio
Open

fix(editor): preserve Windows microphone audio during preview#677
sin6626 wants to merge 3 commits into
webadderallorg:mainfrom
sin6626:codex/fix-windows-editor-mic-audio

Conversation

@sin6626

@sin6626 sin6626 commented Jun 12, 2026

Copy link
Copy Markdown

Description

Fix Windows editor preview cases where a companion microphone track has an incomplete waveform or becomes silent after the first part of a recording even though the recorded WAV and exported video still contain the audio.

The editor now:

  • probes companion sidecar duration/sample metadata in the main process
  • decodes local WAV sidecars directly to PCM for preview and waveform generation
  • falls back to the browser decoder for WAV subformats not handled by the custom decoder
  • keeps asynchronous resource loading independent from play/pause and volume rerenders
  • uses resource-version keys to discard stale results without cancelling the current load
  • starts a newly decoded buffer at the current timeline position
  • prevents stale asynchronous playback from restarting a track after pause or seek
  • uses probed duration to represent partial waveform coverage accurately

Motivation

On Windows 11, Chromium can expose only part of a long companion WAV through the media-element path. Playback then stops around a fixed timestamp while export remains correct. The timeline can show a full-length microphone track whose waveform only covers the beginning, even though the sidecar contains the complete recording. Playback-state rerenders could also invalidate an in-flight sidecar load, leaving the editor permanently silent.

Type of Change

  • New Feature
  • Bug Fix
  • Refactor / Code Cleanup
  • Documentation Update
  • Other

Related Issue(s)

Fixes #602
Related to #629, #636, and #667.

This is separate from #536: that PR addresses audio loss during recording/mixing, while this PR addresses editor preview and waveform handling when the recorded companion WAV already exists.

This PR is also submitted for consideration for the $50 bounty offered in #629. It fixes the editor-preview variant represented most precisely by duplicate issue #636, and has now been tested with a real affected Windows 11 recording.

Screenshots / Video

Not applicable; this changes audio playback and waveform completeness rather than adding a new UI surface.

Testing Guide

  1. On Windows 11, record at least 60 seconds with microphone enabled.
  2. Open the recording in the editor.
  3. Confirm the microphone waveform covers the actual sidecar duration.
  4. Play and seek beyond the previous 19-25 second cutoff.
  5. Pause/resume while the project is loading and confirm microphone audio still starts at the current position.
  6. Seek near the end, return to the middle, and confirm stale playback does not restart.
  7. Export and confirm audio remains present.

Automated validation:

  • latest focused review validation: 5 test files, 48 tests passed
  • full Vitest run: 93 files and 797 tests passed; one unrelated exporter suite hit its existing explicit 30-second dynamic-import timeout
  • the timed-out exporter suite passed 5/5 when rerun in isolation
  • production Vite/Electron build passed for the original fix
  • Biome checks on the latest touched files passed
  • git diff --check passed

TypeScript currently reports the same pre-existing upstream error on the untouched zoomRegionUtils.ts: getConnectedRegionTransition is declared but never read.

Windows 11 manual validation:

  • launched the PR branch with npm run dev
  • opened an affected recording longer than the previous cutoff
  • confirmed the microphone waveform covers the full recorded duration
  • confirmed microphone audio remains audible beyond the previous 19-25 second cutoff
  • confirmed play, pause, seeking, end-of-track, and returning to the middle work correctly
  • confirmed the video exports successfully with audio present

Checklist

  • I have performed a self-review of my code.
  • I have added any necessary screenshots or videos.
  • I have linked related issue(s); no changelog entry was added for this focused bug fix.

Summary by CodeRabbit

  • New Features

    • Companion audio probing: per-file media metadata (duration, sample rate, channels, audio presence) surfaced to IPC and editor (mediaInfoByPath).
    • Editor playback and UI: editor now consumes per-path media info, supports decoded-WAV vs media-element preview paths, waveform duration overrides, and partial-coverage visuals.
    • Waveform caching: cache key versioning for controlled invalidation.
  • Tests

    • Expanded coverage for companion probing, WAV decoding, waveform caching, timing/preview sync, and peak-cache behavior.

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Backend ffprobe probing now returns per-path mediaInfoByPath via IPC; client stores that map, decodes WAVs for peaks/preview when appropriate, uses probed durations in preview timing and sync (WebAudio or media-element), and renders duration-aware waveforms and richer source-audio tracks.

Changes

Companion Audio Probing & Preview Refactor

Layer / File(s) Summary
Backend audio probing contract and IPC
electron/electron-env.d.ts, electron/ipc/recording/diagnostics.ts, electron/ipc/register/recording.ts, electron/ipc/recording/diagnostics.test.ts, electron/ipc/register/recording.test.ts
Diagnostics probe candidate companion audio with ffprobe and return mediaInfoByPath; new resolveVideoAudioFallbackPathsForIpc centralizes IPC response (paths, startDelayMsByPath, mediaInfoByPath) and remembers approved local-read paths.
WAV decoder and waveform peak generation
src/components/video-editor/audio/waveform/wavDecoder.ts, src/components/video-editor/audio/waveform/wavDecoder.test.ts, src/components/video-editor/audio/waveform/WaveformGenerator.ts
Adds a WAV decoder returning per-channel Float32 samples; WaveformGenerator tries the decoder before audioContext and accepts cacheKeyVersion to alter peak cache keys for invalidation.
Audio metadata types and state tracking
src/components/video-editor/audio/audioTypes.ts, src/components/video-editor/audio/useSourceAudioFallback.ts, src/components/video-editor/audio/useVideoEditorAudio.ts, src/components/video-editor/VideoEditor.tsx
Introduces SourceAudioMediaInfo and expands track shapes; useSourceAudioFallback stores sourceAudioFallbackMediaInfoByPath from IPC; hooks forward the map to preview sync and TimelineEditor receives it.
Companion audio preview timing
src/lib/mediaTiming.ts, src/lib/mediaTiming.test.ts
New helpers compute companion preview timing and end-tolerance using probed durations and recorded start delays to decide target times and atEnd behavior.
Audio preview sync with dual-path playback
src/components/video-editor/audio/useAudioPreviewSync.ts, src/components/video-editor/audio/useAudioPreviewSync.test.ts
Refactors preview sync to support decoded-WAV WebAudio playback and media-element playback; exports deterministic resource keys, freshness checks, preview volume, decoded eligibility, and decoded-sync action selection; adds tests.
Timeline editor routing and track building
src/components/video-editor/timeline/TimelineEditor.tsx, src/components/video-editor/timeline/sourceAudioTracks.ts, src/components/video-editor/timeline/sourceAudioTracks.test.ts, src/components/video-editor/timeline/hooks/useTimelineAudioPeaks.ts, src/components/video-editor/timeline/hooks/useTimelineAudioPeaks.test.ts
TimelineEditor uses routing policies to pick sidecars; peak loading receives cacheKeyVersion derived from mediaInfo; buildTimelineSourceAudioTracks emits richer tracks with probedDurationMs and waveformCoverage; tests updated.
Waveform UI with duration override and coverage
src/components/video-editor/timeline/Item.tsx, src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx, src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx
Item and AudioWaveform accept audioDurationMs and waveformCoverage; AudioWaveform uses an effective duration override and draws guide lines for peaks beyond the effective duration; partial coverage overlay added.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested reviewers

  • webadderall

Poem

🐰 Hopped through WAVs and probes so neat,

Mapped each path, each duration, every beat,
Peaks decoded, previews hum in time,
The rabbit smiles — the waveform's in rhyme! 🎶

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.38% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing Windows microphone audio preservation during preview, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR directly addresses issue #602 by implementing probed duration metadata, WAV decoding for preview, resource versioning for stale-load prevention, and proper waveform coverage representation.
Out of Scope Changes check ✅ Passed All changes are scoped to addressing Windows microphone audio preview issues: companion audio probing, WAV decoding, resource management, and waveform generation—no unrelated modifications detected.
Description check ✅ Passed The PR description is comprehensive and well-structured, addressing purpose, motivation, change type, related issues, and testing guidance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx (1)

79-82: 💤 Low value

Optional: Simplify redundant safety check.

Lines 80-81 check (audioDurationMs ?? 0) > 0 then use Math.max(0, audioDurationMs ?? 0). Since the condition already ensures the value is positive, the Math.max(0, ...) wrapper is redundant.

♻️ Simplification
 	const effectiveDurationMs =
-		Number.isFinite(audioDurationMs) && (audioDurationMs ?? 0) > 0
-			? Math.max(0, audioDurationMs ?? 0)
+		Number.isFinite(audioDurationMs) && audioDurationMs! > 0
+			? audioDurationMs!
 			: peaksDurationMs;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx`
around lines 79 - 82, The effectiveDurationMs computation in AudioWaveform
redundantly wraps audioDurationMs with Math.max(0, ...) after already checking
it's > 0; simplify by returning the audioDurationMs (with the existing nullish
fallback) when Number.isFinite(audioDurationMs) && (audioDurationMs ?? 0) > 0,
otherwise fall back to peaksDurationMs. Update the effectiveDurationMs
assignment to use audioDurationMs ?? 0 directly in the true branch instead of
Math.max.
src/components/video-editor/timeline/sourceAudioTracks.ts (1)

48-55: 💤 Low value

Optional: Simplify redundant null check.

Line 53's !Number.isFinite(probedDurationMs) || probedDurationMs === null can be simplified to just !Number.isFinite(probedDurationMs) since Number.isFinite(null) already returns false.

♻️ Simplification
-	if (!Number.isFinite(probedDurationMs) || probedDurationMs === null) return "full";
+	if (!Number.isFinite(probedDurationMs)) return "full";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/video-editor/timeline/sourceAudioTracks.ts` around lines 48 -
55, The conditional in getWaveformCoverage redundantly checks probedDurationMs
=== null; replace the combined check `!Number.isFinite(probedDurationMs) ||
probedDurationMs === null` with just `!Number.isFinite(probedDurationMs)` so the
function still returns "full" when probedDurationMs is non-finite (including
null), keeping the rest of the logic (peaks null -> "none", duration comparison
-> "partial"/"full") unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/video-editor/audio/useAudioPreviewSync.test.ts`:
- Around line 150-182: The tests import and type-cast internal helpers
(isAudioResourceLoadCurrent, getSourceAudioPreviewVolume) from
useAudioPreviewSync, coupling tests to private implementation; fix by making the
contract explicit: either export these helpers from the module (export function
isAudioResourceLoadCurrent / getSourceAudioPreviewVolume) so tests can import
them directly, or move them into a new utility module (e.g.,
audioResourceUtils.ts) with proper exports and import those in both the
implementation and tests, or alternatively remove direct assertions and verify
the same behaviors via the public API of useAudioPreviewSync; choose one
approach and update imports/exports and test imports accordingly.
- Line 21: The test is asserting an internal key format by expecting "122100";
replace that with a behavioral assertion: remove the literal "122100" check on
the withProbe variable and instead assert behavior using the probe identifier or
outcome produced by the function under test (e.g., assert withProbe contains
probe.id or that the returned key resolves to the expected resource/data or is
non-empty). Locate the test file and update the expectation on the withProbe
variable (from useAudioPreviewSync.test.ts) so it asserts observable behavior
(contains probe.id, resolves to stored data, or similar) rather than the
internal formatted substring "122100".

In `@src/components/video-editor/audio/useAudioPreviewSync.ts`:
- Around line 890-901: The useEffect that calls ensureSourceAudioRunning() then
unconditionally .play()s every element (in useAudioPreviewSync.ts: the effect
watching isPlaying, resolvedSourceTracks.length, ensureSourceAudioRunning) can
restart companion tracks that the main sync logic intentionally paused via
beforeAudioStart/atEnd; modify this effect to honor the same gating: before
calling audio.play(), check the same conditions used by the main sync (e.g.,
beforeAudioStart and atEnd flags or whatever predicate the sync uses) for each
track, or alternatively remove the automatic play here and let the main sync
effect (the primary play/pause logic in useAudioPreviewSync) own all play/pause
transitions; ensure you reference sourceAudioElementsRef.current and only call
.play() on elements allowed by the gating to avoid starting delayed sidecars
early.

In `@src/components/video-editor/audio/waveform/wavDecoder.ts`:
- Around line 75-87: The validation currently allows any bitsPerSample for float
WAVs (audioFormat === 3) so 64-bit floats slip through and decode to silence;
update the checks in the WAV decoding validation (the block that computes
audioFormat, channelCount, sampleRate, bitsPerSample, dataSize and
bytesPerSample) to explicitly reject unsupported float widths by requiring
bitsPerSample === 32 when audioFormat === 3 (and still reject non-integer or <=0
bytesPerSample for PCM paths); make the same explicit check in the secondary
validation near the decodePcmSample/decodeFloatSample call sites (the region
referenced around lines 107-109) so 64-bit float WAVs return null instead of
being passed into decodePcmSample.

In `@src/lib/mediaTiming.test.ts`:
- Around line 96-108: The test call to resolveCompanionAudioPreviewTiming
unnecessarily casts the input object with "as never"; remove that cast so the
literal matches the function's declared param type (which already allows
probedAudioDurationSeconds?: number | null). Update the test in
mediaTiming.test.ts by deleting "as never" from the object passed to
resolveCompanionAudioPreviewTiming (the call with currentTimeSeconds,
timelineDurationSeconds, audioDurationSeconds, recordedStartDelayMs,
probedAudioDurationSeconds) so the test uses the correctly typed literal.

---

Nitpick comments:
In `@src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx`:
- Around line 79-82: The effectiveDurationMs computation in AudioWaveform
redundantly wraps audioDurationMs with Math.max(0, ...) after already checking
it's > 0; simplify by returning the audioDurationMs (with the existing nullish
fallback) when Number.isFinite(audioDurationMs) && (audioDurationMs ?? 0) > 0,
otherwise fall back to peaksDurationMs. Update the effectiveDurationMs
assignment to use audioDurationMs ?? 0 directly in the true branch instead of
Math.max.

In `@src/components/video-editor/timeline/sourceAudioTracks.ts`:
- Around line 48-55: The conditional in getWaveformCoverage redundantly checks
probedDurationMs === null; replace the combined check
`!Number.isFinite(probedDurationMs) || probedDurationMs === null` with just
`!Number.isFinite(probedDurationMs)` so the function still returns "full" when
probedDurationMs is non-finite (including null), keeping the rest of the logic
(peaks null -> "none", duration comparison -> "partial"/"full") unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 78ec3b2e-3b4d-4bae-9a5a-74b59ae4c934

📥 Commits

Reviewing files that changed from the base of the PR and between 52dd842 and 6413591.

📒 Files selected for processing (24)
  • electron/electron-env.d.ts
  • electron/ipc/recording/diagnostics.test.ts
  • electron/ipc/recording/diagnostics.ts
  • electron/ipc/register/recording.test.ts
  • electron/ipc/register/recording.ts
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/audio/audioTypes.ts
  • src/components/video-editor/audio/useAudioPreviewSync.test.ts
  • src/components/video-editor/audio/useAudioPreviewSync.ts
  • src/components/video-editor/audio/useSourceAudioFallback.ts
  • src/components/video-editor/audio/useVideoEditorAudio.ts
  • src/components/video-editor/audio/waveform/WaveformGenerator.ts
  • src/components/video-editor/audio/waveform/wavDecoder.test.ts
  • src/components/video-editor/audio/waveform/wavDecoder.ts
  • src/components/video-editor/timeline/Item.tsx
  • src/components/video-editor/timeline/TimelineEditor.tsx
  • src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx
  • src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx
  • src/components/video-editor/timeline/hooks/useTimelineAudioPeaks.test.ts
  • src/components/video-editor/timeline/hooks/useTimelineAudioPeaks.ts
  • src/components/video-editor/timeline/sourceAudioTracks.test.ts
  • src/components/video-editor/timeline/sourceAudioTracks.ts
  • src/lib/mediaTiming.test.ts
  • src/lib/mediaTiming.ts

Comment thread src/components/video-editor/audio/useAudioPreviewSync.test.ts Outdated
Comment thread src/components/video-editor/audio/useAudioPreviewSync.test.ts
Comment thread src/components/video-editor/audio/useAudioPreviewSync.ts Outdated
Comment thread src/components/video-editor/audio/waveform/wavDecoder.ts
Comment thread src/lib/mediaTiming.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/components/video-editor/audio/useAudioPreviewSync.ts (1)

490-497: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fallback when decodeWavAudioData() returns null for local WAV sidecars

decodeWavAudioData() returns null for unsupported WAV subformats, and src/components/video-editor/audio/waveform/WaveformGenerator.ts:64-103 already falls back to audioContext.decodeAudioData(arrayBuffer) in that case. In src/components/video-editor/audio/useAudioPreviewSync.ts:490-516, the same null is treated as a hard error (throw), so preview audio is lost even though the browser decode path could handle it.

Suggested fix
 							const file = await createReadableMediaResourceFile(audioPath);
 							const arrayBuffer = await file.arrayBuffer();
 							const decoded = decodeWavAudioData(arrayBuffer);
-							if (!decoded) {
-								throw new Error("Failed to decode companion WAV audio");
-							}
 
 							if (
 								!isAudioResourceLoadCurrent(
 									decodedSourceAudioResourcesRef.current,
@@
 								) {
 									return;
 								}
 
 							const context = ensureSourceAudioContext();
-							const buffer = createAudioBufferFromDecodedWav(context, decoded);
+							const buffer = decoded
+								? createAudioBufferFromDecodedWav(context, decoded)
+								: await context.decodeAudioData(arrayBuffer);
 							decodedSourceAudioBuffersRef.current.set(audioPath, {
 								resourceKey,
 								buffer,
 							});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/video-editor/audio/useAudioPreviewSync.ts` around lines 490 -
497, The code in the async block treats decodeWavAudioData(arrayBuffer)
returning null as a hard error and throws, which prevents using the browser
decoder fallback used elsewhere; instead, when decodeWavAudioData(...) returns
null, call the AudioContext.decodeAudioData(arrayBuffer) fallback (same approach
as in WaveformGenerator.ts) and use its result as decoded; only throw if both
decodeWavAudioData and audioContext.decodeAudioData fail. Update the block
around createReadableMediaResourceFile, decodeWavAudioData, and the async
decoding flow to attempt the fallback via
audioContext.decodeAudioData(arrayBuffer) and handle the returned AudioBuffer
before proceeding.
♻️ Duplicate comments (1)
src/components/video-editor/audio/useAudioPreviewSync.ts (1)

873-876: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid replaying a stale element after the async resume promise settles.

This still queues audio.play() behind ensureSourceAudioRunning(). If the user pauses or seeks out of range before that promise resolves, the older callback can restart a companion element that a newer sync pass already paused. The direct-element path is not routed through Web Audio, so it should not wait on the AudioContext at all here.

Suggested fix
 			if (shouldPlaySourceAudioElement({ isPlaying, beforeAudioStart, atEnd })) {
-				void ensureSourceAudioRunning().then(() => {
-					audio.play().catch(() => undefined);
-				});
+				audio.play().catch(() => undefined);
 			} else if (!audio.paused) {
 				audio.pause();
 			}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/video-editor/audio/useAudioPreviewSync.ts` around lines 873 -
876, The current code awaits ensureSourceAudioRunning() then calls audio.play(),
which can replay a stale element after the async promise resolves; instead, for
the direct-element path (when shouldPlaySourceAudioElement returns true) call
audio.play() synchronously without awaiting ensureSourceAudioRunning(), or if
you must keep the async call, capture a guard (e.g., a local syncId/compare
flag) before awaiting and re-check it after the promise to avoid restarting a
newer/paused element; update the block around
shouldPlaySourceAudioElement/ensureSourceAudioRunning/audio.play() to either
call audio.play() immediately or add a post-await validity check so only the
currently intended element is played.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/components/video-editor/audio/useAudioPreviewSync.ts`:
- Around line 490-497: The code in the async block treats
decodeWavAudioData(arrayBuffer) returning null as a hard error and throws, which
prevents using the browser decoder fallback used elsewhere; instead, when
decodeWavAudioData(...) returns null, call the
AudioContext.decodeAudioData(arrayBuffer) fallback (same approach as in
WaveformGenerator.ts) and use its result as decoded; only throw if both
decodeWavAudioData and audioContext.decodeAudioData fail. Update the block
around createReadableMediaResourceFile, decodeWavAudioData, and the async
decoding flow to attempt the fallback via
audioContext.decodeAudioData(arrayBuffer) and handle the returned AudioBuffer
before proceeding.

---

Duplicate comments:
In `@src/components/video-editor/audio/useAudioPreviewSync.ts`:
- Around line 873-876: The current code awaits ensureSourceAudioRunning() then
calls audio.play(), which can replay a stale element after the async promise
resolves; instead, for the direct-element path (when
shouldPlaySourceAudioElement returns true) call audio.play() synchronously
without awaiting ensureSourceAudioRunning(), or if you must keep the async call,
capture a guard (e.g., a local syncId/compare flag) before awaiting and re-check
it after the promise to avoid restarting a newer/paused element; update the
block around shouldPlaySourceAudioElement/ensureSourceAudioRunning/audio.play()
to either call audio.play() immediately or add a post-await validity check so
only the currently intended element is played.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5b6afe95-4b3a-4946-a52b-6c7725d5cee7

📥 Commits

Reviewing files that changed from the base of the PR and between 6413591 and d3de02a.

📒 Files selected for processing (7)
  • src/components/video-editor/audio/useAudioPreviewSync.test.ts
  • src/components/video-editor/audio/useAudioPreviewSync.ts
  • src/components/video-editor/audio/waveform/wavDecoder.test.ts
  • src/components/video-editor/audio/waveform/wavDecoder.ts
  • src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx
  • src/components/video-editor/timeline/sourceAudioTracks.ts
  • src/lib/mediaTiming.test.ts
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/lib/mediaTiming.test.ts
  • src/components/video-editor/timeline/components/waveform/AudioWaveform.tsx
  • src/components/video-editor/timeline/sourceAudioTracks.ts
  • src/components/video-editor/audio/waveform/wavDecoder.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Audio disappears during editing on Windows 11, but exported video has sound

1 participant