Skip to content

Creator workflow suite: greenscreen facecam pipeline, scene styles, and recording reliability fixes#676

Open
justmaiko12 wants to merge 45 commits into
webadderallorg:mainfrom
justmaiko12:feature/creator-workflow-suite
Open

Creator workflow suite: greenscreen facecam pipeline, scene styles, and recording reliability fixes#676
justmaiko12 wants to merge 45 commits into
webadderallorg:mainfrom
justmaiko12:feature/creator-workflow-suite

Conversation

@justmaiko12

Copy link
Copy Markdown

Summary

A creator-workflow feature suite built and battle-tested while producing real facecam-over-screen content (courses, presentations, demos) with a green screen and an iPhone Continuity Camera. It contains two halves:

  1. Recording reliability fixes that affect every user (root-caused, not patched)
  2. Creator features: a full facecam greenscreen pipeline and per-segment "scene styles"

Everything renders identically in the editor preview and both exporters, persists with projects (older project files open unchanged), and degrades gracefully (no WebGL → raw webcam; missing assets → sensible fallbacks).

I'm happy to split this into smaller PRs per feature if that's easier to review — say the word and I'll carve it up.


Bug fixes (likely the easiest wins)

Webcam frame gaps from camera device renegotiation

Recordings could contain multi-second frozen-facecam gaps (we measured 24s missing from a 72s clip via ffprobe). Root cause: the floating preview and the recorder each held their own getUserMedia with different constraints; any consumer churn (HUD compact transition, popover open/close) made Chromium restart the physical camera, and slow-renegotiation devices (iPhone Continuity Camera) stall 3–12s while the recorder's track receives no frames.

Fix: a refcounted shared webcam session (src/lib/webcamSession.ts) — one getUserMedia per device; the preview attaches to it and the recorder records a cloned track, so the device never restarts mid-session. Also: dead-stream self-healing (ended tracks are never reused — Continuity Camera disconnects recover on reselect) and a [webcam-watchdog] that logs track mute/unmute with timestamps so future stalls leave evidence. Verified: post-fix recordings show 0 frame gaps.

HUD invisible over fullscreen apps (macOS)

The HUD overlay never opted into fullscreen Spaces, so it vanished when presenting. Fixed with setVisibleOnAllWorkspaces(visibleOnFullScreen) + screen-saver window level, matching the update-toast window's existing pattern.

Notch black-bar auto-crop

Fullscreen apps on notched MacBooks render the menu-bar band pure black, which screen captures faithfully record. Fresh recordings are now sampled (3 frames, conservative thresholds — dark themes/black slides are never falsely detected; unit-tested) and the bars cropped automatically.

Creator features

Facecam greenscreen pipeline (WebGL2)

Chroma key with eyedropper + auto key-color detection (samples the frame border for the dominant screen color — real screens shift far from pure green under lighting), edge softness, fixed spill suppression, and background-image compositing. Garbage matte with box or bezier pen mask (insert-on-path, smooth/corner toggling, mirrored handles, fullscreen editor dialog) and feather. Facecam color controls (brightness/contrast/highlights/shadows) applied to the keyed foreground. The per-pixel math lives in a pure, unit-tested module (chromaKeyMath.ts) that the shader mirrors exactly.

Scene styles: per-segment fill-frame ("Fullscreen") regions

Time ranges where the recording covers the full canvas edge-to-edge (presentation mode) vs the framed look (demo mode), with an animated transition between the two layouts using the existing easing. Controlled by a timeline track, ⌥+. / ⌥+, editor shortcuts, header toggle buttons — and the same hotkeys during recording, persisted as a sidecar event file and imported as pre-split segments on project open (mirrors the webcam-layout-events pattern). Zooms are automatically suppressed inside fullscreen segments. "Remove background" now rides this system (cover-crop at the project aspect) instead of switching to native aspect.

Editor ergonomics

