Skip to content

Add dynamic webcam overlay dimensions#682

Open
surim0n wants to merge 1 commit into
webadderallorg:mainfrom
surim0n:codex/dynamic-webcam-overlay-shape
Open

Add dynamic webcam overlay dimensions#682
surim0n wants to merge 1 commit into
webadderallorg:mainfrom
surim0n:codex/dynamic-webcam-overlay-shape

Conversation

@surim0n

@surim0n surim0n commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces the single webcam size control with separate width and height controls, while falling back to the old size value for existing projects.
  • Removes the square lock from webcam crop editing and lets crop aspect drive the overlay height when width/height are still linked.
  • Updates live preview, canvas export, and the modern Pixi renderer to draw rectangular webcam overlays correctly.
  • Skips the native static-layout shortcut for rectangular/cropped webcam overlays so export falls back to the renderer that supports the shape.
  • Adds locale labels and focused tests for overlay math and native static-layout eligibility.

Verification

  • npx vitest --run src/components/video-editor/webcamOverlay.test.ts src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
  • npx vitest --run src/lib/exporter/frameRenderer.test.ts src/lib/exporter/modernFrameRenderer.test.ts src/components/video-editor/webcamOverlay.test.ts src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
  • npx tsc --noEmit --noUnusedLocals false --noUnusedParameters false
  • npx biome check src/components/video-editor/WebcamCropControl.tsx src/components/video-editor/webcamOverlay.ts src/components/video-editor/webcamOverlay.test.ts src/components/video-editor/types.ts src/components/video-editor/projectPersistence.ts src/lib/exporter/modernVideoExporter.ts src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts

Known existing check failures

  • npx tsc --noEmit fails on existing unused code in src/components/video-editor/videoPlayback/zoomRegionUtils.ts.
  • npm run i18n:check fails on existing missing/extra locale keys unrelated to these new webcam labels.
  • npm test has one unrelated failure in electron/ipc/paths/binaries.test.ts around Windows helper path resolution; the focused renderer/webcam tests pass.

Summary by CodeRabbit

Bug Fixes

  • Fixed webcam overlay sizing to use consistent defaults across all export modes
  • Improved handling of invalid webcam dimensions in native static-layout exports

Tests

  • Added validation test for non-finite webcam overlay dimensions

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Replaces hardcoded 50 fallback values and fills missing non-finite guards with DEFAULT_WEBCAM_SIZE across project persistence normalization (normalizeProjectEditor), both frame renderers (frameRenderer.ts, modernFrameRenderer.ts), and native static-layout webcam shape validation in modernVideoExporter.ts. A new test covers the non-finite rejection path.

Changes

Non-finite Webcam Dimension Handling

Layer / File(s) Summary
Persistence: normalizedWebcamSize prefers width over size
src/components/video-editor/projectPersistence.ts
Computes normalizedWebcamSize by clamping webcam.width if finite, then webcam.size if finite, then DEFAULT_WEBCAM_SIZE; returned webcam.size uses this value instead of directly clamping webcam.size.
Frame renderers: DEFAULT_WEBCAM_SIZE fallbacks replace hardcoded 50
src/lib/exporter/frameRenderer.ts, src/lib/exporter/modernFrameRenderer.ts
Both renderers import DEFAULT_WEBCAM_SIZE; frameRenderer.ts substitutes it for the prior hardcoded 50 in widthPercent and getCropMatchedWebcamHeightPercent. modernFrameRenderer.ts refactors updateWebcamOverlay to use per-axis webcam.width ?? webcam.size ?? DEFAULT_WEBCAM_SIZE and webcam.height ?? webcam.size ?? DEFAULT_WEBCAM_SIZE, with cropMatchRegion set to null when source dimensions are unavailable.
Native static-layout guard: reject non-finite webcam dimensions
src/lib/exporter/modernVideoExporter.ts, src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
hasUnsupportedNativeStaticLayoutWebcamShape now immediately rejects non-finite size/width/height values and derives effective dimensions via finite-guarded DEFAULT_WEBCAM_SIZE fallbacks. New test asserts getNativeStaticLayoutSkipReason returns "unsupported-rectangular-webcam-overlay" for Number.NaN inputs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • webadderallorg/Recordly#394: Both PRs modify webcam overlay geometry in frameRenderer.ts/modernFrameRenderer.ts — this PR changes size fallbacks and non-finite handling; the other changes how webcam.cropRegion is applied via getWebcamCropSourceRect.
  • webadderallorg/Recordly#624: Related through webcam overlay cache and render assertions in modernFrameRenderer.test.ts that would be affected by the updateWebcamOverlay refactor in this PR.
  • webadderallorg/Recordly#646: Both PRs modify frameRenderer.ts webcam overlay logic — this PR changes the size fallback inputs; the other updates cached frame refresh decisions based on webcam target time.

