Skip to content

Conversation

@julianromli
Copy link

@julianromli julianromli commented Jan 14, 2026

Description

This PR introduces two major features to enhance the screen recording experience:

  1. Preset System - Save, load, and manage video styling configurations with one-click application
  2. Microphone Input - Record voice narration alongside screen capture with real-time audio level monitoring

Motivation

Preset System

Currently, users must manually reconfigure padding, shadow, rounded corners, background, and other styling settings every time they open a new video. This is repetitive and time-consuming. The preset system allows users to save their preferred styles and apply them instantly.

Microphone Input

Users often need to add voice narration to their screen recordings for tutorials, demos, or explanations. This feature adds native microphone support with device selection, real-time level meters, and seamless audio merging into the final video export.

Type of Change

  • New Feature
  • Bug Fix
  • Refactor / Code Cleanup
  • Documentation Update
  • Other (please specify)

Related Issue(s)

N/A (Feature development from design docs)

Features Overview

🎨 Preset System

Feature Description
Save Presets Save current styling settings (padding, shadow, border radius, blur, wallpaper) as named presets
Load Presets One-click application of saved presets
Default Preset Set a preset as default to auto-apply on new videos
Preset Management Rename, duplicate, delete, and manage presets via dropdown menu
Persistent Storage Presets saved to Electron Store (survives app restarts)

Settings included in presets:

  • Padding (0-100%)
  • Shadow Intensity (0-1)
  • Border Radius (0-16px)
  • Motion Blur (on/off)
  • Show Blur (on/off)
  • Wallpaper (image/color/gradient)

🎤 Microphone Input

Feature Description
Device Selection Choose from available microphone devices
Real-time Level Meter Visual audio level indicator
Mute Toggle Quick mute/unmute control
Audio Merging Audio track merged directly into WebM/MP4 output
State Persistence Selected device and preferences saved across sessions
Separate Settings Window Dedicated mic settings window for advanced configuration
Cross-window Sync Settings synchronized between HUD and settings window

Error Handling:

  • Graceful fallback when no microphone detected
  • Permission denial handling with user guidance
  • Mid-recording disconnection handling
  • Auto-reconnect support

Screenshots / Video

{6C07AA5D-0CD1-4571-AE27-82E408C7E73D} {66AA1323-0286-40EB-8DD4-3978125B3F04} {C3E00095-2DFA-46DD-883E-E9BA845DB4C6} {61EA35DE-0661-4CC2-A865-7EA8EC58C692} {15C5A213-9DC7-4422-B254-D47835033200}

Preset System UI:

  • Preset dropdown in Settings Panel (top of video editor)
  • Save Preset modal with name input and default checkbox

Microphone UI:

  • Mic toggle button in HUD bar
  • Device selection dropdown with level meter
  • Separate mic settings window for advanced config

Testing

Prerequisites

bun install
bun run dev

Test Preset System

  1. Open the app and load a video in the editor
  2. Adjust styling settings (padding, shadow, border radius, wallpaper)
  3. Click "Save" button next to preset dropdown
  4. Enter a name and optionally set as default
  5. Verify preset appears in dropdown
  6. Change settings, then select saved preset → Settings should restore
  7. Close and reopen app → Default preset should auto-apply

Test Microphone Input

  1. Click mic icon in HUD bar
  2. Grant microphone permission if prompted
  3. Verify device list populates (if microphones available)
  4. Select a device → Level meter should respond to audio
  5. Start recording with mic enabled
  6. Stop recording → Export video
  7. Verify exported video contains audio track

Test Cross-window Sync

  1. Toggle mic on in HUD
  2. Open mic settings window (gear icon)
  3. Change device in settings window
  4. Verify HUD reflects the change
  5. Close settings window → Verify state persists

Technical Details

New Files (12 files)