Facecam FPS preference (24/30/60), instant preview updates for webcam setting changes, marquee multi-select with batch delete on the timeline, condensed track rows, teleprompter auto-close when recording stops, background image no longer mirrored by "Mirror webcam".

Testing

  • ~120 new unit tests (key/matte/color math, mask path geometry, session manager semantics, fill-frame regions/persistence, black-bar detection, marquee selection); suite at 1028 passing
  • tsc --noEmit and biome clean on all touched files
  • Manually verified end-to-end on macOS (Apple Silicon): record with hotkeys → edit → export, including Continuity Camera disconnect/reconnect scenarios

🤖 Generated with Claude Code

justmaiko12 and others added 30 commits June 10, 2026 23:30
On macOS, when recording mic-only (no system audio), the native helper writes
mic audio both into the video's inline track and a .mic sidecar. The preview
was playing both sources simultaneously, causing an audible echo. Mute the
embedded preview whenever sidecar tracks exist but the video path was not
listed as a distinct audio source (hasEmbeddedSourceAudio === false).
Export behavior (includeEmbeddedInExport) is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… from persisted snapshots

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… reason

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ording, Alt+/ hotkey, teleprompter camera-full highlight

- persistWebcamLayoutEvents no longer clears the session on first write:
  finalize runs for both the screen and webcam output files, and the events
  were landing only next to the webcam video where the editor never looks
- the floating webcam self-view now hides while recording/finalizing: the HUD
  window shrinks to a 160px strip then, which clipped the preview to a sliver
- camera layout hotkey moved from Alt+F10 to Alt+/ and shown in the tooltip
- the teleprompter shows a blue border while camera-full mode is active

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…state

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- DEFAULT_SHORTCUTS.splitClip changed from { key: "c" } to { key: "b" }
- Updated TimelineCanvas hint text from "Press C to split clip" to "Press B to split clip" (literal; keyShortcuts config does not flow to TimelineCanvas as a prop, so dynamic rendering was disproportionate)
- Updated toolbar.splitClip tooltip label from "(C)" to "(B)" across all 10 i18n locales
- Added src/lib/shortcuts.test.ts with TDD-first test; saved user configs override the default

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Added magnetEnabled: boolean to ProjectEditorState with normalizeProjectEditor default true
- Added TDD tests in projectPersistence.webcamLayout.test.ts (fail-first: 4 tests failing before implementation)
- VideoEditor: useState + setMagnetEnabled in project open path (next to webcamLayout setters) + buildPersistedEditorState type + currentPersistedEditorState memo + deps
- Toolbar: Magnet icon (from @phosphor-icons/react, same library as Scissors) placed next to split button; text-blue-400 when ON, text-muted-foreground when OFF
- Added editor.toolbar.magnetOn / magnetOff i18n keys across all 10 locales

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
justmaiko12 and others added 11 commits June 10, 2026 23:38
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When the magnet is off, playback entering a trim region no longer seeks
past it: a wall-clock driver pauses the media element and advances the
playhead in real time while a black overlay covers the preview frame.
requestVideoFrameCallback does not fire on a paused element (and the
normal scheduler early-returns when paused), so the driver runs its own
requestAnimationFrame loop. User pause freezes the wall clock retaining
progress; user seeks cancel the driver (restarting it when scrubbing
into a gap while playing). togglePlayPause/handleSeek now treat the
editor's isPlaying state as authoritative because the gap driver keeps
the element paused while logically playing. Magnet-on behavior is
unchanged (guarded trim skip).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When magnetEnabled, VideoEditor maps all data passed to TimelineEditor
into display space (inter-clip gaps collapsed, clips packed from 0) and
reverse-maps every callback before the existing handlers run. The
timeline package itself is untouched; magnet-off passes the original
references through.

