Skip to content

fix(windows): Fixed windows Export Issue and early decode Crash#423

Merged
siddharthvaddem merged 5 commits intosiddharthvaddem:mainfrom
org-cyber:fix/windows-export-clean
Apr 18, 2026
Merged

fix(windows): Fixed windows Export Issue and early decode Crash#423
siddharthvaddem merged 5 commits intosiddharthvaddem:mainfrom
org-cyber:fix/windows-export-clean

Conversation

@org-cyber
Copy link
Copy Markdown

@org-cyber org-cyber commented Apr 11, 2026

Fixes #428

Description

I fixed two problems that stopped exports from working on Windows:

Export not saving – The latest release was supposed to fix this issue on windows but it still didnt work. The file save dialog appeared, but no file was created. This happened because the file path wasn't formatted correctly for Windows. I added code to clean up the path and make sure the folder exists before writing the file.

Export stopping early – Sometimes exports would fail with a "Decode ended early" error before finishing. On Windows, I made the app log a warning instead of crashing, so the export can finish with the frames it already has. Other operating systems keep the strict check.

Motivation

Windows users couldn't reliably export their recordings. These changes make exports work as expected on Windows without affecting macOS or Linux.

Type of Change

  • Bug Fix

Related Issue(s)

None directly linked, but this addresses reports of export failures on Windows.

Screenshots / Video

No visual changes.

Testing

Recorded a short video and exported as MP4 on Windows 10 – file saved correctly.

Exported to folders with spaces in the name (like C:\My Videos) – worked fine.

Ran unit tests with npm test – 36 tests passed.

Checklist

I have performed a self-review of my code.

I have added any necessary screenshots or videos. (None needed)

I have linked related issue(s) and updated the changelog if applicable. (No issue linked)


Thank you for contributing!

Summary by CodeRabbit

  • Bug Fixes
    • More reliable video exports: file paths are normalized and missing parent directories are created so saves succeed consistently.
    • Improved decoding robustness: refined error handling reduces failed exports, especially on Windows where certain early-decode gaps are tolerated.
    • Reduced unnecessary UI updates: webcam size and certain region changes no longer trigger redundant snapshot or key-handler recomputations.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 34596892-d979-4ef8-bfc0-e053d6421660

📥 Commits

Reviewing files that changed from the base of the PR and between e4d4ce2 and 5caee9b.

📒 Files selected for processing (4)
  • electron/ipc/handlers.ts
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/timeline/TimelineEditor.tsx
  • src/lib/exporter/streamingDecoder.ts
💤 Files with no reviewable changes (2)
  • src/components/video-editor/timeline/TimelineEditor.tsx
  • src/components/video-editor/VideoEditor.tsx
✅ Files skipped from review due to trivial changes (1)
  • electron/ipc/handlers.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/exporter/streamingDecoder.ts

📝 Walkthrough

Walkthrough

Normalize and ensure export path exists before writing in the Electron IPC handler; adjust streaming decoder to allow a small, Windows-only tolerance for early-decode gaps when a last-decoded frame exists, emitting a warning instead of throwing; remove some snapshot/dependency triggers in the editor components.

Changes

Cohort / File(s) Summary
IPC Video Save Handler
electron/ipc/handlers.ts
Use path.normalize(result.filePath), fs.mkdir(path.dirname(normalizedPath), { recursive: true }) before fs.writeFile, and return normalizedPath in the IPC response. JSDoc added.
Streaming Decoder (Windows fallback)
src/lib/exporter/streamingDecoder.ts
Compute requiredEndSec via segments[segments.length - 1]?.endSec ?? 0; detect Windows and, when decode appears to end early, allow a Windows-only tolerance (min(3.0, requiredEndSec * 0.1)) to log a console.warn and continue if gap ≤ threshold and last frame exists; otherwise throw. JSDoc expanded.
Editor snapshot/deps
src/components/video-editor/VideoEditor.tsx, src/components/video-editor/timeline/TimelineEditor.tsx
Removed webcamSizePreset from currentProjectSnapshot dependencies/memo and removed blurRegions from keydown-effect deps so those changes no longer retrigger the memo/effect.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • siddharthvaddem

Poem

