Context
A popular look for product videos puts the recording on a colorful background, with padding, rounded corners and a soft shadow. Today FrameComposer fills the canvas with black and fits the screen edge to edge.
Where to look
Sources/SnapcapCore/Render/FrameComposer.swift: compose(...) starts from a black CIImage and calls fit(_:into:).
Sources/SnapcapCore/Render/OverlayChrome.swift: renders a mask, border and shadow once with Core Graphics and caches them. Reuse this approach for the screen's rounded mask and shadow.
Sources/SnapcapCore/Layout/OverlayLayout.swift: the single source of truth for bubble geometry. Add an equivalent ScreenLayout (screen rectangle, corner radius, shadow) that both the export and the preview use.
Sources/SnapcapCore/Model/Project.swift: add a lenient background section, and add it to renderFingerprint's Inputs.
Sources/Snapcap/Views/EditorView.swift: PlayerStage puts PlayerLayerView edge to edge. The preview must inset it and draw the same background.
Sources/Snapcap/Views/Components.swift: SliderRow, plus ColorPicker with Binding(rgba:), for the controls.
Proposal
- Model:
"background": { "style": "none" | "color" | "gradient", "color1": {…}, "color2": {…}, "angle": 135, "padding": 64, "cornerRadius": 12, "shadow": true }. Lengths use the 1080 reference units (OverlayLayout.unitScale). An image background can come later.
- Style
none must produce exactly today's output.
- The camera bubble stays positioned relative to the whole canvas, so it can sit on the background.
- The output size doesn't change; padding shrinks the screen within the same render size.
Acceptance criteria
Context
A popular look for product videos puts the recording on a colorful background, with padding, rounded corners and a soft shadow. Today
FrameComposerfills the canvas with black and fits the screen edge to edge.Where to look
Sources/SnapcapCore/Render/FrameComposer.swift:compose(...)starts from a blackCIImageand callsfit(_:into:).Sources/SnapcapCore/Render/OverlayChrome.swift: renders a mask, border and shadow once with Core Graphics and caches them. Reuse this approach for the screen's rounded mask and shadow.Sources/SnapcapCore/Layout/OverlayLayout.swift: the single source of truth for bubble geometry. Add an equivalentScreenLayout(screen rectangle, corner radius, shadow) that both the export and the preview use.Sources/SnapcapCore/Model/Project.swift: add a lenientbackgroundsection, and add it torenderFingerprint'sInputs.Sources/Snapcap/Views/EditorView.swift:PlayerStageputsPlayerLayerViewedge to edge. The preview must inset it and draw the same background.Sources/Snapcap/Views/Components.swift:SliderRow, plusColorPickerwithBinding(rgba:), for the controls.Proposal
"background": { "style": "none" | "color" | "gradient", "color1": {…}, "color2": {…}, "angle": 135, "padding": 64, "cornerRadius": 12, "shadow": true }. Lengths use the 1080 reference units (OverlayLayout.unitScale). An image background can come later.nonemust produce exactly today's output.Acceptance criteria
nonerenders exactly as today, so the existingExportTestsstay green.project.jsonfiles open with the background off.ScreenLayoutmath (padding at 720p and at 4K scales identically), plus an export test that samples a background pixel and a screen pixel.