Playhead findings: the call site already passed playheadTime =
mapSourceTimeToTimelineTime(currentTime) (timeline space), and clip /
zoom / audio spans are timeline space too, so the existing contract was
internally consistent. Annotation and camera regions, however, are
SOURCE space (preview filters them against the video element's
currentTime) while being drawn on the timeline ruler at raw startMs —
an existing inconsistency that only diverges when speed clips exist.
It is preserved: their display mapping goes through source-space
conversion (regionToDisplay/spanToSource) so preview semantics are
unchanged, while zoom/audio use the timeline-space variants.

Clip edge/body edits cannot be expressed in the collapsed display, so
clip span changes are intercepted with a toast (i18n key
editor.timeline.magnetClipEdit in all 10 locales); selection and
delete still work, and deletes ripple naturally because the display
recomputes from the remaining clips.

Known limitation: timelineModel derives the waveform sourceSpan from
clip.startMs internally and ignores extra fields, so source-audio
waveform segments for clips after a collapsed gap sample a shifted
source offset while the magnet is on (display-only artifact).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… magnet toggle

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…and click-emitted clip span changes

- Timeline: render the camera row above the zoom row (clip > source-audio >
  camera > zoom > annotations > audio); row ids are stable so nothing
  index-based changes.
- Camera-full fill: the crop panel always stores pixel-square bubble crops,
  so cover-fitting them into a 16:9 frame discarded ~44% of the crop height
  and over-zoomed the face. Add expandRectToAspect and expand the crop to the
  output frame aspect (centered, clamped) in both the preview fill branch and
  the exporter frame cache so fill barely crops and preview matches export.
- Settings panel: hide bubble-only webcam controls (size, position grid,
  custom position sliders, margin) while the playhead is inside a camera-full
  segment, and also hide roundness/shadow when the fullscreen style is fill;
  show a localized hint in their place (key added to all 10 locales).
- Timeline dnd: selection clicks ran full drag/resize cycles (no sensor
  activation constraint) and committed unchanged spans, which fired the
  magnet-on "Turn the magnet off to adjust clip edges" toast when merely
  selecting a clip before deleting it. Skip zero-delta gestures and gestures
  that resolve back to the item's current placement (isNoOpSpanCommit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Camera-full "Fill screen" segments exported as a shrunken, pillarboxed
camera square over the wallpaper instead of covering the frame, even
though the preview rendered fill correctly.

Root cause: the fill style expands the pixel-square bubble crop cache
to the output frame aspect mid-export, recreating the webcam frame
cache canvas at new dimensions. ensureWebcamSprite swapped the new
canvas into the existing texture via webcamTextureSource.resource +
update(). Pixi resizes the Texture, but sprites only forward texture
"update" events for dynamic textures (pixi.js Sprite "set texture":
value.on("update", ...) is gated on value.dynamic, and Texture.from()
textures are not dynamic), so the sprite's batched quad kept the stale
square dimensions while applyCoverLayoutToSprite computed the cover
scale for the expanded ones — e.g. a 720x720 quad scaled by 1.125
renders an 810x810 centered square in a 1440x810 export.

Track the source dimensions behind the webcam texture and replace the
sprite texture (replaceSpriteTexture) whenever they change, so the
sprite re-reads its dimensions through the texture setter. Same-size
refreshes keep the cheap in-place resource swap.

Verified end-to-end with a smoke export of a square-crop fill project:
the camera now covers the frame edge to edge during camera-full fill
segments, and bubble segments before/after the segment still render
correctly. Adds a renderer test covering the decoded-source bubble->
fill transition and an exporter test asserting webcamLayoutStyle /
webcamLayoutRegions forward into the frame renderer construction.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Facecam chroma key with eyedropper + auto key-color detection, edge
  softness, spill suppression, background image compositing (preview +
  both exporters, pixel-identical)
- Garbage matte: box + bezier pen mask with feather and fullscreen editor
- Facecam color controls (brightness/contrast/highlights/shadows)
- Scene styles: fill-frame (fullscreen) segments with animated nested-rect
  transitions, Alt+./Alt+, hotkeys in editor and during recording, header
  toggle buttons, recording sidecar import, zoom suppression inside
  fullscreen segments, 'Remove background' now rides the same system