File Purpose
src/components/video-editor/PresetSelector.tsx Preset dropdown component
src/components/video-editor/SavePresetModal.tsx Save preset dialog
src/hooks/usePresets.ts Preset state management hook
electron/ipc/presets.ts Electron-side preset file operations
src/hooks/useMicrophone.ts Mic device management & level meter
src/hooks/useMicrophone.test.ts Unit tests for mic hook
src/components/launch/MicrophoneSelector.tsx Device selection dropdown UI
src/components/launch/MicrophoneSettingsPage.tsx Dedicated settings window
src/stores/audioSettings.ts Audio preferences Zustand store
src/stores/audioSettings.test.ts Unit tests for audio store
src/lib/exporter/audioExtractor.ts Audio extraction utilities
docs/plans/*.md Design documentation for both features

Modified Files (8 files)

File Changes
electron/preload.ts Exposed preset & audio APIs to renderer
electron/ipc/handlers.ts Added IPC handlers for mic settings window
electron/windows.ts Added mic settings window creation & management
electron/electron-env.d.ts Added type definitions for new APIs
src/hooks/useScreenRecorder.ts Added audio stream combining support
src/components/launch/LaunchWindow.tsx Integrated mic toggle in HUD
src/components/video-editor/SettingsPanel.tsx Added preset selector at top
src/components/video-editor/VideoEditor.tsx Added default preset loading on mount
src/lib/exporter/videoExporter.ts Added audio track support for export

Commits Summary (19 commits)

feat: add preset system for saving and loading video styling configurations
docs: add preset feature design document
docs: add microphone input feature design document
feat(audio): add useMicrophone hook with TDD tests
feat(audio): add audioSettings store for mic preferences persistence
feat(ui): add MicrophoneSelector dropdown component
feat(audio): add audio stream support to useScreenRecorder
feat(ui): integrate MicrophoneSelector into LaunchWindow HUD
feat(audio): add track-ended handler for mid-use disconnection
feat(audio): add advanced audio settings for recording and export
feat(export): add audio track support to video export
feat(audio): implement separate mic settings window with cross-window sync
fix(audio): restore mic state in HUD window from saved settings
fix(audio): ensure all settings saved before closing mic settings window
fix(audio): prevent race conditions and ensure cleanup on window close
+ UI fixes for dropdown clipping issues

Checklist

  • I have performed a self-review of my code.
  • I have added any necessary screenshots or videos.
  • I have linked related issue(s) and updated the changelog if applicable.
  • Added design documentation for both features
  • Added unit tests for core functionality
  • Tested on Windows (manual testing)

…ations

- Add preset types and interfaces (Preset, PresetSettings, PresetStore)
- Create electron IPC handlers for preset CRUD operations
- Implement file-based storage in userData/presets.json
- Add usePresets React hook for state management
- Create PresetSelector component with dropdown UI
- Create SavePresetModal for naming new presets
- Integrate into SettingsPanel and VideoEditor
- Support setting default preset that auto-applies on video load
- Include duplicate, rename, delete, and reset to defaults actions
- Device enumeration with audioinput filtering
- devicechange event listener for auto-refresh
- Audio stream management via getUserMedia
- AudioContext + AnalyserNode for level metering
- RMS-based audio level (0-100 scale) at ~60fps
- Permission state tracking (granted/denied/prompt/unknown)
- Proper cleanup on unmount using refs
- localStorage-based persistence layer
- get/set/clear API with partial updates
- Graceful handling of unavailable/corrupted storage
- 16 TDD tests passing
- Device list with radio selection
- Real-time audio level meter (color-coded)
- Mute toggle checkbox
- Persists settings via audioSettings store
- Glassmorphism styling matching HUD bar
- Permission denied/error state display
- Accept optional audioStream via options parameter
- Combine video and audio tracks into single MediaStream
- Only stop video tracks on cleanup (audio managed externally)
- Graceful handling of null/undefined audio stream
- Backward compatible - video-only recording still works
- Add useMicrophone hook to get audio stream
- Pass audioStream to useScreenRecorder for combined recording
- Position MicrophoneSelector between source selector and record button
- Disable mic selector during active recording
- Listen for 'ended' event on audio tracks
- Set error state when microphone disconnects
- Cleanup and refresh device list on disconnection
- Provides better UX feedback for hardware changes
- Increase HUD overlay window height from 100px to 350px to accommodate popover
- Position HUD bar at bottom of window using items-end
- Convert MicrophoneSelector to controlled component (single hook instance)
- Fix dual useMicrophone hook issue causing state desync between components
- Create AudioExtractor class to decode audio from video using Web Audio API
- Add AudioEncoder initialization with Opus codec in VideoExporter
- Initialize VideoMuxer with hasAudio flag when audio is detected
- Process audio in 20ms chunks synchronized with video export
- Handle trim regions for audio via mapEffectiveToSourceTime
- Clean up audio resources (encoder, extractor) on export completion
- Add configurable recording settings: sample rate (44.1/48kHz),
  channels (mono/stereo), noise suppression, echo cancellation,
  auto gain control
- Add audio bitrate selector for export (128/192/256/320 kbps)
- Extend AudioSettings store with new fields and persistence
- Add Advanced Settings UI section in MicrophoneSelector popover
- Add Audio Quality selector in SettingsPanel (MP4 export only)
- Apply audio constraints to getUserMedia via useMicrophone hook
- Default to audiophile-friendly settings (48kHz, stereo, 192kbps)
…ipping

The HUD window's fixed 350px height was causing Select dropdowns to be
clipped when opening inside the popover. Converted to a centered modal
dialog which renders via portal outside the HUD bounds, allowing all
UI elements to display properly.
… sync

- Create MicrophoneSettingsPage as standalone child window for mic settings
- Add setWindowOpenHandler in HUD to spawn mic settings child window
- Simplify MicrophoneSelector to just open the settings window
- Add localStorage polling in LaunchWindow to detect settings changes
- Add constraint change detection in useMicrophone to re-apply settings
- Settings now persist and sync between HUD and settings window
LaunchWindow now initializes microphone based on localStorage settings.
Previously, each window had independent useMicrophone hook states - settings
were saved but HUD never called enable()/selectDevice() to restore them.

Added useEffect that watches audioSettings and restores mic state when:
- Settings indicate mic should be enabled but hook shows disabled
- Triggers on mount and when settings change (via polling)

This ensures mic stays enabled after closing the settings window.
handleClose now explicitly saves ALL current settings to localStorage
before closing, with a small delay to ensure the write completes.
This prevents race conditions where window closes before save finishes.
CRITICAL-1: Added cancellation flag to constraint change effect to prevent
race conditions when settings change rapidly. New streams are properly
cleaned up if the effect is cancelled before completion.

CRITICAL-2: Added beforeunload handler to MicrophoneSettingsPage to ensure
all settings are saved when window is closed via OS controls (X button,
Alt+F4, etc.). The useMicrophone hook's cleanup effect handles stream
cleanup on component unmount.
- Define SubtitleRegion data model with word-level timestamps
- Outline AssemblyAI integration architecture
- Specify UI components and user flow
- Estimate 7-day implementation timeline
…ntegration

- Add subtitle track row to timeline editor with vertical scroll support
- Implement SubtitleGenerateDialog for AI-powered subtitle generation
- Add SubtitleOverlay and SubtitleSettingsPanel components
- Integrate Deepgram transcription service via Electron IPC
- Add subtitle rendering support for video/GIF export
- Fix timeline vertical scroll by changing overflow-hidden to overflow-y-auto
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.

1 participant