paths get normalized, dirs made on the fly,
windows shrugs, “small gap? let it slide,”
snapshots stop thrashing on tiny prop flips,
keys stop re-registering mid-sip,
bytes land where they belong — kinda cursed, lowkey wise.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Changes to VideoEditor.tsx and TimelineEditor.tsx removing dependency array entries appear unrelated to Windows export/decode issues. Clarify or separate the VideoEditor and TimelineEditor changes—they seem out of scope for a Windows export/decode fix.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main fix for Windows export functionality and early decode crashes, directly matching the core changes.
Description check ✅ Passed The description covers all required template sections including motivation, type of change, testing approach, and checklist completion.
Linked Issues check ✅ Passed Code changes directly address issue #428 requirements: path normalization fixes file saving on Windows, decode tolerance logic prevents premature termination.

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


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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/lib/exporter/streamingDecoder.ts (1)

508-516: Windows bypass is a bit too broad (lowkey risky for truly truncated exports)

Line 508 now downgrades all early-end failures to warn on Windows. That can mark heavily truncated decodes as successful exports. Consider tolerating only small gaps (known metadata-tail cases) and still failing on large gaps, or returning a partialExport signal.

nit: tighter guardrail without undoing the Windows fix
-			if (isWindows) {
+			const decodeGapSec =
+				lastDecodedFrameSec === null ? Number.POSITIVE_INFINITY : requiredEndSec - lastDecodedFrameSec;
+			const canProceedOnWindows = isWindows && decodeGapSec <= METADATA_TAIL_TOLERANCE_SEC;
+			if (canProceedOnWindows) {
 				console.warn(
 					`[StreamingVideoDecoder] Decode ended early on Windows at ${decodedAtLabel} (needed ${requiredEndSec.toFixed(3)}s) – proceeding anyway.`,
 				);
 				// Do not throw on Windows; allow export to complete with the frames we have.
 			} else {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/exporter/streamingDecoder.ts` around lines 508 - 516, The current
Windows-only bypass (isWindows) silences all early-end decode errors; change it
to only tolerate small known metadata-tail gaps by introducing a max tolerance
(e.g. maxToleranceSec) and comparing the missing duration (requiredEndSec -
decodedAtLabel) to that threshold: if gap <= maxToleranceSec then log the
warning and mark result as partialExport (or set a partialExport flag on the
decoder/export result), otherwise keep throwing the Error as before; update the
branch around isWindows, decodedAtLabel, and requiredEndSec and ensure callers
can handle the partialExport signal.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/lib/exporter/streamingDecoder.ts`:
- Around line 508-516: The current Windows-only bypass (isWindows) silences all
early-end decode errors; change it to only tolerate small known metadata-tail
gaps by introducing a max tolerance (e.g. maxToleranceSec) and comparing the
missing duration (requiredEndSec - decodedAtLabel) to that threshold: if gap <=
maxToleranceSec then log the warning and mark result as partialExport (or set a
partialExport flag on the decoder/export result), otherwise keep throwing the
Error as before; update the branch around isWindows, decodedAtLabel, and
requiredEndSec and ensure callers can handle the partialExport signal.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c57ada4-2cec-4210-90dd-08870724d3f4

📥 Commits

Reviewing files that changed from the base of the PR and between 68295b2 and 08aff31.

📒 Files selected for processing (2)
  • electron/ipc/handlers.ts
  • src/lib/exporter/streamingDecoder.ts

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 08aff31351

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/lib/exporter/streamingDecoder.ts Outdated
On Windows, tolerate small decode gaps (<=3 seconds) to work around driver quirks, allowing export to complete with available frames.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/exporter/streamingDecoder.ts`:
- Around line 513-519: The Windows-only 3s tolerance can silently succeed for
very short requested ranges; change the logic in StreamingVideoDecoder (the
isWindows / lastDecodedFrameSec / decodeGapSec branch inside decodeAll()) to use
a relative cap instead of a fixed 3s (e.g. allowedGap = min(3.0, requiredEndSec
* <small-fraction>) ) and if decodeGapSec > allowedGap return an explicit
partial-decode result (or error) rather than treating it as full success; update
decodeAll()’s return shape to include a partial flag/lastDecodedFrameSec and
adjust callers (videoExporter.ts and gifExporter.ts which await decodeAll()) to
surface a user-visible warning or handle the partial result instead of
proceeding to 100%.
- Around line 504-521: The decodeAll() flow uses requiredEndSec but never
declares it; add a local constant requiredEndSec immediately after the segments
declaration (where segments is created) that computes the end time of the last
segment or 0 if segments is empty (e.g., take segments[segments.length-1].end or
equivalent fallback). This ensures requiredEndSec is defined for the
shouldFailDecodeEndedEarly(...) call and later error message in
StreamingVideoDecoder.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1ba3f54d-f8db-4d65-8d0b-b458783c5ff2

📥 Commits

Reviewing files that changed from the base of the PR and between 08aff31 and 05da56f.

📒 Files selected for processing (2)
  • electron/ipc/handlers.ts
  • src/lib/exporter/streamingDecoder.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • electron/ipc/handlers.ts

Comment thread src/lib/exporter/streamingDecoder.ts Outdated
Comment thread src/lib/exporter/streamingDecoder.ts Outdated
Add requiredEndSec calculation to properly handle early decode termination by using the last segment's end time. This addresses issues with export processing on Windows platforms.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/exporter/streamingDecoder.ts`:
- Around line 504-526: The decodeAll method is missing its terminating brace
causing a syntax error and the subsequent computeSegments method to be nested
incorrectly; close the decodeAll method by adding a single `}` just after the
final if-block that handles early decode termination (the block that references
isWindows, lastDecodedFrameSec, and decodeGapSec) so that decodeAll ends before
the declaration of private computeSegments, and then reformat the surrounding
lines (within the StreamingVideoDecoder class) to use consistent indentation
(e.g., 2 or 4 spaces) to avoid mixed tabs/spaces.
- Around line 504-521: Add integration tests that exercise the Windows-specific
tolerance branch around isWindows in streamingDecoder.ts: create tests that mock
navigator.userAgent to a Windows string and invoke the code path where
shouldFailDecodeEndedEarly({... cancelled: this.cancelled, lastDecodedFrameSec,
requiredEndSec, streamDurationSec: this.metadata.streamDuration }) returns true,
then (1) for lastDecodedFrameSec set so decodeGapSec <= 3.0 assert the decoder
does not throw and that console.warn was called, (2) for lastDecodedFrameSec
null or decodeGapSec > 3.0 assert the decoder still throws, and (3) with a
non-Windows userAgent assert the decoder throws when
shouldFailDecodeEndedEarly() is true; use the same entry point used by the
integration tests (the StreamingVideoDecoder or the method that contains the
isWindows check) and ensure navigator.userAgent is reset after each test.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7f18fb4c-d4c2-45d6-a818-cbbcc0df6941

📥 Commits

Reviewing files that changed from the base of the PR and between 05da56f and d40f40d.

📒 Files selected for processing (1)
  • src/lib/exporter/streamingDecoder.ts

Comment thread src/lib/exporter/streamingDecoder.ts Outdated
Comment thread src/lib/exporter/streamingDecoder.ts Outdated
Add requiredEndSec calculation to properly handle early decode termination by using the last segment's end time. This addresses issues with export processing on Windows platforms.
@org-cyber org-cyber force-pushed the fix/windows-export-clean branch from d40f40d to e4d4ce2 Compare April 11, 2026 17:35
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
src/lib/exporter/streamingDecoder.ts (1)

252-256: ⚠️ Potential issue | 🟠 Major

Base the Windows tolerance on kept span, not absolute media time.

requiredEndSec is an absolute source timestamp, so a clip trimmed to the last 5s of a 60s recording still gets Math.min(3, 60 * 0.1) === 3 here. That means Windows can return success after missing most of the visible tail. Since src/lib/exporter/videoExporter.ts:180-230 treats decodeAll() returning as success, this can quietly ship a truncated export. lowkey safer to size the cap from the kept source span (or at least the final kept segment duration) instead of requiredEndSec.

💡 One way to size the tolerance from the kept span
@@
 const segments = this.splitBySpeed(
 	this.computeSegments(this.metadata.duration, trimRegions),
 	speedRegions,
 );
 const requiredEndSec = segments[segments.length - 1]?.endSec ?? 0;
+const keptSourceSpanSec = segments.reduce(
+	(total, segment) => total + (segment.endSec - segment.startSec),
+	0,
+);
@@
-const maxToleratedGap = Math.min(3.0, requiredEndSec * 0.1);
+const maxToleratedGap = Math.min(3.0, keptSourceSpanSec * 0.1);

Also applies to: 515-518

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/exporter/streamingDecoder.ts` around lines 252 - 256, The
Windows-tolerance cap is being computed from absolute media time (using
requiredEndSec derived after computeSegments and splitBySpeed), which makes the
tolerance too large for clips that only keep a short tail; change the logic to
compute the cap from the kept span length (e.g., the duration of the final kept
segment or total kept segments) instead of requiredEndSec. Locate where
requiredEndSec is computed (after this.splitBySpeed(this.computeSegments(...))
in streamingDecoder.ts) and replace the absolute-end usage with the kept-span
duration (finalSegment.endSec - finalSegment.startSec or sum of kept segment
durations), and apply the same fix to the analogous logic around lines 515-518
so decodeAll() success won’t silently accept a truncated tail.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lib/exporter/streamingDecoder.ts`:
- Line 225: The JSDoc for the parameter trimRegions is incorrect:
computeSegments treats trimRegions as spans to cut out (regions to discard), not
regions to keep; update the `@param` description for trimRegions in
streamingDecoder.ts (the computeSegments(...) JSDoc) to say these are time
ranges to remove/trim out (e.g., "Array of time regions to discard/trim out from
the input"), ensuring the doc matches the computeSegments implementation and any
mention elsewhere in that function.

---

Outside diff comments:
In `@src/lib/exporter/streamingDecoder.ts`:
- Around line 252-256: The Windows-tolerance cap is being computed from absolute
media time (using requiredEndSec derived after computeSegments and
splitBySpeed), which makes the tolerance too large for clips that only keep a
short tail; change the logic to compute the cap from the kept span length (e.g.,
the duration of the final kept segment or total kept segments) instead of
requiredEndSec. Locate where requiredEndSec is computed (after
this.splitBySpeed(this.computeSegments(...)) in streamingDecoder.ts) and replace
the absolute-end usage with the kept-span duration (finalSegment.endSec -
finalSegment.startSec or sum of kept segment durations), and apply the same fix
to the analogous logic around lines 515-518 so decodeAll() success won’t
silently accept a truncated tail.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 791ea455-e9fa-460b-a00c-1a05c5da0940

📥 Commits

Reviewing files that changed from the base of the PR and between d40f40d and e4d4ce2.

📒 Files selected for processing (1)
  • src/lib/exporter/streamingDecoder.ts

Comment thread src/lib/exporter/streamingDecoder.ts Outdated
@org-cyber org-cyber closed this Apr 11, 2026
@org-cyber org-cyber reopened this Apr 11, 2026
@org-cyber
Copy link
Copy Markdown
Author

The current latest build fixes the export saving isssue when the video being recorded is less that 4,500 frames, this PR fixes the premature decode timeout/termination issue on windows, all tests ran and passed. feel free to check out the pr in your free time or reach out

@org-cyber org-cyber changed the title fix(windows): normalize export save path and relax early decode end fix(windows): Fixed windows Export Issue and early decode Crash Apr 12, 2026
@siddharthvaddem
Copy link
Copy Markdown
Owner

fix ci issues 🙏

Address merge conflict markers added during resolution of Windows export fixes, ensuring clean integration of decode termination logic updates.
@org-cyber org-cyber force-pushed the fix/windows-export-clean branch from f4d6ce1 to 5caee9b Compare April 16, 2026 08:51
@org-cyber
Copy link
Copy Markdown
Author

org-cyber commented Apr 16, 2026

fix ci issues 🙏

Sorry for the stress, fixed the formatting and lint warnings. Ready for review

@org-cyber org-cyber closed this Apr 18, 2026
@siddharthvaddem
Copy link
Copy Markdown
Owner

did you mean to close this?

@org-cyber
Copy link
Copy Markdown
Author

did you mean to close this?

Yeah the CI is failing but it works perfectly, and all the tests pass, so uhhmm ill just use my version of the program, Dont want to add to your work. Really sorry for the stress and delay

@siddharthvaddem
Copy link
Copy Markdown
Owner

siddharthvaddem commented Apr 18, 2026

@org-cyber no worries, reopen it, i'll fix them in myself after merging it

@siddharthvaddem siddharthvaddem merged commit 57c6a59 into siddharthvaddem:main Apr 18, 2026
5 of 13 checks passed
@org-cyber
Copy link
Copy Markdown
Author

@org-cyber no worries, reopen it, i'll fix them in myself after merging it

Thankyou very much, i Appreciate it Alot

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Can't export video on windows

2 participants