- Shared webcam session manager: fixes multi-second Continuity Camera
  frame gaps from device renegotiation; self-heals dead streams; watchdog
- Facecam FPS preference (24/30/60, default 30); HUD visible over
  fullscreen apps; auto-crop of notch black bars on fresh recordings
- Instant preview updates (no more nudging the crop to refresh)
- Timeline: condensed rows, marquee multi-select with batch delete,
  camera double-click affordance removed
- Teleprompter auto-closes when recording stops

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 160 files, which is 10 over the limit of 150.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 10e1d4fe-5b36-4fab-88ad-2d3b7bd40360

📥 Commits

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

📒 Files selected for processing (160)
  • README.md
  • docs/superpowers/plans/2026-06-10-camera-layout-switch.md
  • docs/superpowers/plans/2026-06-10-camera-track-and-style.md
  • docs/superpowers/plans/2026-06-10-hidden-teleprompter.md
  • docs/superpowers/plans/2026-06-10-teleprompter-camera-background.md
  • docs/superpowers/plans/2026-06-10-timeline-magnet-and-gaps.md
  • docs/superpowers/plans/2026-06-10-webcam-presets-and-flicker.md
  • docs/superpowers/plans/2026-06-11-fill-frame-scene-styles.md
  • docs/superpowers/plans/2026-06-11-greenscreen-pipeline.md
  • docs/superpowers/specs/2026-06-10-camera-layout-switch-design.md
  • docs/superpowers/specs/2026-06-10-camera-track-and-style-design.md
  • docs/superpowers/specs/2026-06-10-hidden-teleprompter-design.md
  • docs/superpowers/specs/2026-06-10-teleprompter-camera-background-design.md
  • docs/superpowers/specs/2026-06-10-timeline-magnet-and-gaps-design.md
  • docs/superpowers/specs/2026-06-10-webcam-presets-and-flicker-design.md
  • docs/superpowers/specs/2026-06-11-greenscreen-and-scene-styles-design.md
  • electron/electron-env.d.ts
  • electron/ipc/recording/mac.ts
  • electron/ipc/recording/prune.ts
  • electron/ipc/recording/sceneStyleEvents.test.ts
  • electron/ipc/recording/sceneStyleEvents.ts
  • electron/ipc/recording/webcamLayoutEvents.test.ts
  • electron/ipc/recording/webcamLayoutEvents.ts
  • electron/ipc/register/export.ts
  • electron/ipc/register/recording.ts
  • electron/ipc/register/settings.ts
  • electron/main.ts
  • electron/preload.ts
  • electron/teleprompterBounds.test.ts
  • electron/teleprompterBounds.ts
  • electron/teleprompterShortcuts.ts
  • electron/windows.ts
  • src/App.tsx
  • src/components/launch/LaunchWindow.tsx
  • src/components/launch/RecordingControls.tsx
  • src/components/launch/hooks/useWebcamPreviewOverlay.ts
  • src/components/launch/popovers/MorePopover.tsx
  • src/components/launch/popovers/WebcamPopover.tsx
  • src/components/teleprompter/Teleprompter.tsx
  • src/components/teleprompter/teleprompterCamera.test.ts
  • src/components/teleprompter/teleprompterCamera.ts
  • src/components/teleprompter/teleprompterScroll.test.ts
  • src/components/teleprompter/teleprompterScroll.ts
  • src/components/video-editor/ExportSettingsMenu.tsx
  • src/components/video-editor/SettingsPanel.tsx
  • src/components/video-editor/VideoEditor.tsx
  • src/components/video-editor/VideoPlayback.tsx
  • src/components/video-editor/WebcamKeyColorPicker.tsx
  • src/components/video-editor/WebcamMaskEditorDialog.tsx
  • src/components/video-editor/WebcamMaskPenEditor.tsx
  • src/components/video-editor/editorPreferences.test.ts
  • src/components/video-editor/editorPreferences.ts
  • src/components/video-editor/exportStartSettings.test.ts
  • src/components/video-editor/exportStartSettings.ts
  • src/components/video-editor/fillFrameRegions.test.ts
  • src/components/video-editor/fillFrameRegions.ts
  • src/components/video-editor/projectPersistence.fillFrame.test.ts
  • src/components/video-editor/projectPersistence.ts
  • src/components/video-editor/projectPersistence.webcamLayout.test.ts
  • src/components/video-editor/projectPersistence.webcamProcessing.test.ts
  • src/components/video-editor/timeline/Item.tsx
  • src/components/video-editor/timeline/ItemGlass.module.css
  • src/components/video-editor/timeline/Row.tsx
  • src/components/video-editor/timeline/TimelineEditor.tsx
  • src/components/video-editor/timeline/components/axis/TimelineAxis.tsx
  • src/components/video-editor/timeline/components/viewport/TimelineCanvas.tsx
  • src/components/video-editor/timeline/components/wrapper/TimelineWrapper.tsx
  • src/components/video-editor/timeline/core/constants.ts
  • src/components/video-editor/timeline/core/timelineTypes.ts
  • src/components/video-editor/timeline/dnd/engine.test.ts
  • src/components/video-editor/timeline/dnd/engine.ts
  • src/components/video-editor/timeline/hooks/useTimelineDndBindings.ts
  • src/components/video-editor/timeline/hooks/useTimelineEditorRuntime.ts
  • src/components/video-editor/timeline/hooks/useTimelineKeyboardShortcuts.ts
  • src/components/video-editor/timeline/hooks/useTimelineSelection.ts
  • src/components/video-editor/timeline/hooks/utils/timelineMarqueeUtils.test.ts
  • src/components/video-editor/timeline/hooks/utils/timelineMarqueeUtils.ts
  • src/components/video-editor/timeline/hooks/utils/timelineSelectionUtils.test.ts
  • src/components/video-editor/timeline/hooks/utils/timelineSelectionUtils.ts
  • src/components/video-editor/timeline/model/timelineModel.test.ts
  • src/components/video-editor/timeline/model/timelineModel.ts
  • src/components/video-editor/timeline/timelineLayout.test.ts
  • src/components/video-editor/timeline/timelineLayout.ts
  • src/components/video-editor/timelineDisplayMapping.test.ts
  • src/components/video-editor/timelineDisplayMapping.ts
  • src/components/video-editor/types.ts
  • src/components/video-editor/videoPlayback/layoutUtils.test.ts
  • src/components/video-editor/videoPlayback/layoutUtils.ts
  • src/components/video-editor/videoPlayback/useProcessedWebcamPreview.ts
  • src/components/video-editor/videoPlayback/videoEventHandlers.test.ts
  • src/components/video-editor/videoPlayback/videoEventHandlers.ts
  • src/components/video-editor/videoPlayback/zoomRegionUtils.ts
  • src/components/video-editor/webcamLayoutRegions.test.ts
  • src/components/video-editor/webcamLayoutRegions.ts
  • src/components/video-editor/webcamOverlay.ts
  • src/components/video-editor/webcamSettingsFields.test.ts
  • src/components/video-editor/webcamSettingsFields.ts
  • src/hooks/useScreenRecorder.test.ts
  • src/hooks/useScreenRecorder.ts
  • src/i18n/locales/en/editor.json
  • src/i18n/locales/en/launch.json
  • src/i18n/locales/en/settings.json
  • src/i18n/locales/es/editor.json
  • src/i18n/locales/es/launch.json
  • src/i18n/locales/es/settings.json
  • src/i18n/locales/fr/editor.json
  • src/i18n/locales/fr/launch.json
  • src/i18n/locales/fr/settings.json
  • src/i18n/locales/it/editor.json
  • src/i18n/locales/it/launch.json
  • src/i18n/locales/it/settings.json
  • src/i18n/locales/ko/editor.json
  • src/i18n/locales/ko/launch.json
  • src/i18n/locales/ko/settings.json
  • src/i18n/locales/nl/editor.json
  • src/i18n/locales/nl/launch.json
  • src/i18n/locales/nl/settings.json
  • src/i18n/locales/pt-BR/editor.json
  • src/i18n/locales/pt-BR/launch.json
  • src/i18n/locales/pt-BR/settings.json
  • src/i18n/locales/ru/editor.json
  • src/i18n/locales/ru/launch.json
  • src/i18n/locales/ru/settings.json
  • src/i18n/locales/zh-CN/editor.json
  • src/i18n/locales/zh-CN/launch.json
  • src/i18n/locales/zh-CN/settings.json
  • src/i18n/locales/zh-TW/editor.json
  • src/i18n/locales/zh-TW/launch.json
  • src/i18n/locales/zh-TW/settings.json
  • src/lib/blackBarDetection.test.ts
  • src/lib/blackBarDetection.ts
  • src/lib/exporter/audioEncoder.test.ts
  • src/lib/exporter/audioEncoder.ts
  • src/lib/exporter/audioRoutingEngine.ts
  • src/lib/exporter/exportBitrate.test.ts
  • src/lib/exporter/exportBitrate.ts
  • src/lib/exporter/frameRenderer.ts
  • src/lib/exporter/modernFrameRenderer.test.ts
  • src/lib/exporter/modernFrameRenderer.ts
  • src/lib/exporter/modernVideoExporter.fallback.test.ts
  • src/lib/exporter/modernVideoExporter.nativeStaticLayout.test.ts
  • src/lib/exporter/modernVideoExporter.ts
  • src/lib/exporter/outputTimeline.test.ts
  • src/lib/exporter/outputTimeline.ts
  • src/lib/exporter/sourceTrackRoutingPolicy.test.ts
  • src/lib/exporter/types.ts
  • src/lib/shortcuts.test.ts
  • src/lib/shortcuts.ts
  • src/lib/webcamProcessing/chromaKeyMath.test.ts
  • src/lib/webcamProcessing/chromaKeyMath.ts
  • src/lib/webcamProcessing/detectKeyColor.test.ts
  • src/lib/webcamProcessing/detectKeyColor.ts
  • src/lib/webcamProcessing/maskPath.test.ts
  • src/lib/webcamProcessing/maskPath.ts
  • src/lib/webcamProcessing/maskTexture.test.ts
  • src/lib/webcamProcessing/maskTexture.ts
  • src/lib/webcamProcessing/webcamProcessor.test.ts
  • src/lib/webcamProcessing/webcamProcessor.ts
  • src/lib/webcamSession.test.ts
  • src/lib/webcamSession.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ 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.

@github-actions github-actions Bot added the Slop label Jun 12, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

Extends the webcam Color group with white-balance temperature (warm/cool)
and saturation sliders. Same pattern as the existing controls: pure math
in chromaKeyMath.ts mirrored exactly by the WebGL shader, exact identity
at neutral, persisted with the project, applied to the keyed foreground in
preview and both exporters.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

The processing pipeline shipped with temperature/saturation support but the
two sliders were missing from the panel's control list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

A pixel matching either key color is removed (minimum alpha wins), so one
sample can cover the bright center and another the shadowed edges. New '+'
swatch next to the key color arms the eyedropper for the second slot; ×2
clears it. Same reference-math + shader-mirror pattern as the single key,
with unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

Picks a color the key must leave alone (skin tones or clothing catching
green spill). Protection wins over both key colors (max alpha), blends
smoothly at boundaries, and protected pixels skip spill suppression so
their color stays true. New '−' swatch in the key colors row; ×− clears.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ This pull request has been flagged by Anti-Slop.
Our automated checks detected patterns commonly associated with
low-quality or automated/AI submissions (failure count reached).
No automatic closure — a maintainer will review it.
If this is legitimate work, please add more context, link issues, or ping us.

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