Poem

🐇 A webcam once grew wild and wide,
With NaN values lurking inside.
I clamped every side — width, height, and size —
No infinite frames to surprise!
Now DEFAULT_WEBCAM_SIZE guides the way,
And finite overlays are here to stay. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
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 (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add dynamic webcam overlay dimensions' accurately captures the primary change: replacing fixed webcam size with flexible width/height controls.
Description check ✅ Passed The PR description covers motivation, changes made, verification steps, and known issues. All required template sections are either present or reasonably addressed in the summary.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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.

@surim0n surim0n force-pushed the codex/dynamic-webcam-overlay-shape branch from 1b2260a to f58576d Compare June 20, 2026 15:26
@surim0n surim0n marked this pull request as ready for review June 20, 2026 15:26

@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

🤖 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/projectPersistence.ts`:
- Around line 1030-1040: The size property at line 1030 can diverge from the
width property (lines 1031-1035) when persisted data has webcam.width but no
webcam.size, causing size to default while width gets restored from the data. To
fix this, update the size property to follow the same fallback logic as width:
first check if webcam.width is a finite number and clamp it, then fall back to
checking webcam.size, and finally default to DEFAULT_WEBCAM_SIZE. This ensures
the size and width properties remain synchronized and consistent regardless of
which properties exist in the persisted data.

In `@src/components/video-editor/SettingsPanel.tsx`:
- Around line 3920-3933: In the onCropChange callback within SettingsPanel.tsx,
the call to getCropMatchedWebcamHeightPercent is passing webcamWidth as both the
first and second parameters. The function expects the first parameter to be
widthPercent and the second parameter to be heightPercent. Replace the second
parameter (currently webcamWidth) with webcamHeight to ensure correct height
calculations when the crop region changes.

In `@src/lib/exporter/frameRenderer.ts`:
- Around line 2500-2503: The hardcoded fallback values of 50 in the
frameRenderer.ts file for widthPercent and heightPercent calculations do not
align with the playback defaults which use DEFAULT_WEBCAM_SIZE set to 40,
causing size mismatches for legacy webcam settings. Import DEFAULT_WEBCAM_SIZE
from src/components/video-editor/types.ts and replace both instances of the 50
fallback values (in the widthPercent assignment and in the heightPercent
parameter passed to getCropMatchedWebcamHeightPercent) with DEFAULT_WEBCAM_SIZE
to ensure consistency between preview and export rendering.

In `@src/lib/exporter/modernFrameRenderer.ts`:
- Around line 2919-2925: The call to getCropMatchedWebcamHeightPercent is
double-applying the crop aspect because renderableWebcamSource dimensions are
already crop-trimmed in the cache-backed path for non-default crops, yet the
webcam.cropRegion is still being passed as a parameter. To fix this,
conditionally pass the cropRegion parameter only when renderableWebcamSource has
not already been crop-trimmed, or pass null/undefined for the cropRegion
argument when the source dimensions are already cropped. This ensures the crop
aspect is only applied once during the heightPercent computation.

In `@src/lib/exporter/modernVideoExporter.ts`:
- Around line 1505-1507: The nullish coalescing operator at lines 1505 and 1506
does not filter out NaN values, so width and height variables can remain
non-finite. This causes Math.abs(width - height) at line 1507 to potentially
return NaN, which makes the comparison NaN > 0.001 evaluate to false and
incorrectly bypasses the unsupported-rectangular-webcam-overlay guard for
invalid persisted values. Add validation using isFinite() on the width and
height variables to ensure they are valid finite numbers before performing the
Math.abs comparison in the return statement.
🪄 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: c107421f-048b-4464-8a0f-e07fb5a4cd12

📥 Commits

Reviewing files that changed from the base of the PR and between 952d63d and f58576d.

📒 Files selected for processing (22)
  • src/components/video-editor/SettingsPanel.tsx
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/VideoPlayback.tsx
  • src/components/video-editor/WebcamCropControl.tsx
  • src/components/video-editor/projectPersistence.ts
  • src/components/video-editor/types.ts
  • src/components/video-editor/webcamOverlay.test.ts
  • src/components/video-editor/webcamOverlay.ts
  • src/i18n/locales/en/settings.json
  • src/i18n/locales/es/settings.json
  • src/i18n/locales/fr/settings.json
  • src/i18n/locales/it/settings.json
  • src/i18n/locales/ko/settings.json
  • src/i18n/locales/nl/settings.json
  • src/i18n/locales/pt-BR/settings.json
  • src/i18n/locales/ru/settings.json
  • src/i18n/locales/zh-CN/settings.json
  • src/i18n/locales/zh-TW/settings.json
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/modernFrameRenderer.ts
  • src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
  • src/lib/exporter/modernVideoExporter.ts

Comment thread src/components/video-editor/projectPersistence.ts Outdated
Comment thread src/components/video-editor/SettingsPanel.tsx
Comment thread src/lib/exporter/frameRenderer.ts Outdated
Comment thread src/lib/exporter/modernFrameRenderer.ts
Comment thread src/lib/exporter/modernVideoExporter.ts Outdated
@surim0n surim0n force-pushed the codex/dynamic-webcam-overlay-shape branch from f58576d to e8eb226 Compare June 20, 2026 15:41
@surim0n surim0n force-pushed the codex/dynamic-webcam-overlay-shape branch from e8eb226 to 9567b9c Compare June 22, 2026 08:40

@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.

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

2048-2048: 🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Use the shared webcam default constant in native static-layout size fallback.

Line 2048 still uses a literal 40; switching to DEFAULT_WEBCAM_SIZE keeps this path consistent with normalized/renderer defaults and avoids future drift.

Suggested change
 		const rawSize = getWebcamOverlaySizePx({
 			containerWidth: this.config.width,
 			containerHeight: this.config.height,
-			sizePercent: webcam.width ?? webcam.size ?? 40,
+			sizePercent: webcam.width ?? webcam.size ?? DEFAULT_WEBCAM_SIZE,
 			margin,
 			zoomScale: 1,
 			reactToZoom: webcam.reactToZoom ?? true,
 		});
🤖 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/lib/exporter/modernVideoExporter.ts` at line 2048, Replace the hardcoded
literal value 40 with the DEFAULT_WEBCAM_SIZE constant in the sizePercent
property fallback. Locate the line containing sizePercent: webcam.width ??
webcam.size ?? 40 and change the final 40 to DEFAULT_WEBCAM_SIZE to maintain
consistency with the normalized and renderer defaults throughout the codebase.
🤖 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.

Nitpick comments:
In `@src/lib/exporter/modernVideoExporter.ts`:
- Line 2048: Replace the hardcoded literal value 40 with the DEFAULT_WEBCAM_SIZE
constant in the sizePercent property fallback. Locate the line containing
sizePercent: webcam.width ?? webcam.size ?? 40 and change the final 40 to
DEFAULT_WEBCAM_SIZE to maintain consistency with the normalized and renderer
defaults throughout the codebase.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fb536aa7-72f9-4fcf-a33c-0db6567a0e5d

📥 Commits

Reviewing files that changed from the base of the PR and between e8eb226 and 9567b9c.

📒 Files selected for processing (5)
  • src/components/video-editor/projectPersistence.ts
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/modernFrameRenderer.ts
  • src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
  • src/lib/exporter/modernVideoExporter.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.

1 participant