### Run Linux AppImage with No Sandbox Source: https://github.com/siddharthvaddem/openscreen/blob/main/README.md Use this command if the application fails to launch on Linux due to sandbox-related errors. ```bash ./Openscreen-Linux-*.AppImage --no-sandbox ``` -------------------------------- ### Make Linux AppImage Executable Source: https://github.com/siddharthvaddem/openscreen/blob/main/README.md Commands to set the correct permissions and execute the AppImage file on Linux systems. ```bash chmod +x Openscreen-Linux-*.AppImage ./Openscreen-Linux-*.AppImage ``` -------------------------------- ### Electron IPC API - Source Selection Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Provides methods to enumerate available screen sources (displays and windows) and manage source selection for recording. Sources include thumbnails and application icons for display in a source picker UI. Use these methods to interact with the Electron environment for selecting recording sources. ```typescript // Get available screen sources with thumbnails const sources = await window.electronAPI.getSources({ types: ["screen", "window"], thumbnailSize: { width: 320, height: 180 }, }); // Example source object structure: // { // id: "screen:0:0", // name: "Entire Screen", // display_id: "12345678", // thumbnail: "data:image/png;base64,...", // appIcon: "data:image/png;base64,..." // } // Select a source for recording await window.electronAPI.selectSource({ id: "screen:0:0", name: "Entire Screen", display_id: "12345678", }); // Get currently selected source const selectedSource = await window.electronAPI.getSelectedSource(); // Open source selector window await window.electronAPI.openSourceSelector(); ``` -------------------------------- ### Electron IPC API - Source Selection Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Methods for enumerating available screen sources and managing source selection for recording. ```APIDOC ## Electron IPC API - Source Selection ### Description Provides methods to enumerate available screen sources (displays and windows) and manage source selection for recording. ### Methods - **window.electronAPI.getSources(options)**: Returns a list of available screen sources. - **window.electronAPI.selectSource(source)**: Selects a specific source for recording. - **window.electronAPI.getSelectedSource()**: Returns the currently selected source. - **window.electronAPI.openSourceSelector()**: Opens the source selector UI. ### Parameters #### getSources Options - **types** (array) - Required - List of source types (e.g., ["screen", "window"]) - **thumbnailSize** (object) - Optional - Dimensions for source thumbnails (width, height) ### Response Example { "id": "screen:0:0", "name": "Entire Screen", "display_id": "12345678", "thumbnail": "data:image/png;base64,...", "appIcon": "data:image/png;base64,..." } ``` -------------------------------- ### Open Video File Picker for Import Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Use this to open a file picker dialog for selecting video files. It returns the selected file path upon successful selection. ```typescript // Open video file picker for import const pickerResult = await window.electronAPI.openVideoFilePicker(); if (pickerResult.success && !pickerResult.canceled) { const videoPath = pickerResult.path; await window.electronAPI.setCurrentVideoPath(videoPath); } ``` -------------------------------- ### Screen Recording with useScreenRecorder Hook Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Manages the screen recording lifecycle, including source selection, audio mixing, webcam capture, and video storage. Supports 4K recording at 60fps with automatic bitrate scaling and codec selection. Use this hook to control recording state and enable/disable audio and video inputs. ```typescript import { useScreenRecorder } from "@/hooks/useScreenRecorder"; function RecordingPanel() { const { recording, toggleRecording, restartRecording, microphoneEnabled, setMicrophoneEnabled, microphoneDeviceId, setMicrophoneDeviceId, systemAudioEnabled, setSystemAudioEnabled, webcamEnabled, setWebcamEnabled, webcamDeviceId, setWebcamDeviceId, } = useScreenRecorder(); // Enable microphone with specific device setMicrophoneEnabled(true); setMicrophoneDeviceId("device-uuid-here"); // Enable system audio capture setSystemAudioEnabled(true); // Enable webcam recording (returns boolean success) const webcamSuccess = await setWebcamEnabled(true); if (webcamSuccess) { setWebcamDeviceId("webcam-device-id"); } // Start/stop recording toggleRecording(); // Restart recording (discards current and starts fresh) restartRecording(); return (
Recording: {recording ? "Active" : "Stopped"}
); } ``` -------------------------------- ### Manage Project Persistence Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Use these functions to create, save, and load project data structures. Ensure project data is validated before processing media or editor states. ```typescript import { createProjectData, validateProjectData, normalizeProjectEditor, resolveProjectMedia, toFileUrl, fromFileUrl, } from "@/components/video-editor/projectPersistence"; import type { ProjectMedia } from "@/lib/recordingSession"; import type { ProjectEditorState } from "@/components/video-editor/projectPersistence"; // Create project data for saving const media: ProjectMedia = { screenVideoPath: "/Users/demo/recordings/screen.webm", webcamVideoPath: "/Users/demo/recordings/webcam.webm", // optional }; const editorState: ProjectEditorState = { wallpaper: "/wallpapers/wallpaper1.jpg", shadowIntensity: 0.5, showBlur: true, motionBlurAmount: 0.35, borderRadius: 12, padding: 50, cropRegion: { x: 0, y: 0, width: 1, height: 1 }, zoomRegions: [], trimRegions: [], speedRegions: [], annotationRegions: [], aspectRatio: "16:9", webcamLayoutPreset: "picture-in-picture", webcamMaskShape: "circle", webcamPosition: { cx: 0.9, cy: 0.9 }, exportQuality: "good", exportFormat: "mp4", gifFrameRate: 15, gifLoop: true, gifSizePreset: "medium", }; const projectData = createProjectData(media, editorState); // Save project file const result = await window.electronAPI.saveProjectFile( projectData, "my-demo", // suggested filename "/existing/path.openscreen" // optional: overwrite existing ); if (result.success) { console.log(`Project saved to: ${result.path}`); } // Load project file const loadResult = await window.electronAPI.loadProjectFile(); if (loadResult.success && validateProjectData(loadResult.project)) { const media = resolveProjectMedia(loadResult.project); const editor = normalizeProjectEditor(loadResult.project.editor); // Convert file paths for video element src const videoUrl = toFileUrl(media.screenVideoPath); const webcamUrl = media.webcamVideoPath ? toFileUrl(media.webcamVideoPath) : null; } ``` -------------------------------- ### Read Binary File for Video Loading Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Reads a binary file, typically used for loading video data into memory. Ensure the path is correct and the file exists. ```typescript // Read binary file (for loading video into memory) const readResult = await window.electronAPI.readBinaryFile("/path/to/video.webm"); if (readResult.success) { const arrayBuffer: ArrayBuffer = readResult.data; const blob = new Blob([arrayBuffer], { type: "video/webm" }); } ``` -------------------------------- ### Exporting Video with VideoExporter Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Configures and executes a video export with various regions and visual effects. Requires an Electron environment for saving the resulting blob. ```typescript import { VideoExporter } from "@/lib/exporter"; import type { ExportProgress, ZoomRegion, TrimRegion, SpeedRegion, AnnotationRegion, CropRegion } from "@/lib/exporter"; const zoomRegions: ZoomRegion[] = [ { id: "zoom-1", startMs: 2000, endMs: 5000, depth: 3, // 1-6 scale, higher = more zoom focus: { cx: 0.5, cy: 0.5 }, // normalized 0-1 coordinates focusMode: "manual", // or "auto" for cursor-following }, ]; const trimRegions: TrimRegion[] = [ { id: "trim-1", startMs: 0, endMs: 1000 }, // Removes first second ]; const speedRegions: SpeedRegion[] = [ { id: "speed-1", startMs: 5000, endMs: 8000, speed: 1.5 }, // 1.5x playback ]; const annotationRegions: AnnotationRegion[] = [ { id: "annotation-1", startMs: 3000, endMs: 6000, type: "text", content: "Click here!", position: { x: 50, y: 50 }, // percentage-based position size: { width: 30, height: 20 }, style: { color: "#ffffff", backgroundColor: "transparent", fontSize: 32, fontFamily: "Inter", fontWeight: "bold", fontStyle: "normal", textDecoration: "none", textAlign: "center", }, zIndex: 1, }, ]; const cropRegion: CropRegion = { x: 0, y: 0, width: 1, height: 1, // normalized 0-1 values }; const exporter = new VideoExporter({ videoUrl: "file:///path/to/recording.webm", webcamVideoUrl: "file:///path/to/webcam.webm", // optional width: 1920, height: 1080, frameRate: 60, bitrate: 20_000_000, codec: "avc1.640033", wallpaper: "/wallpapers/wallpaper1.jpg", zoomRegions, trimRegions, speedRegions, annotationRegions, cropRegion, showShadow: true, shadowIntensity: 0.5, showBlur: true, motionBlurAmount: 0.35, borderRadius: 12, padding: 50, webcamLayoutPreset: "picture-in-picture", webcamMaskShape: "circle", onProgress: (progress: ExportProgress) => { console.log(`Export: ${progress.percentage.toFixed(1)}% - Frame ${progress.currentFrame}/${progress.totalFrames}`); }, }); const result = await exporter.export(); if (result.success && result.blob) { const arrayBuffer = await result.blob.arrayBuffer(); await window.electronAPI.saveExportedVideo(arrayBuffer, "export.mp4"); } // Cancel export if needed exporter.cancel(); ``` -------------------------------- ### Open External URL in Default Browser Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Opens a given URL in the user's default web browser. This is typically used for linking to external resources or websites. ```typescript // Open external URL in default browser await window.electronAPI.openExternalUrl("https://github.com/siddharthvaddem/openscreen"); ``` -------------------------------- ### Reveal File in System File Manager Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Opens the system's file manager to reveal the specified file or folder. Useful for showing users where their exported files are saved. ```typescript // Reveal file in system file manager await window.electronAPI.revealInFolder("/path/to/exported-video.mp4"); ``` -------------------------------- ### Manage Recording Sessions Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Handle storage of recorded video buffers and retrieve session metadata or cursor telemetry. Requires valid ArrayBuffer inputs for video data. ```typescript import type { RecordingSession, StoreRecordedSessionInput } from "@/lib/recordingSession"; // Store a new recording session const sessionInput: StoreRecordedSessionInput = { screen: { videoData: screenArrayBuffer, fileName: `recording-${Date.now()}.webm`, }, webcam: { videoData: webcamArrayBuffer, fileName: `recording-${Date.now()}-webcam.webm`, }, createdAt: Date.now(), }; const storeResult = await window.electronAPI.storeRecordedSession(sessionInput); if (storeResult.success) { console.log(`Recording stored at: ${storeResult.path}`); console.log(`Session:`, storeResult.session); } // Get current recording session const sessionResult = await window.electronAPI.getCurrentRecordingSession(); if (sessionResult.success) { const session: RecordingSession = sessionResult.session; console.log(`Screen video: ${session.screenVideoPath}`); console.log(`Webcam video: ${session.webcamVideoPath}`); console.log(`Created at: ${new Date(session.createdAt)}`); } // Set current video path (for imported videos) await window.electronAPI.setCurrentVideoPath("/path/to/video.mp4"); // Get cursor telemetry for automatic zoom suggestions const telemetryResult = await window.electronAPI.getCursorTelemetry("/path/to/video.webm"); if (telemetryResult.success) { // Array of { timeMs: number, cx: number, cy: number } const samples = telemetryResult.samples; console.log(`${samples.length} cursor positions recorded`); } ``` -------------------------------- ### Define Zoom Region Configuration Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Defines a zoom region with start/end times, zoom depth, focus point, and focus mode. Use `clampFocusToDepth` to ensure focus coordinates are valid for the selected zoom depth. `ZOOM_DEPTH_SCALES` maps zoom depth levels to magnification factors. ```typescript import type { ZoomRegion, ZoomDepth, ZoomFocus, ZoomFocusMode } from "@/components/video-editor/types"; import { ZOOM_DEPTH_SCALES, DEFAULT_ZOOM_DEPTH, clampFocusToDepth } from "@/components/video-editor/types"; // Zoom depth scale mapping (1 = least zoom, 6 = most zoom) // 1: 1.25x, 2: 1.5x, 3: 1.8x, 4: 2.2x, 5: 3.5x, 6: 5.0x const zoomRegion: ZoomRegion = { id: "zoom-1", startMs: 2000, // Start at 2 seconds endMs: 5000, // End at 5 seconds depth: 3 as ZoomDepth, // 1.8x zoom focus: { cx: 0.7, // 70% from left (normalized 0-1) cy: 0.3, // 30% from top (normalized 0-1) }, focusMode: "auto", // "manual" | "auto" - auto follows cursor telemetry }; // Clamp focus point to valid range for depth const clampedFocus = clampFocusToDepth( { cx: 1.5, cy: -0.2 }, // out of bounds zoomRegion.depth ); // Result: { cx: 1, cy: 0 } // Get scale factor for zoom depth const scaleFactor = ZOOM_DEPTH_SCALES[zoomRegion.depth]; console.log(`Zoom level ${zoomRegion.depth} = ${scaleFactor}x magnification`); ``` -------------------------------- ### useScreenRecorder Hook Source: https://context7.com/siddharthvaddem/openscreen/llms.txt The useScreenRecorder hook manages the screen recording lifecycle, including audio/webcam configuration and recording control. ```APIDOC ## useScreenRecorder Hook ### Description Manages the complete screen recording lifecycle including source selection, audio mixing, webcam capture, and automatic video storage. ### Methods - **toggleRecording()**: Starts or stops the recording session. - **restartRecording()**: Discards the current recording and starts a fresh one. - **setMicrophoneEnabled(boolean)**: Toggles microphone input. - **setMicrophoneDeviceId(string)**: Sets the active microphone device ID. - **setSystemAudioEnabled(boolean)**: Toggles system audio capture. - **setWebcamEnabled(boolean)**: Toggles webcam capture; returns a promise resolving to a boolean success status. - **setWebcamDeviceId(string)**: Sets the active webcam device ID. ### State - **recording** (boolean): Current recording status. - **microphoneEnabled** (boolean): Current microphone status. - **systemAudioEnabled** (boolean): Current system audio status. - **webcamEnabled** (boolean): Current webcam status. ``` -------------------------------- ### Save Exported Video with File Dialog Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Initiates a file save dialog for exporting video data. Allows the user to choose a location and filename for the export. Handles both successful saves and user cancellations. ```typescript // Save exported video with file dialog const saveResult = await window.electronAPI.saveExportedVideo( videoArrayBuffer, "my-export.mp4" // suggested filename ); if (saveResult.success) { console.log(`Saved to: ${saveResult.path}`); } else if (saveResult.canceled) { console.log("Export canceled by user"); } ``` -------------------------------- ### Exporting GIF with GifExporter Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Generates an animated GIF using specific size presets and frame rate settings. Uses the same rendering pipeline as video export. ```typescript import { GifExporter, GIF_SIZE_PRESETS, calculateOutputDimensions } from "@/lib/exporter"; const aspectRatioValue = 16 / 9; const sourceWidth = 1920; const sourceHeight = 1080; // Calculate output dimensions based on size preset const dimensions = calculateOutputDimensions( sourceWidth, sourceHeight, "medium", // "medium" | "large" | "original" GIF_SIZE_PRESETS, aspectRatioValue ); const gifExporter = new GifExporter({ videoUrl: "file:///path/to/recording.webm", width: dimensions.width, height: dimensions.height, frameRate: 15, // 15, 20, 25, or 30 fps loop: true, sizePreset: "medium", wallpaper: "/wallpapers/wallpaper1.jpg", zoomRegions: [], trimRegions: [], speedRegions: [], annotationRegions: [], showShadow: true, shadowIntensity: 0.5, showBlur: false, borderRadius: 12, padding: 50, cropRegion: { x: 0, y: 0, width: 1, height: 1 }, onProgress: (progress) => { console.log(`GIF Export: ${progress.percentage.toFixed(1)}%`); }, }); const result = await gifExporter.export(); if (result.success && result.blob) { const arrayBuffer = await result.blob.arrayBuffer(); await window.electronAPI.saveExportedVideo(arrayBuffer, "animation.gif"); } ``` -------------------------------- ### Bypass macOS Gatekeeper Source: https://github.com/siddharthvaddem/openscreen/blob/main/README.md Use this command to allow the application to run if macOS Gatekeeper blocks it due to a missing developer certificate. ```bash xattr -rd com.apple.quarantine /Applications/Openscreen.app ``` -------------------------------- ### Implement Undo/Redo with useEditorHistory Hook Source: https://context7.com/siddharthvaddem/openscreen/llms.txt The `useEditorHistory` hook manages editor state with separate methods for live updates (`updateState`) and history commits (`pushState`, `commitState`). It also provides `undo` and `redo` functions, which can be triggered by keyboard shortcuts. ```typescript import { useEditorHistory, INITIAL_EDITOR_STATE } from "@/hooks/useEditorHistory"; function VideoEditor() { const { state, pushState, updateState, commitState, undo, redo, } = useEditorHistory(INITIAL_EDITOR_STATE); // Push a complete new state (adds to history) const handleAddZoom = (newZoom: ZoomRegion) => { pushState((prev) => ({ zoomRegions: [...prev.zoomRegions, newZoom], })); }; // Update state during drag (doesn't add to history) const handleDragFocus = (id: string, focus: ZoomFocus) => { updateState((prev) => ({ zoomRegions: prev.zoomRegions.map((r) => r.id === id ? { ...r, focus } : r ), })); }; // Commit after drag ends (adds current state to history) const handleDragEnd = () => { commitState(); }; // Undo/redo keyboard shortcuts useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { const mod = e.ctrlKey || e.metaKey; if (mod && e.key === "z" && !e.shiftKey) { e.preventDefault(); undo(); } if (mod && (e.key === "y" || (e.key === "z" && e.shiftKey))) { e.preventDefault(); redo(); } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [undo, redo]); return (
); } ``` -------------------------------- ### Define Annotation Region Types Source: https://context7.com/siddharthvaddem/openscreen/llms.txt Defines various annotation types including text, images, and figures with position, size, and style. Content for images is expected as base64 data. Figure data includes specific properties like arrow direction and color. ```typescript import type { AnnotationRegion, AnnotationType, AnnotationPosition, AnnotationSize, AnnotationTextStyle, FigureData, ArrowDirection, } from "@/components/video-editor/types"; // Text annotation const textAnnotation: AnnotationRegion = { id: "annotation-1", startMs: 1000, endMs: 4000, type: "text", content: "Welcome to the demo!", textContent: "Welcome to the demo!", // stored separately for type switching position: { x: 50, y: 20 }, // percentage of canvas size: { width: 40, height: 15 }, style: { color: "#ffffff", backgroundColor: "rgba(0,0,0,0.7)", fontSize: 48, fontFamily: "Inter", fontWeight: "bold", fontStyle: "normal", textDecoration: "none", textAlign: "center", }, zIndex: 1, }; // Image annotation const imageAnnotation: AnnotationRegion = { id: "annotation-2", startMs: 2000, endMs: 6000, type: "image", content: "data:image/png;base64,...", // base64 image data imageContent: "data:image/png;base64,...", position: { x: 10, y: 10 }, size: { width: 20, height: 20 }, style: { ...DEFAULT_ANNOTATION_STYLE }, zIndex: 2, }; // Arrow figure annotation const arrowAnnotation: AnnotationRegion = { id: "annotation-3", startMs: 3000, endMs: 5000, type: "figure", content: "", position: { x: 60, y: 50 }, size: { width: 15, height: 10 }, style: { ...DEFAULT_ANNOTATION_STYLE }, zIndex: 3, figureData: { arrowDirection: "right" as ArrowDirection, // up, down, left, right, up-right, etc. color: "#34B27B", strokeWidth: 4, }, }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.