# Get OpenAPI specification Source: https://docs.videobgremover.com/api-reference/api/get-openapi-specification https://videobgremover.com/openapi.yaml get /v1/openapi Retrieve the OpenAPI 3.0 specification for this API in YAML format. # Check credit balance Source: https://docs.videobgremover.com/api-reference/credits/check-credit-balance https://videobgremover.com/openapi.yaml get /v1/credits Get your current credit balance and usage information. # API Reference | Video Background Remover Source: https://docs.videobgremover.com/api-reference/introduction Complete introduction to VideoBGRemover API v1.6.0. Learn authentication, rate limits, error handling, versioning, and AI-powered video background removal. # API Reference The VideoBGRemover API provides programmatic access to our video background removal service. This section contains the complete API reference with interactive examples. ## Base URL ``` https://api.videobgremover.com/v1 ``` ## Versioning The VideoBGRemover API uses semantic versioning. The current version is **v1.6.0**. * **URL versioning**: All endpoints use `/v1/` in the path * **Header versioning**: All responses include `X-API-Version: 1.6.0` header Version headers are automatically included in all API responses to help you track which version you're using. ## Authentication All API requests require an API key in the `X-Api-Key` header: ```bash theme={"dark"} curl -H "X-Api-Key: vbr_your_api_key_here" \ https://api.videobgremover.com/v1/credits ``` Generate your API key in the dashboard ## Interactive Playground Each endpoint below includes an interactive playground where you can test API calls directly from this documentation. The playground uses your API key to make real requests to our servers. ## Response Examples For detailed examples of API responses in different states, see the [API Responses](/api-reference/responses) page. ## Rate Limits & File Limits * **File Size**: Maximum 1GB per video * **Supported Formats**: MP4, MOV, WebM, AVI, MKV, M4V * **Credits**: Credit usage based on video duration (see [Models](/video-background-removal/models)) ## Error Handling The API uses standard HTTP status codes: | Code | Description | | ----- | --------------------------------------- | | `200` | Success | | `400` | Bad Request - Invalid parameters | | `401` | Unauthorized - Invalid API key | | `402` | Payment Required - Insufficient credits | | `413` | Payload Too Large - File exceeds 1GB | | `500` | Internal Server Error | # Check job processing status Source: https://docs.videobgremover.com/api-reference/jobs/check-job-processing-status https://videobgremover.com/openapi.yaml get /v1/jobs/{id}/status Check the current status of a video processing job and get download URLs when complete. # Create a new video processing job Source: https://docs.videobgremover.com/api-reference/jobs/create-a-new-video-processing-job https://videobgremover.com/openapi.yaml post /v1/jobs Create a new job for video background removal. You can either: 1. **File Upload**: Provide filename and content_type to get an upload URL 2. **URL Download**: Provide video_url to download from a public URL **File Limits:** - Formats: MP4, MOV, WebM - Size: 1GB maximum - Duration: No hard limit (processing time varies) Note: Provide either (filename + content_type) OR video_url, not both. # Delete a video job Source: https://docs.videobgremover.com/api-reference/jobs/delete-a-video-job https://videobgremover.com/openapi.yaml delete /v1/jobs/{id} Permanently delete a video job and all associated files. This will delete: - Videos and exports - Database record and all related data **Warning**: This action cannot be undone. No credit refunds are issued for deleted jobs. **Authorization**: You can only delete jobs that belong to your API key's user account. # Start processing a video job Source: https://docs.videobgremover.com/api-reference/jobs/start-processing-a-video-job https://videobgremover.com/openapi.yaml post /v1/jobs/{id}/start Start background removal processing for an uploaded video. **Important**: Credits are checked and deducted when you call this endpoint, not when creating the job. Processing costs 1 credit per second of video. # API Response Reference - VideoBGRemover API Source: https://docs.videobgremover.com/api-reference/responses Complete guide to VideoBGRemover API response formats, status codes, and error handling. Learn to parse responses and handle job states effectively. # API Response Reference This page provides detailed examples of API responses to help you understand what to expect when integrating with the VideoBGRemover API. ## Job Status Responses The `/v1/jobs/{id}/status` endpoint returns different response formats depending on the job's current state. ### Created Status When a job is first created but processing hasn't started: ```json theme={"dark"} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "created", "filename": "my-video.mp4", "created_at": "2023-12-01T10:00:00Z", "length_seconds": null, "thumbnail_url": null, "processed_video_url": null, "message": null, "background": null, "output_format": null, "export_id": null } ``` ### Processing Status When the video is being analyzed and processed: ```json theme={"dark"} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing", "filename": "my-video.mp4", "created_at": "2023-12-01T10:00:00Z", "length_seconds": 30.5, "thumbnail_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Expires=3600", "processed_video_url": null, "message": "Processing video with red background", "background": { "type": "color", "color": "#FF0000" }, "output_format": "mp4", "export_id": "exp_red_bg_123" } ``` ### Completed Status (Default Green Screen) When processing is complete with default settings: ```json theme={"dark"} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "filename": "my-video.mp4", "created_at": "2023-12-01T10:00:00Z", "length_seconds": 30.5, "thumbnail_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Expires=3600", "transparent_thumbnail_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_transparent_thumb.png?X-Goog-Expires=3600", "processed_video_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000.mp4?X-Goog-Expires=3600", "processed_mask_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_mask.mp4?X-Goog-Expires=3600", "message": "Processing completed successfully", "background": null, "output_format": null, "export_id": null } ``` ### Completed Status (Transparent WebM) When processing is complete with transparent background: ```json theme={"dark"} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "filename": "my-video.mp4", "created_at": "2023-12-01T10:00:00Z", "length_seconds": 30.5, "thumbnail_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_thumb.jpg?X-Goog-Expires=3600", "transparent_thumbnail_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_transparent_thumb.png?X-Goog-Expires=3600", "processed_video_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000.webm?X-Goog-Expires=3600", "processed_mask_url": "https://storage.googleapis.com/videobg-processed/550e8400-e29b-41d4-a716-446655440000_mask.mp4?X-Goog-Expires=3600", "message": "Processing completed successfully", "background": { "type": "transparent", "transparent_format": "webm_vp9" }, "output_format": "webm", "export_id": "exp_webm_vp9_456" } ``` ### Failed Status When processing encounters an error: ```json theme={"dark"} { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "filename": "my-video.mp4", "created_at": "2023-12-01T10:00:00Z", "length_seconds": null, "thumbnail_url": null, "processed_video_url": null, "message": "Video too large: 1250.5MB", "background": { "type": "color", "color": "#FF0000" }, "output_format": "mp4", "export_id": "exp_red_bg_123" } ``` ## Error Responses ### 400 Bad Request Invalid request parameters or malformed data: ```json theme={"dark"} { "error": "Must provide either (filename + content_type) OR video_url" } ``` ### 401 Unauthorized Invalid or missing API key: ```json theme={"dark"} { "error": "Invalid API key" } ``` ### 413 Payload Too Large File exceeds the 1GB size limit: ```json theme={"dark"} { "error": "Video too large: 1250.5MB" } ``` ### 402 Payment Required Insufficient credits for processing: ```json theme={"dark"} { "error": "Not enough credits available" } ``` ### 404 Not Found Job ID doesn't exist: ```json theme={"dark"} { "error": "Job not found" } ``` ## Credit Balance Response The `/v1/credits` endpoint returns: ```json theme={"dark"} { "user_id": "usr_abc123def456", "total_credits": 1000, "remaining_credits": 750, "credits_used": 250 } ``` ## Response Field Explanations | Field | Type | Description | | --------------------------- | ----------- | ------------------------------------------------------------------------- | | `id` | string | Unique job identifier (UUID format) | | `status` | string | Current processing status: `created`, `processing`, `completed`, `failed` | | `filename` | string | Original uploaded filename | | `created_at` | string | ISO 8601 timestamp of job creation | | `length_seconds` | number/null | Video duration in seconds (null until analyzed) | | `thumbnail_url` | string/null | Signed URL for video thumbnail (expires in 1 hour) | | `transparent_thumbnail_url` | string/null | Signed URL for transparent thumbnail | | `processed_video_url` | string/null | Signed URL for processed video (expires in 1 hour) | | `processed_mask_url` | string/null | Signed URL for video mask | | `message` | string/null | Human-readable status message | | `background` | object/null | Background configuration used for processing | | `output_format` | string/null | Output video format (mp4, webm, etc.) | | `export_id` | string/null | Export identifier for custom background processing | ## Important Notes **Signed URLs Expire**: All `*_url` fields contain signed URLs that expire after 1 hour. Download files immediately or call the status endpoint again to get fresh URLs. **Polling Frequency**: When monitoring job status, poll every 5-10 seconds. Faster polling may result in rate limiting. **Error Handling**: Always check the `status` field first. If it's `failed`, check the `message` field for error details. # Get webhook delivery history Source: https://docs.videobgremover.com/api-reference/webhooks/get-webhook-delivery-history https://videobgremover.com/openapi.yaml get /v1/webhooks/deliveries Retrieve the delivery history for webhooks sent for a specific video job. Shows all delivery attempts, their status, and any error messages. # API Authentication Guide | Video Background Remover API Key Setup Source: https://docs.videobgremover.com/authentication Complete authentication guide for VideoBGRemover API. Learn API key setup, security best practices, rate limiting, and troubleshooting with examples. ## API Key Format All API requests require authentication using an API key with the format `vbr_` followed by 32 characters. ``` vbr_1234567890abcdef1234567890abcdef ``` ## Request Header Include your API key in the `X-Api-Key` header for all requests: ```bash theme={"dark"} curl -X GET https://api.videobgremover.com/v1/credits \ -H "X-Api-Key: vbr_your_api_key_here" ``` Never share your API key publicly or include it in client-side code. Keep it secure on your server. ## Getting Your API Key Sign up at [videobgremover.com](https://videobgremover.com) if you haven't already. You need credits to create an API key. Buy credits in your dashboard. Go to [API Management](https://videobgremover.com/api-management) and create a new API key with a descriptive name. ## Testing Authentication Test your API key by checking your credit balance: ```bash theme={"dark"} curl -X GET https://api.videobgremover.com/v1/credits \ -H "X-Api-Key: vbr_your_api_key_here" ``` **Success Response:** ```json theme={"dark"} { "user_id": "user-uuid", "total_credits": 100, "remaining_credits": 95, "used_credits": 5 } ``` ## Authentication Errors ### Invalid API Key (401) ```json theme={"dark"} { "error": "Invalid API key" } ``` **Common causes:** * Typo in the API key * Using wrong header name (should be `X-Api-Key`) * API key was deleted or deactivated ### Missing API Key (401) ```json theme={"dark"} { "error": "API key required" } ``` **Solution:** Make sure you include the `X-Api-Key` header in your request. ## Security Best Practices Never use API keys in client-side JavaScript, mobile apps, or any publicly accessible code. Store your API key in environment variables, not in your source code: ```bash theme={"dark"} export VIDEOBGREMOVER_API_KEY="vbr_your_api_key_here" ``` Regularly rotate your API keys. Create a new key before deleting the old one to avoid downtime. Use different API keys for development, staging, and production environments. ## Rate Limits Each API key has the following limits: * **100 requests per minute** * **3 video processing jobs per minute** Rate limit headers are included in all responses: ``` X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1640995200 ``` When you exceed the rate limit, you'll receive a `429 Too Many Requests` response. # Video Background Removal Examples Source: https://docs.videobgremover.com/examples Ready-to-use code examples for video background removal. Complete Node.js, Python, and cURL examples with step-by-step workflows and best practices. ## Basic Examples ### Simple Background Replacement Remove background and overlay on a colored background. ```typescript Node.js theme={"dark"} // 1. Remove background from video import { VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('your_api_key') const video = Video.open('input.mp4') const transparent = await video.removeBackground(client) // 2. Add to colored background const background = Background.fromColor('#FF6B35', 1920, 1080, 30) const comp = new Composition(background) comp.add(transparent, 'main').at(Anchor.CENTER).size(SizeMode.CONTAIN) // 3. Export await comp.toFile('output.mp4', EncoderProfile.h264()) console.log('✅ Background replaced!') ``` ```python Python theme={"dark"} # 1. Remove background from video from videobgremover import VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode client = VideoBGRemoverClient('your_api_key') video = Video.open('input.mp4') transparent = video.remove_background(client) # 2. Add to colored background background = Background.from_color('#FF6B35', 1920, 1080, 30) comp = Composition(background) comp.add(transparent, 'main').at(Anchor.CENTER).size(SizeMode.CONTAIN) # 3. Export comp.to_file('output.mp4', EncoderProfile.h264()) print('✅ Background replaced!') ``` ## AI UGC Ads ### AI Avatar on Video Background Create professional UGC ads with AI avatars positioned bottom-right. ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode, RemoveBGOptions, Prefer } from '@videobgremover/sdk' async function createAIUGCAd() { // 1. Remove background from AI actor const client = new VideoBGRemoverClient('your_api_key') const aiActor = Video.open('ai_actor_video.mp4') const options = new RemoveBGOptions(Prefer.WEBM_VP9) const transparentActor = await aiActor.removeBackground(client, options) // 2. Create video background const background = Background.fromVideo('product_showcase.mp4') const comp = new Composition(background) // 3. Position AI avatar bottom-right (35% of canvas) comp.add(transparentActor, 'ai_avatar') .at(Anchor.BOTTOM_RIGHT, -50, -50) // 50px from edges .size(SizeMode.CANVAS_PERCENT, { percent: 35 }) .opacity(0.95) // Slight transparency for polish // 4. Export for ads await comp.toFile('ai_ugc_ad.mp4', EncoderProfile.h264({ crf: 20, preset: 'medium' })) console.log('✅ AI UGC ad created: ai_ugc_ad.mp4') } createAIUGCAd() ``` ```python Python theme={"dark"} from videobgremover import ( VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode, RemoveBGOptions, Prefer ) def create_ai_ugc_ad(): # 1. Remove background from AI actor client = VideoBGRemoverClient('your_api_key') ai_actor = Video.open('ai_actor_video.mp4') options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) transparent_actor = ai_actor.remove_background(client, options) # 2. Create video background background = Background.from_video('product_showcase.mp4') comp = Composition(background) # 3. Position AI avatar bottom-right (35% of canvas) comp.add(transparent_actor, 'ai_avatar') \ .at(Anchor.BOTTOM_RIGHT, dx=-50, dy=-50) \ .size(SizeMode.CANVAS_PERCENT, percent=35) \ .opacity(0.95) # 4. Export for ads comp.to_file('ai_ugc_ad.mp4', EncoderProfile.h264(crf=20, preset='medium')) print('✅ AI UGC ad created: ai_ugc_ad.mp4') create_ai_ugc_ad() ``` ## Dynamic Social Media Content ### Interactive Positioning with Transparency Effects Create engaging social media content with moving elements and transparency changes. ```typescript Node.js theme={"dark"} async function createDynamicSocialContent() { // 1. Process content video const client = new VideoBGRemoverClient('your_api_key') const contentVideo = Video.open('dynamic_content.mp4') const transparent = await contentVideo.removeBackground(client) // 2. Create vertical background video (9:16 for social) const background = Background.fromVideo('trending_background.mp4') const comp = new Composition(background) // 3. Dynamic positioning sequence // 0-3s: Bottom-right with transparency comp.add(transparent.subclip(0, 3), 'phase1') .start(0).duration(3) .at(Anchor.BOTTOM_RIGHT, -30, -30) .size(SizeMode.CANVAS_PERCENT, { percent: 40 }) .alpha(true) .opacity(0.8) // 3-6s: Top-left without transparency comp.add(transparent.subclip(3, 6), 'phase2') .start(3).duration(3) .at(Anchor.TOP_LEFT, 30, 30) .size(SizeMode.CANVAS_PERCENT, { percent: 35 }) .alpha(false) .opacity(1.0) // 6-9s: Center with partial transparency comp.add(transparent.subclip(6, 9), 'phase3') .start(6).duration(3) .at(Anchor.CENTER) .size(SizeMode.CANVAS_PERCENT, { percent: 50 }) .alpha(true) .opacity(0.6) // 9-12s: Bottom-left with full transparency comp.add(transparent.subclip(9, 12), 'phase4') .start(9).duration(3) .at(Anchor.BOTTOM_LEFT, 30, -30) .size(SizeMode.CANVAS_PERCENT, { percent: 45 }) .alpha(true) .opacity(0.9) // 4. Export for social media await comp.toFile('dynamic_social_content.mp4', EncoderProfile.h264({ crf: 25, preset: 'fast' })) console.log('✅ Dynamic social content created') } createDynamicSocialContent() ``` ```python Python theme={"dark"} def create_dynamic_social_content(): # 1. Process content video client = VideoBGRemoverClient('your_api_key') content_video = Video.open('dynamic_content.mp4') transparent = content_video.remove_background(client) # 2. Create vertical background video background = Background.from_video('trending_background.mp4') comp = Composition(background) # 3. Dynamic positioning sequence # 0-3s: Bottom-right with transparency comp.add(transparent.subclip(0, 3), 'phase1') \ .start(0).duration(3) \ .at(Anchor.BOTTOM_RIGHT, dx=-30, dy=-30) \ .size(SizeMode.CANVAS_PERCENT, percent=40) \ .alpha(enabled=True) \ .opacity(0.8) # 3-6s: Top-left without transparency comp.add(transparent.subclip(3, 6), 'phase2') \ .start(3).duration(3) \ .at(Anchor.TOP_LEFT, dx=30, dy=30) \ .size(SizeMode.CANVAS_PERCENT, percent=35) \ .alpha(enabled=False) \ .opacity(1.0) # 6-9s: Center with partial transparency comp.add(transparent.subclip(6, 9), 'phase3') \ .start(6).duration(3) \ .at(Anchor.CENTER) \ .size(SizeMode.CANVAS_PERCENT, percent=50) \ .alpha(enabled=True) \ .opacity(0.6) # 9-12s: Bottom-left with full transparency comp.add(transparent.subclip(9, 12), 'phase4') \ .start(9).duration(3) \ .at(Anchor.BOTTOM_LEFT, dx=30, dy=-30) \ .size(SizeMode.CANVAS_PERCENT, percent=45) \ .alpha(enabled=True) \ .opacity(0.9) # 4. Export for social media comp.to_file('dynamic_social_content.mp4', EncoderProfile.h264( crf=25, preset='fast' )) print('✅ Dynamic social content created') create_dynamic_social_content() ``` ## Next Steps Complete API documentation for all classes and methods Detailed guide to background removal options and formats Learn advanced composition techniques and effects # Video Composition via API Source: https://docs.videobgremover.com/guides/api-composition Compose videos on custom backgrounds using server-side processing. Perfect for automation, n8n workflows, and applications that need ready-to-use videos. # Video Composition via API Automatically compose your transparent videos on custom backgrounds - all processed on our servers. No need to handle transparent videos yourself. **New:** Try our [Composition Builder](https://videobgremover.com/composition-builder) to design compositions visually and export JSON. **Perfect for:** Automation workflows (n8n, Zapier), applications that need final videos immediately, and users who don't want to deal with transparent video formats. ## What is API Composition? Instead of receiving a transparent video that you need to compose yourself, the API can automatically layer your foreground on a custom background and return the final video. **Two modes:** 1. **Templates** - Quick presets for common layouts (social media ads, centered, PiP, fullscreen) 2. **Custom** - Full control over positioning, sizing, and effects *** ## Quick Start with Templates Templates are pre-configured compositions optimized for common use cases. ### Available Templates Optimized for social media ads (9:16 vertical) * Centered foreground * Contain sizing * Perfect for TikTok, Instagram Reels Simple centered layout * Foreground in center * Fits within canvas * Universal use case Small overlay in corner * Bottom-right position * 30% canvas size * News, commentary style Cover entire canvas * Foreground fills screen * May crop to fit * Immersive experience ### Template Example ```bash theme={"dark"} curl -X POST https://api.videobgremover.com/v1/jobs/JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "composition", "composition": { "template": "ai_ugc_ad", "background_url": "https://example.com/background.mp4", "background_type": "video", "background_audio_enabled": true, "background_audio_volume": 0.8 } } }' ``` **SDK Support Coming Soon**: Python and Node.js SDK clients will support composition in an upcoming release. For now, use direct HTTP requests as shown above. *** ## Custom Composition Full control over positioning, sizing, and effects. ### Basic Custom Composition ```bash cURL - Image Background theme={"dark"} curl -X POST https://api.videobgremover.com/v1/jobs/JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "composition", "composition": { "background_url": "https://example.com/background.jpg", "background_type": "image", "position": "center", "size_mode": "canvas_percent", "size_percent": 50, "opacity": 1.0, "export_format": "h264", "export_crf": 23 } } }' ``` ```bash cURL - Video Background theme={"dark"} curl -X POST https://api.videobgremover.com/v1/jobs/JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "composition", "composition": { "background_url": "https://example.com/background.mp4", "background_type": "video", "background_audio_enabled": true, "background_audio_volume": 1.0, "position": "bottom_right", "size_mode": "canvas_percent", "size_percent": 30, "offset_x": -20, "offset_y": -20, "opacity": 0.95 } } }' ``` *** ## Positioning Control where your foreground appears on the canvas. ### Anchor Points Choose from 9 anchor positions:
📍 `top_left`
📍 `top_center`
📍 `top_right`
📍 `center_left`
📍 `center`
📍 `center_right`
📍 `bottom_left`
📍 `bottom_center`
📍 `bottom_right`
### Pixel Offsets Fine-tune position with pixel offsets from the anchor: ```json theme={"dark"} { "position": "bottom_right", "offset_x": -20, // 20px from right edge "offset_y": -20 // 20px from bottom edge } ``` ### Positioning Examples ```json theme={"dark"} { "position": "center", "offset_x": 0, "offset_y": 0 } ``` Perfect for standard layouts ```json theme={"dark"} { "position": "top_right", "offset_x": -10, "offset_y": 10 } ``` Logo or watermark placement ```json theme={"dark"} { "position": "bottom_left", "offset_x": 20, "offset_y": -20 } ``` Commentary or reaction video style *** ## Sizing Modes Control how your foreground is sized on the canvas. ### Size Mode Reference | Mode | Description | Use Case | Parameters | | -------------------- | --------------------------------------------- | -------------------- | -------------------------------------------- | | **`contain`** | Fit within canvas, preserve aspect ratio | Default, safe choice | None | | **`cover`** | Fill canvas, preserve aspect ratio (may crop) | Full coverage | None | | **`canvas_percent`** | Size as % of canvas | Precise control | `size_percent` | | **`px`** | Exact pixel dimensions | Fixed size | `size_width`, `size_height` | | **`scale`** | Scale relative to original | Proportional resize | `size_width`, `size_height` as scale factors | | **`fit_width`** | Fit to canvas width | Full width | None | | **`fit_height`** | Fit to canvas height | Full height | None | ### Sizing Examples ```json theme={"dark"} { "size_mode": "contain" } ``` Foreground fits within canvas, no cropping ```json theme={"dark"} { "size_mode": "canvas_percent", "size_percent": 50 } ``` Foreground is 50% of canvas dimensions ```json theme={"dark"} { "size_mode": "px", "size_width": 640, "size_height": 480 } ``` Foreground is exactly 640x480px ```json theme={"dark"} { "size_mode": "scale", "size_width": 0.75, "size_height": 0.75 } ``` Foreground scaled to 75% of original size *** ## Background Types ### Image Backgrounds Static image backgrounds (JPEG, PNG): ```json theme={"dark"} { "background_url": "https://example.com/background.jpg", "background_type": "image" } ``` **Perfect for:** Product showcases, simple layouts, photos ### Video Backgrounds Animated video backgrounds (MP4, WebM): ```json theme={"dark"} { "background_url": "https://example.com/background.mp4", "background_type": "video", "background_audio_enabled": true, "background_audio_volume": 0.7 } ``` **Perfect for:** Dynamic content, ads, music videos **Audio Mixing:** When `background_audio_enabled: true`, both background and foreground audio are mixed together. Adjust `background_audio_volume` (0.0 to 1.0) to balance the mix. *** ## Advanced Options ### Opacity Control Control foreground transparency: ```json theme={"dark"} { "opacity": 0.85 } ``` Values: `0.0` (fully transparent) to `1.0` (fully opaque) **Use cases:** * Watermarks (0.3 - 0.5) * Subtle overlays (0.6 - 0.8) * Normal composition (1.0) ### Export Quality Control output video quality: ```json theme={"dark"} { "export_format": "h264", "export_crf": 23 } ``` **CRF Values:** * `18` - Very high quality (larger files) * `23` - High quality (default, recommended) * `28` - Medium quality (smaller files) * `32` - Lower quality (smallest files) **CRF (Constant Rate Factor):** Lower values = better quality + larger files. Range: 0-51, default: 23. *** ## Complete Examples ### Social Media Ad Workflow ```bash theme={"dark"} #!/bin/bash API_KEY="vbr_your_api_key" VIDEO_URL="https://example.com/product-demo.mp4" BG_VIDEO="https://example.com/trendy-background.mp4" # 1. Create job JOB=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d "{\"video_url\": \"$VIDEO_URL\"}") JOB_ID=$(echo $JOB | jq -r '.id') echo "Created job: $JOB_ID" # 2. Start processing with composition curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "composition", "composition": { "template": "ai_ugc_ad", "background_url": "'"$BG_VIDEO"'", "background_type": "video", "background_audio_enabled": true, "background_audio_volume": 0.6 } } }' # 3. Poll for completion while true; do STATUS=$(curl -s -X GET https://api.videobgremover.com/v1/jobs/$JOB_ID/status \ -H "X-Api-Key: $API_KEY" | jq -r '.status') if [ "$STATUS" = "completed" ]; then VIDEO_URL=$(curl -s -X GET https://api.videobgremover.com/v1/jobs/$JOB_ID/status \ -H "X-Api-Key: $API_KEY" | jq -r '.processed_video_url') echo "✅ Composition complete!" echo "Download: $VIDEO_URL" break fi echo "Status: $STATUS - waiting..." sleep 10 done ``` **Python & Node.js SDK**: Composition support will be added to the SDK clients in an upcoming release. Use direct HTTP requests (cURL, axios, requests, etc.) for now. ### Picture-in-Picture News Style ```json theme={"dark"} { "background": { "type": "composition", "composition": { "background_url": "https://example.com/news-background.jpg", "background_type": "image", "position": "bottom_right", "size_mode": "canvas_percent", "size_percent": 25, "offset_x": -30, "offset_y": -30, "opacity": 1.0 } } } ``` ### Watermark Overlay ```json theme={"dark"} { "background": { "type": "composition", "composition": { "background_url": "https://example.com/main-video.mp4", "background_type": "video", "position": "top_right", "size_mode": "canvas_percent", "size_percent": 15, "offset_x": -20, "offset_y": 20, "opacity": 0.4 } } } ``` *** ## Parameter Reference ### Composition Object (Template) | Parameter | Type | Required | Default | Description | | -------------------------- | ------- | -------- | ----------- | -------------------------------------------------------------------------- | | `template` | string | ✅ Yes | - | Template name: `ai_ugc_ad`, `centered`, `picture_in_picture`, `fullscreen` | | `background_url` | string | ✅ Yes | - | URL to background image/video | | `background_type` | string | No | auto-detect | `image` or `video` | | `background_audio_enabled` | boolean | No | `false` | Enable background audio (video only) | | `background_audio_volume` | number | No | `1.0` | Audio volume (0.0 to 1.0) | | `export_format` | string | No | `h264` | Export codec | | `export_crf` | integer | No | `23` | Quality (0-51, lower = better) | ### Composition Object (Custom) | Parameter | Type | Required | Default | Description | | -------------------------- | ------- | ----------- | --------- | ------------------------------------ | | `background_url` | string | ✅ Yes | - | URL to background | | `background_type` | string | ✅ Yes | - | `color`, `image`, or `video` | | `background_color` | string | Conditional | - | Hex color (if type is `color`) | | `background_audio_enabled` | boolean | No | `false` | Enable audio | | `background_audio_volume` | number | No | `1.0` | Volume (0.0-1.0) | | `position` | string | No | `center` | Anchor point | | `offset_x` | integer | No | `0` | Horizontal offset (px) | | `offset_y` | integer | No | `0` | Vertical offset (px) | | `size_mode` | string | No | `contain` | Sizing mode | | `size_percent` | number | Conditional | - | Size % (if mode is `canvas_percent`) | | `size_width` | number | Conditional | - | Width value | | `size_height` | number | Conditional | - | Height value | | `opacity` | number | No | `1.0` | Opacity (0.0-1.0) | | `export_format` | string | No | `h264` | Export codec | | `export_crf` | integer | No | `23` | Quality (0-51) | *** ## Common Issues ### Background URL Not Accessible **Problem:** Composition fails with "Cannot download background" **Solution:** Ensure background URL is: * ✅ Publicly accessible (no authentication required) * ✅ Direct file link (not a webpage) * ✅ Supported format (JPEG, PNG for images; MP4, WebM for videos) ### Audio Not Playing **Problem:** Background audio is silent in final video **Solution:** ```json theme={"dark"} { "background_audio_enabled": true, // Must be true "background_audio_volume": 1.0 // 0.0 = silent, 1.0 = full volume } ``` ### Foreground Too Small/Large **Problem:** Foreground doesn't fit properly **Solution:** Try different size modes: * `contain` - Safest, fits within canvas * `canvas_percent` with `size_percent: 80` - 80% of canvas * Adjust `size_percent` value until it looks right ### Position Not Accurate **Problem:** Foreground not in expected position **Solution:** Use offset adjustments: ```json theme={"dark"} { "position": "bottom_right", "offset_x": -50, // Move 50px from right edge "offset_y": -50 // Move 50px from bottom edge } ``` *** ## Next Steps Complete REST API reference Advanced local composition with multiple layers More code examples and use cases Learn about transparent video formats # Webhooks - Real-Time Job Notifications Source: https://docs.videobgremover.com/guides/webhooks Get instant notifications when video processing completes. Learn how to use webhooks with cURL, API client, and SDKs instead of polling. ## Why Use Webhooks? Instead of repeatedly calling the API to check if your video is done (polling), webhooks notify you instantly when processing completes. ### Polling (Inefficient) ```typescript theme={"dark"} // ❌ Wastes resources, adds latency while (true) { const status = await client.status(jobId) if (status.status === 'completed') break await sleep(5000) // Check every 5 seconds } ``` ### Webhooks (Efficient) ```typescript theme={"dark"} // ✅ Instant notification, no wasted API calls await client.startJob(jobId, { webhook_url: 'https://your-app.com/webhooks/videobgremover', background: { type: 'transparent' } }) // Server notifies you when done ``` **Benefits:** * **Real-time**: Get notified instantly when processing completes * **Efficient**: No repeated API calls or bandwidth waste * **Scalable**: Process multiple videos without constant polling **When to use webhooks vs polling:** * ✅ **Use webhooks** for production apps, automation, background processing * ⚠️ **Use polling** for quick scripts, testing, or if you can't receive HTTP requests *** ## How VideoBGRemover Webhooks Work When you start a job with a `webhook_url`, our system: 1. **Validates** your webhook URL (HTTPS required in production) 2. **Stores** the URL with your job 3. **Triggers 3 events** during processing: * `job.started` - Processing begins * `job.completed` - Video ready (includes output URLs) * `job.failed` - Processing failed (includes error message) 4. **Sends POST request** to your URL with JSON payload 5. **Retries** up to 3 times (10 seconds apart) if delivery fails 6. **Waits** for BOTH background removal AND export to complete before final webhook The system waits for your complete video (with composition/export) before sending the `job.completed` webhook. This prevents premature notifications. *** ## Quick Setup Your webhook endpoint must: 1. Accept `POST` requests with `Content-Type: application/json` 2. Return a `2xx` status code quickly (\< 5 seconds) 3. Use HTTPS (production only - HTTP allowed for testing) *** ## Using Webhooks via cURL Add `webhook_url` to your job start request: ```bash theme={"dark"} # 1. Create job JOB=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: $API_KEY" \ -F "file=@video.mp4") JOB_ID=$(echo $JOB | jq -r '.id') # 2. Start job with webhook curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "webhook_url": "https://your-app.com/webhooks", "background": { "type": "transparent", "transparent_format": "webm_vp9" } }' ``` **Response:** ```json theme={"dark"} { "message": "Job started", "status": "processing", "webhook_url": "https://your-app.com/webhooks" } ``` *** ## Using Webhooks via API Client (Low-Level) Use the `VideoBGRemoverClient` class for direct API control: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient } from 'videobgremover' const client = new VideoBGRemoverClient(process.env.API_KEY!) // Create job from file const job = await client.createJobFile({ file: './video.mp4' }) // Start with webhook await client.startJob(job.id, { webhook_url: 'https://your-app.com/webhooks', background: { type: 'transparent', transparent_format: 'webm_vp9' } }) console.log('Job started, webhook will notify when complete') ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient import os client = VideoBGRemoverClient(api_key=os.getenv('API_KEY')) # Create job from file job = client.create_job_file({ 'file': './video.mp4' }) # Start with webhook client.start_job(job['id'], { 'webhook_url': 'https://your-app.com/webhooks', 'background': { 'type': 'transparent', 'transparent_format': 'webm_vp9' } }) print('Job started, webhook will notify when complete') ``` *** ## Using Webhooks via SDK (High-Level) Use the `Video` class for simpler workflows: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from 'videobgremover' const client = new VideoBGRemoverClient(process.env.API_KEY!) // Load video const video = await Video.open('./video.mp4') // Remove background with webhook const foreground = await video.removeBackground({ client, webhookUrl: 'https://your-app.com/webhooks', options: new RemoveBGOptions(Prefer.WEBM_VP9) }) console.log('Processing started, webhook will notify when complete') ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(api_key=os.getenv('API_KEY')) # Load video video = Video.open('./video.mp4') # Remove background with webhook foreground = video.remove_background( client, RemoveBGOptions(prefer=Prefer.WEBM_VP9), webhook_url='https://your-app.com/webhooks' ) print('Processing started, webhook will notify when complete') ``` Webhook support for the high-level `video.removeBackground()` SDK method is coming soon. For now, use the low-level `client.startJob()` API shown above for webhook functionality. *** ## Webhook Events & Payloads Your webhook endpoint will receive POST requests with these payloads: ### job.started Fires when processing begins. ```json theme={"dark"} { "event": "job.started", "timestamp": "2025-11-01T12:30:00.123Z", "job": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "processing", "filename": "my-video.mp4", "created_at": "2025-11-01T12:30:00.000Z" } } ``` ### job.completed Fires when BOTH background removal AND export complete. ```json theme={"dark"} { "event": "job.completed", "timestamp": "2025-11-01T12:35:00.456Z", "job": { "id": "550e8400-e29b-41d4-a716-446655440000", "export_id": "exp_webm_vp9_123", "status": "completed", "filename": "my-video.mp4", "length_seconds": 30.5, "output_format": "webm", "background": { "type": "transparent", "transparent_format": "webm_vp9" } } } ``` To download the processed video, call the status endpoint: `GET /v1/jobs/{id}/status` which returns the `processed_video_url` field with the download URL. ### job.failed Fires when processing or export fails. ```json theme={"dark"} { "event": "job.failed", "timestamp": "2025-11-01T12:32:00.789Z", "job": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "failed", "filename": "my-video.mp4", "message": "Video file too large: 1250.5MB exceeds limit of 1000MB" } } ``` ### HTTP Headers Webhooks include these headers: ```http theme={"dark"} POST /your/webhook/endpoint Content-Type: application/json User-Agent: VideoBGRemover-Webhooks/1.0 X-VideoBGRemover-Event: job.completed X-VideoBGRemover-Job-ID: 550e8400-e29b-41d4-a716-446655440000 X-VideoBGRemover-Timestamp: 2025-11-01T12:35:00.456Z X-VideoBGRemover-Attempt: 1 ``` *** ## Checking Delivery History View webhook delivery attempts and results: ### API Endpoint ```bash theme={"dark"} curl "https://api.videobgremover.com/v1/webhooks/deliveries?video_id=$JOB_ID" \ -H "X-Api-Key: $API_KEY" ``` ### SDK Methods ```typescript Node.js theme={"dark"} const deliveries = await client.webhookDeliveries(jobId) console.log(`Total deliveries: ${deliveries.total_deliveries}`) deliveries.deliveries.forEach(d => { console.log(`${d.event_type}: ${d.delivery_status} (attempt ${d.attempt_number})`) if (d.error_message) { console.log(` Error: ${d.error_message}`) } }) ``` ```python Python theme={"dark"} deliveries = client.webhook_deliveries(job_id) print(f"Total deliveries: {deliveries['total_deliveries']}") for d in deliveries['deliveries']: print(f"{d['event_type']}: {d['delivery_status']} (attempt {d['attempt_number']})") if d['error_message']: print(f" Error: {d['error_message']}") ``` **Response:** ```json theme={"dark"} { "video_id": "550e8400-e29b-41d4-a716-446655440000", "total_deliveries": 2, "deliveries": [ { "event_type": "job.started", "webhook_url": "https://your-app.com/webhooks", "attempt_number": 1, "delivery_status": "delivered", "http_status_code": 200, "error_message": null, "scheduled_at": "2025-11-01T12:30:00.000Z", "delivered_at": "2025-11-01T12:30:00.234Z" }, { "event_type": "job.completed", "webhook_url": "https://your-app.com/webhooks", "attempt_number": 1, "delivery_status": "delivered", "http_status_code": 200, "error_message": null, "scheduled_at": "2025-11-01T12:35:00.000Z", "delivered_at": "2025-11-01T12:35:00.567Z" } ] } ``` *** ## Best Practices ### Return 200 Immediately Process webhooks asynchronously to avoid timeouts: ```typescript theme={"dark"} // ✅ Good: Return immediately, process async app.post('/webhooks', async (req, res) => { res.status(200).send('OK') // Return first // Process async await processWebhook(req.body).catch(console.error) }) // ❌ Bad: Slow processing blocks response app.post('/webhooks', async (req, res) => { await downloadVideo(req.body.job.processed_video_url) // Slow! res.status(200).send('OK') // Timeout risk }) ``` ### Handle Retries Use `attempt_number` to detect retries: ```typescript theme={"dark"} app.post('/webhooks', (req, res) => { const { job } = req.body const attempt = parseInt(req.headers['x-videobgremover-attempt']) if (attempt > 1) { console.log(`Retry attempt ${attempt} for job ${job.id}`) } // Process idempotently res.status(200).send('OK') }) ``` ### Validate Events Check event type before processing: ```typescript theme={"dark"} const VALID_EVENTS = ['job.started', 'job.completed', 'job.failed'] if (!VALID_EVENTS.includes(req.body.event)) { return res.status(400).send('Invalid event') } ``` ### Use HTTPS Production webhooks require HTTPS for security. *** ## Common Issues ### Webhook Not Received 1. **Check delivery history** using the API or SDK 2. **Verify HTTPS** (required in production) 3. **Check firewall** - ensure your server is publicly accessible 4. **Test with webhook.site** to verify our system is sending correctly ### Duplicate Webhooks This is expected during retries. Implement idempotency: ```typescript theme={"dark"} const processedJobs = new Set() app.post('/webhooks', (req, res) => { const jobId = req.body.job.id if (processedJobs.has(jobId)) { return res.status(200).send('Already processed') } processedJobs.add(jobId) // Process webhook... }) ``` ### Timeout Errors * Optimize your webhook endpoint to respond in \< 5 seconds * Return 200 immediately, process asynchronously * Check delivery history to see timeout errors **Security Note:** Webhooks do not currently include HMAC signatures. Use unpredictable webhook URLs (include random tokens) and validate job IDs via the API if security is critical. *** ## Next Steps * [API Reference](/api-reference/introduction) - Complete API documentation * [Examples](/examples) - Webhook server code examples * [SDK Reference](/sdk-reference/client) - Full SDK documentation # Installation Guide | Install Video Background Remover SDK Source: https://docs.videobgremover.com/installation Install VideoBGRemover SDK for Python and Node.js. Complete setup guide with FFmpeg configuration and API key setup for video background removal. ## Choose Your SDK The VideoBGRemover SDKs provide a complete solution for background removal and video composition. Choose the SDK that matches your development environment: TypeScript-first SDK for Node.js applications Pythonic SDK with type hints and validation ## Installation ### Requirements ```bash Node.js theme={"dark"} # Requirements: # - Node.js 16+ # - FFmpeg (required for video composition) # - VideoBGRemover API key npm install @videobgremover/sdk ``` ```bash Python theme={"dark"} # Requirements: # - Python 3.9+ # - FFmpeg (required for video composition) # - VideoBGRemover API key pip install videobgremover ``` ### Verify Installation ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, Background, Composition } from '@videobgremover/sdk' // Check if FFmpeg is available import { MediaContext } from '@videobgremover/sdk' const ctx = new MediaContext() console.log('FFmpeg available:', ctx.checkWebmSupport()) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, Background, Composition from videobgremover import MediaContext # Check if FFmpeg is available ctx = MediaContext() print('FFmpeg available:', ctx.check_webm_support()) ``` ## FFmpeg Installation The SDKs require FFmpeg for video composition operations. Here's how to install it: ```bash macOS theme={"dark"} # Using Homebrew (recommended) brew install ffmpeg # Verify installation ffmpeg -version ffprobe -version ``` ```bash Ubuntu/Debian theme={"dark"} # Using apt sudo apt update sudo apt install ffmpeg # Verify installation ffmpeg -version ffprobe -version ``` ```cmd Windows theme={"dark"} # 1. Download FFmpeg from https://ffmpeg.org/download.html # 2. Extract to a folder (e.g., C:\ffmpeg) # 3. Add C:\ffmpeg\bin to your PATH environment variable # 4. Verify installation: ffmpeg -version ffprobe -version ``` ```dockerfile Docker theme={"dark"} # Add to your Dockerfile RUN apt-get update && apt-get install -y ffmpeg # Or use a base image with FFmpeg FROM node:18-alpine RUN apk add --no-cache ffmpeg ``` ## API Key Setup Get your API key from the [VideoBGRemover Dashboard](https://videobgremover.com/api-management): Sign up at [videobgremover.com](https://videobgremover.com) Buy credits for video processing Create an API key in the [API Management](https://videobgremover.com/api-management) dashboard ### Environment Setup ```bash Node.js theme={"dark"} # Set environment variable export VIDEOBGREMOVER_API_KEY="vbr_your_api_key_here" # Or use .env file echo "VIDEOBGREMOVER_API_KEY=vbr_your_api_key_here" > .env ``` ```bash Python theme={"dark"} # Set environment variable export VIDEOBGREMOVER_API_KEY="vbr_your_api_key_here" # Or use .env file echo "VIDEOBGREMOVER_API_KEY=vbr_your_api_key_here" > .env ``` ### Usage in Code ```typescript Node.js theme={"dark"} // In your code const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) ``` ```python Python theme={"dark"} import os from videobgremover import VideoBGRemoverClient # In your code client = VideoBGRemoverClient(os.getenv("VIDEOBGREMOVER_API_KEY")) ``` ## Verify Everything Works Test your complete setup with this simple example: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient } from '@videobgremover/sdk' async function test() { const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) // Check credits const credits = await client.credits() console.log(`✅ API connected. Credits: ${credits.remainingCredits}`) // Check FFmpeg const ctx = new MediaContext() const hasWebm = ctx.checkWebmSupport() console.log(`✅ FFmpeg ready. WebM support: ${hasWebm}`) } test() ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, MediaContext import os def test(): client = VideoBGRemoverClient(os.getenv("VIDEOBGREMOVER_API_KEY")) # Check credits credits = client.credits() print(f"✅ API connected. Credits: {credits.remaining_credits}") # Check FFmpeg ctx = MediaContext() has_webm = ctx.check_webm_support() print(f"✅ FFmpeg ready. WebM support: {has_webm}") test() ``` ## What's Next? Start removing backgrounds from your videos using AI Layer videos with custom backgrounds and effects # n8n Integration Source: https://docs.videobgremover.com/integrations/n8n Automate video background removal with n8n workflows. Connect to 400+ apps, batch process videos, and build custom automation. ## Overview [n8n](https://n8n.io) is a visual workflow automation platform that lets you connect apps and automate tasks without code. By integrating VideoBGRemover with n8n, you can: * **Batch process videos** automatically from Google Drive, Airtable, or any connected app * **Schedule video processing** with cron triggers for off-peak hours * **Chain workflows** by connecting to 400+ apps (Slack notifications, database updates, etc.) * **No coding required** - visual workflow builder with drag-and-drop nodes We provide two pre-built workflow templates to get you started instantly. *** ## Template 1: Video Composition Workflow ### What It Does Removes the background from a video, composites it onto a custom background, and uploads the final result to Google Drive. Perfect for: AI-generated videos (Sora, HeyGen), product demos, talking head videos, social media content. ### Workflow Steps ``` 1. Trigger (Webhook or Manual) ↓ 2. Create Job (POST /v1/jobs with video URL) ↓ 3. Start Composition (POST /v1/jobs/{id}/start with background) ↓ 4. Poll Status (GET /v1/jobs/{id}/status every 20 seconds) ↓ 5. Download Processed Video ↓ 6. Upload to Google Drive ``` ### API Key Required * **VIDEOBGREMOVER\_KEY** - Get from [API Management](https://videobgremover.com/api-management) ### Processing Time 3-5 minutes per minute of video ### Get the Template [**Import Workflow from GitHub →**](https://raw.githubusercontent.com/videobgremover/videobgremover-n8n-templates/main/templates/01-video-composition-gdrive.json) *** ## Template 2: AI UGC Ad Generator Workflow ### What It Does Complete AI pipeline that analyzes an app screen recording, generates a UGC-style ad script with AI actors, and composites everything into a final video. Perfect for: App developers, SaaS marketing teams, mobile app demos, feature announcements. ### Workflow Steps ``` 1. Upload App Screen Recording ↓ 2. Gemini AI Analysis - Analyzes app features - Generates ad script (hook, problem, solution, CTA) - Describes ideal AI actor ↓ 3. Sora 2 AI Video Generation - Creates AI actor video - Natural UGC-style delivery - 4-12 second duration ↓ 4. VideoBGRemover Composition - Removes actor background - Composites actor over app recording - Mixes audio (30% app + 100% actor) ↓ 5. Upload to Google Drive ``` ### API Keys Required * **GEMINI\_KEY** - Get from [Google AI Studio](https://aistudio.google.com/apikey) * **FAL\_KEY** - Get from [FAL AI Dashboard](https://fal.ai/dashboard/keys) * **VIDEOBGREMOVER\_KEY** - Get from [API Management](https://videobgremover.com/api-management) ### Processing Time 5-8 minutes total (Gemini: \~30s, Sora 2: \~2-4 min, VideoBGRemover: \~2-3 min) ### Get the Template [**Import Workflow from GitHub →**](https://raw.githubusercontent.com/videobgremover/videobgremover-n8n-templates/main/templates/02-ugc-screenrecord-video.json) *** ## Quick Start ### 1. Import Workflow to n8n In your n8n instance: * Go to **Workflows → Import from URL** * Paste the GitHub template URL (see above) * Click **Import** ### 2. Configure API Keys Add your API keys to n8n environment variables: ``` Settings → Variables → Add new variable For Template 1: - Name: VIDEOBGREMOVER_KEY - Value: vbr_your_key_here For Template 2 (add all three): - Name: GEMINI_KEY - Value: your_gemini_key - Name: FAL_KEY - Value: your_fal_key - Name: VIDEOBGREMOVER_KEY - Value: vbr_your_key_here ``` ### 3. Connect Google Drive * Click on the "Upload to Google Drive" node * Click **"Create New Credential"** * Follow the OAuth authorization flow * Select the folder where videos should be saved (optional) ### 4. Test the Workflow **For Template 1:** * Update the video URLs in the "Sample Video URLs" node * Click **"Execute Workflow"** * Wait 3-5 minutes for processing * Check Google Drive for the final video **For Template 2:** * Update the `screenshot_video_url` in the "Sample Input" node * Click **"Execute Workflow"** * Wait 5-8 minutes for processing * Check Google Drive for the UGC ad *** ## How the Workflows Work Both templates follow the same polling pattern used by our API: 1. **Create a job** by uploading your video (`POST /v1/jobs`) 2. **Start processing** with composition parameters (`POST /v1/jobs/{id}/start`) 3. **Poll the status** every 20 seconds (`GET /v1/jobs/{id}/status`) 4. **Download the video** when status is `completed` 5. **Upload to storage** (Google Drive) and return the shareable link The workflow handles: * ✅ Automatic status polling and retries * ✅ Error handling for failed jobs * ✅ Both webhook and manual triggers * ✅ Seamless Google Drive integration *** ## Automation Options ### Webhook Triggers Activate the workflow and use the webhook URL to trigger processing from external applications: ```bash theme={"dark"} curl -X POST https://your-n8n-instance.com/webhook/compose-video \ -H "Content-Type: application/json" \ -d '{ "foreground_video_url": "https://example.com/video.mp4", "background_video_url": "https://example.com/background.mp4" }' ``` ### Batch Processing Connect the workflow to: * **Google Sheets** - Process rows of video URLs * **Airtable** - Process database records * **Google Drive Watch** - Auto-process new uploads * **Cron Schedule** - Process videos at specific times ### Notifications Add nodes to send notifications when processing completes: * **Slack** - Post message with video link * **Discord** - Send webhook notification * **Email** - Send download link * **SMS** - Text notification via Twilio *** ## Resources * [**GitHub Templates Repository**](https://github.com/videobgremover/videobgremover-n8n-templates) - Full workflow JSON files and setup instructions * [**Blog Tutorial: Automate Video Backgrounds in n8n**](https://videobgremover.com/blog/automate-video-backgrounds-n8n) - Step-by-step guide with examples * [**Composition Builder**](https://videobgremover.com/composition-builder) - Visual tool to design composition parameters * [**API Reference**](/api-reference/introduction) - Complete API documentation * [**Video Composition Guide**](/video-composition/overview) - Understanding composition parameters * **Support** - Email us at [paul@videobgremover.com](mailto:paul@videobgremover.com) *** ## Next Steps Explore the full API documentation See code examples in Python, Node.js, and cURL Learn about composition templates and positioning Sign up and get your API key # Quick Start Guide | Remove Video Background in 5 Minutes Source: https://docs.videobgremover.com/quickstart Quickstart guide to remove video backgrounds with AI. Learn API and SDK basics for video background removal with code examples and best practices. ## 1. Install the SDK Choose your development environment and install the VideoBGRemover SDK: TypeScript-first SDK for Node.js applications Pythonic SDK with type hints and validation ### Node.js Installation ```bash npm theme={"dark"} npm install @videobgremover/sdk ``` ```bash yarn theme={"dark"} yarn add @videobgremover/sdk ``` ```bash pnpm theme={"dark"} pnpm add @videobgremover/sdk ``` ### Python Installation ```bash pip theme={"dark"} pip install videobgremover ``` ```bash poetry theme={"dark"} poetry add videobgremover ``` ```bash pipenv theme={"dark"} pipenv install videobgremover ``` ### FFmpeg Installation (Required) The SDK requires FFmpeg for video composition operations: ```bash macOS theme={"dark"} brew install ffmpeg ``` ```bash Ubuntu/Debian theme={"dark"} sudo apt install ffmpeg ``` ```bash Windows theme={"dark"} # Download from https://ffmpeg.org/download.html # Add to PATH environment variable ``` ## 2. Get Your API Key You'll need an API key for background removal: Visit [videobgremover.com](https://videobgremover.com) and create an account. Buy credits for video processing. Pricing is based on video duration. Go to [API Management](https://videobgremover.com/api-management) and create your first API key. ## 3. Remove Backgrounds Now you're ready to remove backgrounds from videos: ```typescript Node.js theme={"dark"} // Perfect for: Node.js apps, TypeScript projects import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('vbr_your_api_key') const video = Video.open('https://example.com/video.mp4') // Remove background (handles everything automatically) const transparent = await video.removeBackground(client) console.log('Background removed! Format:', transparent.getFormat()) ``` ```python Python theme={"dark"} # Perfect for: Python apps, data science, automation from videobgremover import VideoBGRemoverClient, Video client = VideoBGRemoverClient('vbr_your_api_key') video = Video.open('https://example.com/video.mp4') # Remove background (handles everything automatically) transparent = video.remove_background(client) print(f'Background removed! Format: {transparent.format}') ``` ```bash cURL theme={"dark"} # Perfect for: Simple scripts, webhooks, any language # 1. Create job from URL JOB_RESPONSE=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: vbr_your_api_key" \ -d '{"video_url": "https://example.com/video.mp4"}') JOB_ID=$(echo $JOB_RESPONSE | jq -r '.id') # 2. Start processing curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: vbr_your_api_key" \ -d '{"background": {"type": "transparent", "transparent_format": "webm_vp9"}}' # 3. Check status curl -X GET https://api.videobgremover.com/v1/jobs/$JOB_ID/status \ -H "X-Api-Key: vbr_your_api_key" ``` ## 4. Create Compositions After removing backgrounds, create professional video compositions: ```typescript Node.js theme={"dark"} import { Background, Composition, EncoderProfile, Anchor, SizeMode } from '@videobgremover/sdk' // 1. Create custom background const background = Background.fromColor('#FF0000', 1920, 1080, 30) // 2. Create composition const composition = new Composition(background) // 3. Add your transparent video composition.add(transparent, 'main_video') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) // 4. Export final video (local FFmpeg processing) await composition.toFile('final.mp4', EncoderProfile.h264()) console.log('✅ Composition created: final.mp4') ``` ```python Python theme={"dark"} from videobgremover import ( Background, Composition, EncoderProfile, Anchor, SizeMode ) # 1. Create custom background background = Background.from_color('#FF0000', 1920, 1080, 30) # 2. Create composition composition = Composition(background) # 3. Add your transparent video composition.add(transparent, 'main_video') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) # 4. Export final video (local FFmpeg processing) composition.to_file('final.mp4', EncoderProfile.h264()) print('✅ Composition created: final.mp4') ``` ## 5. Complete End-to-End Example Here's a complete workflow from background removal to final video: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode } from '@videobgremover/sdk' async function completeWorkflow() { // 1. Remove background (API call - uses credits) const client = new VideoBGRemoverClient('vbr_your_api_key') const video = Video.open('https://example.com/person.mp4') const transparent = await video.removeBackground(client) // 2. Create composition (local FFmpeg - no credits) const background = Background.fromImage('office.jpg', 30) const comp = new Composition(background) // 3. Position and layer comp.add(transparent, 'person') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) .opacity(0.95) // 4. Export final video await comp.toFile('person_in_office.mp4', EncoderProfile.h264()) console.log('✅ Complete! Person now appears in office background.') } completeWorkflow() ``` ```python Python theme={"dark"} from videobgremover import ( VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, Anchor, SizeMode ) def complete_workflow(): # 1. Remove background (API call - uses credits) client = VideoBGRemoverClient('vbr_your_api_key') video = Video.open('https://example.com/person.mp4') transparent = video.remove_background(client) # 2. Create composition (local FFmpeg - no credits) background = Background.from_image('office.jpg', fps=30) comp = Composition(background) # 3. Position and layer comp.add(transparent, 'person') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) \ .opacity(0.95) # 4. Export final video comp.to_file('person_in_office.mp4', EncoderProfile.h264()) print('✅ Complete! Person now appears in office background.') complete_workflow() ``` ## 6. What's Next? Complete guide to removing backgrounds with different methods Learn to create professional compositions with custom backgrounds Visual tool to design compositions Detailed SDK installation and FFmpeg setup See end-to-end examples and common patterns Explore the complete API and SDK documentation # VideoBGRemoverClient - Complete SDK API Reference Source: https://docs.videobgremover.com/sdk-reference/client Master the VideoBGRemoverClient SDK for seamless API integration. Learn authentication, credit management, background removal, and error handling. ## Overview The `VideoBGRemoverClient` handles all communication with the VideoBGRemover API for background removal operations. This is the **API layer** of the SDK - it handles authentication, job management, and credit tracking. **API Layer**: This class makes HTTP requests to our servers and consumes credits. For local video composition (no credits), see [Composition](/api-reference/sdk-reference/composition). ## Constructor ```typescript theme={"dark"} import { VideoBGRemoverClient } from '@videobgremover/sdk' // Basic initialization const client = new VideoBGRemoverClient('vbr_your_api_key') // With custom options const client = new VideoBGRemoverClient('vbr_your_api_key', { baseUrl: 'https://api.videobgremover.com', // Custom API endpoint timeout: 60000, // 60 second timeout headers: { 'Custom-Header': 'value' } }) ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient # Basic initialization client = VideoBGRemoverClient('vbr_your_api_key') # With custom options client = VideoBGRemoverClient( 'vbr_your_api_key', base_url='https://api.videobgremover.com', # Custom API endpoint timeout=60.0 # 60 second timeout ) ``` ### Parameters | Parameter | Type | Description | | ----------------- | -------- | ------------------------------------------------------------- | | `api_key` | `string` | Your VideoBGRemover API key (format: `vbr_` + 32 characters) | | `options.baseUrl` | `string` | API base URL (default: production) | | `options.timeout` | `number` | Request timeout in milliseconds (Node.js) or seconds (Python) | | `options.headers` | `object` | Additional HTTP headers | ## Methods ### credits() Check your current credit balance. ```typescript theme={"dark"} const credits = await client.credits() console.log(`Total: ${credits.totalCredits}`) console.log(`Remaining: ${credits.remainingCredits}`) console.log(`Used: ${credits.usedCredits}`) ``` **Returns**: `Promise` ```typescript theme={"dark"} interface Credits { totalCredits: number remainingCredits: number usedCredits: number } ``` ```python theme={"dark"} credits = client.credits() print(f"Total: {credits.total_credits}") print(f"Remaining: {credits.remaining_credits}") print(f"Used: {credits.used_credits}") ``` **Returns**: `CreditBalance` ```python theme={"dark"} class CreditBalance: total_credits: int remaining_credits: int used_credits: int ``` ### Low-Level API Methods These methods provide direct access to the REST API. Most users should use the high-level `Video.removeBackground()` method instead. #### createJobFile() Create a job for file upload. ```typescript theme={"dark"} const job = await client.createJobFile({ filename: 'my-video.mp4', content_type: 'video/mp4' }) console.log('Job ID:', job.id) console.log('Upload URL:', job.upload_url) console.log('Expires:', job.expires_at) ``` ```python theme={"dark"} from videobgremover.client.models import CreateJobFileUpload job = client.create_job_file(CreateJobFileUpload( filename='my-video.mp4', content_type='video/mp4' )) print(f"Job ID: {job['id']}") print(f"Upload URL: {job['upload_url']}") ``` #### createJobUrl() Create a job for URL download. ```typescript theme={"dark"} const job = await client.createJobUrl({ video_url: 'https://example.com/video.mp4' }) console.log('Job ID:', job.id) // Video downloads automatically ``` ```python theme={"dark"} from videobgremover.client.models import CreateJobUrlDownload job = client.create_job_url(CreateJobUrlDownload( video_url='https://example.com/video.mp4' )) print(f"Job ID: {job['id']}") ``` #### startJob() Start processing a job. ```typescript theme={"dark"} // Start with default settings (green screen) const result = await client.startJob(jobId) // Start with transparent output const result = await client.startJob(jobId, { background: { type: 'transparent', transparent_format: 'webm_vp9' } }) // Start with color background const result = await client.startJob(jobId, { background: { type: 'color', color: '#FF0000' } }) ``` ```python theme={"dark"} from videobgremover.client.models import StartJobRequest, BackgroundOptions # Start with default settings (green screen) result = client.start_job(job_id) # Start with transparent output result = client.start_job(job_id, StartJobRequest( background=BackgroundOptions( type='transparent', transparent_format='webm_vp9' ) )) # Start with color background result = client.start_job(job_id, StartJobRequest( background=BackgroundOptions( type='color', color='#FF0000' ) )) ``` #### status() Check job processing status. ```typescript theme={"dark"} const status = await client.status(jobId) console.log('Status:', status.status) // 'created', 'processing', 'completed', 'failed' console.log('Message:', status.message) if (status.status === 'completed') { console.log('Download URL:', status.processed_video_url) } ``` ```python theme={"dark"} status = client.status(job_id) print(f'Status: {status.status}') # 'created', 'processing', 'completed', 'failed' print(f'Message: {status.message}') if status.status == 'completed': print(f'Download URL: {status.processed_video_url}') ``` #### wait() Wait for a job to complete with polling. ```typescript theme={"dark"} // Wait with default settings const finalStatus = await client.wait(jobId) // Wait with custom options const finalStatus = await client.wait(jobId, { pollSeconds: 3.0, // Check every 3 seconds timeout: 300, // 5 minute timeout onStatus: (status) => { console.log(`Current status: ${status}`) } }) ``` ```python theme={"dark"} # Wait with default settings final_status = client.wait(job_id) # Wait with custom options def status_callback(status): print(f'Current status: {status}') final_status = client.wait( job_id, poll_seconds=3.0, # Check every 3 seconds timeout=300, # 5 minute timeout on_status=status_callback ) ``` #### deleteJob() Delete a job and all associated files. This action is permanent and cannot be undone. No credit refunds are provided. ```typescript theme={"dark"} const result = await client.deleteJob(jobId) console.log('Deleted:', result.id) console.log('Message:', result.message) ``` ```python theme={"dark"} result = client.delete_job(job_id) print(f"Deleted: {result['id']}") print(f"Message: {result['message']}") ``` **Returns**: `{ id: string, message: string }` | Field | Type | Description | | --------- | -------- | --------------------- | | `id` | `string` | ID of the deleted job | | `message` | `string` | Confirmation message | ## Error Handling The client throws specific exceptions for different error conditions: ```typescript theme={"dark"} import { ApiError, InsufficientCreditsError, JobNotFoundError, ProcessingError } from '@videobgremover/sdk' try { const transparent = await video.removeBackground({ client }) } catch (error) { if (error instanceof InsufficientCreditsError) { console.log('❌ Not enough credits') console.log('Remaining:', error.remainingCredits) } else if (error instanceof JobNotFoundError) { console.log('❌ Job not found') } else if (error instanceof ProcessingError) { console.log('❌ Processing failed:', error.message) } else if (error instanceof ApiError) { console.log('❌ API error:', error.message) } } ``` ```python theme={"dark"} from videobgremover.client.models import ( InsufficientCreditsError, JobNotFoundError, ProcessingError, ApiError ) try: transparent = video.remove_background(client) except InsufficientCreditsError as e: print('❌ Not enough credits') print(f'Remaining: {e.remaining_credits}') except JobNotFoundError: print('❌ Job not found') except ProcessingError as e: print(f'❌ Processing failed: {e}') except ApiError as e: print(f'❌ API error: {e}') ``` ## Usage with Video Class The recommended way to use the client is through the `Video` class: ```typescript theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('your_api_key') const video = Video.open('path/to/video.mp4') // High-level method (recommended) const transparent = await video.removeBackground({ client }) // With options const options = new RemoveBGOptions(Prefer.WEBM_VP9) const transparent = await video.removeBackground({ client, options }) ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer client = VideoBGRemoverClient('your_api_key') video = Video.open('path/to/video.mp4') # High-level method (recommended) transparent = video.remove_background(client) # With options options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) transparent = video.remove_background(client, options) ``` ## Best Practices ### Credit Management ```typescript theme={"dark"} // Always check credits before processing const credits = await client.credits() if (credits.remainingCredits < videoLengthInSeconds) { throw new Error('Not enough credits for this video') } ``` ### Error Recovery ```typescript theme={"dark"} // Implement retry logic for network issues async function removeBackgroundWithRetry(video, client, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { return await video.removeBackground({ client }) } catch (error) { if (error instanceof InsufficientCreditsError) { throw error // Don't retry credit issues } if (i === maxRetries - 1) throw error await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))) } } } ``` ### Timeout Handling ```typescript theme={"dark"} // Use appropriate timeouts for long videos const client = new VideoBGRemoverClient('your_key', { timeout: 120000 // 2 minutes for long videos }) ``` ## Related Classes * **[Video](/api-reference/sdk-reference/video)**: Video loading and background removal * **[Composition](/api-reference/sdk-reference/composition)**: Local video composition * **[EncoderProfile](/api-reference/sdk-reference/encoders)**: Export format configuration # Video Composition System - Complete SDK Reference Source: https://docs.videobgremover.com/sdk-reference/composition Master multi-layer video composition with VideoBGRemover SDK. Create, position, and export professional videos with anchors, sizing modes, and FFmpeg. ## Composition Class The `Composition` class is the core of the **media layer** - it handles local FFmpeg operations for professional video editing. No API calls or credits required. **Media Layer**: This class processes videos locally using FFmpeg. No internet connection or credits required. For background removal (API layer), see [VideoBGRemoverClient](/api-reference/sdk-reference/client). ### Creating Compositions ```typescript theme={"dark"} import { Composition, Background } from '@videobgremover/sdk' // With background const bg = Background.fromColor('#FF0000', 1920, 1080, 30) const comp = new Composition(bg) // With explicit canvas size const comp = Composition.canvas(1920, 1080, 30) // Empty composition (add background later) const comp = new Composition() comp.background(bg) ``` ```python theme={"dark"} from videobgremover import Composition, Background # With background bg = Background.from_color('#FF0000', 1920, 1080, 30) comp = Composition(bg) # With explicit canvas size comp = Composition.canvas(1920, 1080, 30) # Empty composition (add background later) comp = Composition() comp.background(bg) ``` ### Adding Layers Add transparent videos as layers in your composition: ```typescript theme={"dark"} // Add layer and get handle for configuration const layer = comp.add(transparent, 'main_video') // Configure the layer using fluent API layer.at(Anchor.CENTER) .size(SizeMode.CONTAIN) .opacity(0.9) // Or chain everything comp.add(transparent, 'pip') .at(Anchor.TOP_RIGHT, -50, 50) .size(SizeMode.CANVAS_PERCENT, { percent: 25 }) .start(5.0) .duration(10.0) .opacity(0.8) ``` ```python theme={"dark"} # Add layer and get handle for configuration layer = comp.add(transparent, 'main_video') # Configure the layer using fluent API layer.at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) \ .opacity(0.9) # Or chain everything comp.add(transparent, 'pip') \ .at(Anchor.TOP_RIGHT, dx=-50, dy=50) \ .size(SizeMode.CANVAS_PERCENT, percent=25) \ .start(5.0) \ .duration(10.0) \ .opacity(0.8) ``` ### Canvas Configuration ```typescript theme={"dark"} // Set explicit canvas dimensions const comp = new Composition(background) const resizedComp = comp.setCanvas(3840, 2160, 60) // 4K 60fps // Set explicit duration const timedComp = comp.setDuration(30.0) // Force 30-second duration ``` ```python theme={"dark"} # Set explicit canvas dimensions comp = Composition(background) comp.set_canvas(3840, 2160, 60) # 4K 60fps # Set explicit duration comp.set_duration(30.0) # Force 30-second duration ``` ### Export Methods ```typescript theme={"dark"} // Export to file await comp.toFile('output.mp4', EncoderProfile.h264()) // With progress tracking const progressCallback = (status: string) => { console.log(`Export: ${status}`) } await comp.toFile('output.mp4', EncoderProfile.h264(), progressCallback) // Verbose output for debugging await comp.toFile('output.mp4', EncoderProfile.h264(), undefined, true) // See FFmpeg command without executing const command = comp.dryRun() console.log('FFmpeg command:', command) ``` ```python theme={"dark"} # Export to file comp.to_file('output.mp4', EncoderProfile.h264()) # With progress tracking def progress_callback(status): print(f'Export: {status}') comp.to_file('output.mp4', EncoderProfile.h264(), on_progress=progress_callback) # Verbose output for debugging comp.to_file('output.mp4', EncoderProfile.h264(), verbose=True) # See FFmpeg command without executing command = comp.dry_run() print(f'FFmpeg command: {command}') ``` ## LayerHandle Class The `LayerHandle` provides a fluent API for configuring individual layers. You get a handle when calling `comp.add()`. ### Positioning Methods ```typescript theme={"dark"} const layer = comp.add(transparent, 'my_layer') // Basic anchor positioning layer.at(Anchor.CENTER) layer.at(Anchor.TOP_LEFT) layer.at(Anchor.BOTTOM_RIGHT) // With pixel offsets layer.at(Anchor.CENTER, 100, 50) // 100px right, 50px down layer.at(Anchor.TOP_RIGHT, -30, 30) // 30px from right edge, 30px from top // Custom expressions for dynamic positioning layer.xy('W/2 + 100*cos(2*PI*t/5)', 'H/2 + 100*sin(2*PI*t/5)') // Circular motion ``` ```python theme={"dark"} layer = comp.add(transparent, 'my_layer') # Basic anchor positioning layer.at(Anchor.CENTER) layer.at(Anchor.TOP_LEFT) layer.at(Anchor.BOTTOM_RIGHT) # With pixel offsets layer.at(Anchor.CENTER, dx=100, dy=50) # 100px right, 50px down layer.at(Anchor.TOP_RIGHT, dx=-30, dy=30) # 30px from right edge, 30px from top # Custom expressions for dynamic positioning layer.xy('W/2 + 100*cos(2*PI*t/5)', 'H/2 + 100*sin(2*PI*t/5)') # Circular motion ``` ### Sizing Methods ```typescript theme={"dark"} // Fit within canvas (letterbox if needed) layer.size(SizeMode.CONTAIN) // Fill canvas (crop if needed) layer.size(SizeMode.COVER) // Exact pixel dimensions layer.size(SizeMode.PX, { width: 800, height: 600 }) // Percentage of canvas layer.size(SizeMode.CANVAS_PERCENT, { percent: 50 }) // 50% square layer.size(SizeMode.CANVAS_PERCENT, { width: 75, height: 25 }) // 75% wide, 25% tall layer.size(SizeMode.CANVAS_PERCENT, { width: 60 }) // 60% wide, maintain aspect // Scale relative to original video layer.size(SizeMode.SCALE, { scale: 1.5 }) // 150% of original layer.size(SizeMode.SCALE, { width: 2.0, height: 0.8 }) // 200% wide, 80% tall // Fit to canvas dimensions layer.size(SizeMode.FIT_WIDTH) // Scale to match canvas width layer.size(SizeMode.FIT_HEIGHT) // Scale to match canvas height ``` ```python theme={"dark"} # Fit within canvas (letterbox if needed) layer.size(SizeMode.CONTAIN) # Fill canvas (crop if needed) layer.size(SizeMode.COVER) # Exact pixel dimensions layer.size(SizeMode.PX, width=800, height=600) # Percentage of canvas layer.size(SizeMode.CANVAS_PERCENT, percent=50) # 50% square layer.size(SizeMode.CANVAS_PERCENT, width=75, height=25) # 75% wide, 25% tall layer.size(SizeMode.CANVAS_PERCENT, width=60) # 60% wide, maintain aspect # Scale relative to original video layer.size(SizeMode.SCALE, scale=1.5) # 150% of original layer.size(SizeMode.SCALE, width=2.0, height=0.8) # 200% wide, 80% tall # Fit to canvas dimensions layer.size(SizeMode.FIT_WIDTH) # Scale to match canvas width layer.size(SizeMode.FIT_HEIGHT) # Scale to match canvas height ``` ### Visual Effects ```typescript theme={"dark"} // Opacity (0.0 = invisible, 1.0 = opaque) layer.opacity(0.8) // Rotation in degrees layer.rotate(15.0) // 15° clockwise layer.rotate(-45.0) // 45° counter-clockwise // Cropping (x, y, width, height) layer.crop(10, 20, 800, 600) // Z-order (higher = in front) layer.z(10) // Alpha channel control layer.alpha(true) // Use transparency (default) layer.alpha(false) // Ignore transparency (opaque) ``` ```python theme={"dark"} # Opacity (0.0 = invisible, 1.0 = opaque) layer.opacity(0.8) # Rotation in degrees layer.rotate(15.0) # 15° clockwise layer.rotate(-45.0) # 45° counter-clockwise # Cropping (x, y, width, height) layer.crop(10, 20, 800, 600) # Z-order (higher = in front) layer.z(10) # Alpha channel control layer.alpha(enabled=True) # Use transparency (default) layer.alpha(enabled=False) # Ignore transparency (opaque) ``` ### Timing Methods ```typescript theme={"dark"} // Composition timeline control layer.start(2.0) // Start at 2 seconds layer.end(10.0) // End at 10 seconds layer.duration(5.0) // Show for 5 seconds (from start time) // Source trimming (which part of source video to use) layer.subclip(5, 15) // Use seconds 5-15 of source video layer.subclip(3) // Use from 3 seconds to end of source ``` ```python theme={"dark"} # Composition timeline control layer.start(2.0) # Start at 2 seconds layer.end(10.0) # End at 10 seconds layer.duration(5.0) # Show for 5 seconds (from start time) # Source trimming (which part of source video to use) layer.subclip(5, 15) # Use seconds 5-15 of source video layer.subclip(3) # Use from 3 seconds to end of source ``` ### Audio Control ```typescript theme={"dark"} // Audio from this layer layer.audio(true, 1.0) // Enable audio at full volume layer.audio(true, 0.5) // Enable audio at 50% volume layer.audio(false) // Disable audio ``` ```python theme={"dark"} # Audio from this layer layer.audio(enabled=True, volume=1.0) # Enable audio at full volume layer.audio(enabled=True, volume=0.5) # Enable audio at 50% volume layer.audio(enabled=False) # Disable audio ``` ## Method Chaining All LayerHandle methods return the handle itself, allowing for fluent chaining: ```typescript theme={"dark"} // Chain multiple operations comp.add(transparent, 'complex_layer') .at(Anchor.TOP_RIGHT, -50, 50) // Position .size(SizeMode.CANVAS_PERCENT, { percent: 30 }) // Size .opacity(0.8) // Visual effect .rotate(10.0) // Visual effect .start(5.0) // Timing .duration(10.0) // Timing .audio(true, 0.7) // Audio .z(20) // Z-order ``` ```python theme={"dark"} # Chain multiple operations comp.add(transparent, 'complex_layer') \ .at(Anchor.TOP_RIGHT, dx=-50, dy=50) \ # Position .size(SizeMode.CANVAS_PERCENT, percent=30) \ # Size .opacity(0.8) \ # Visual effect .rotate(10.0) \ # Visual effect .start(5.0) \ # Timing .duration(10.0) \ # Timing .audio(enabled=True, volume=0.7) \ # Audio .z(20) # Z-order ``` ## Duration Control Compositions follow a simple 3-rule system for determining duration: ### Rule 1: Video Background Controls Duration ```typescript theme={"dark"} // 30-second background video = 30-second composition const bg = Background.fromVideo('30sec_background.mp4') const comp = new Composition(bg) comp.add(shortForeground) // Even if foreground is 5 seconds // Final video: 30 seconds ``` ```python theme={"dark"} # 30-second background video = 30-second composition bg = Background.from_video('30sec_background.mp4') comp = Composition(bg) comp.add(short_foreground) # Even if foreground is 5 seconds # Final video: 30 seconds ``` ### Rule 2: Color/Image Backgrounds Use Longest Foreground ```typescript theme={"dark"} // Color background adapts to content const bg = Background.fromColor('#FF0000', 1920, 1080, 30) const comp = new Composition(bg) comp.add(tenSecondVideo) // 10-second video comp.add(fiveSecondVideo) // 5-second video // Final video: 10 seconds (longest foreground) ``` ```python theme={"dark"} # Color background adapts to content bg = Background.from_color('#FF0000', 1920, 1080, 30) comp = Composition(bg) comp.add(ten_second_video) # 10-second video comp.add(five_second_video) # 5-second video # Final video: 10 seconds (longest foreground) ``` ### Rule 3: Explicit Duration Override ```typescript theme={"dark"} // Force specific duration const comp = new Composition(anyBackground) comp.setDuration(45.0) // Force 45-second duration comp.add(video) // Final video: exactly 45 seconds ``` ```python theme={"dark"} # Force specific duration comp = Composition(any_background) comp.set_duration(45.0) # Force 45-second duration comp.add(video) # Final video: exactly 45 seconds ``` ## Audio System The composition system automatically handles audio from multiple sources: ### Single Audio Source ```typescript theme={"dark"} // Only one layer has audio - used directly comp.add(videoWithAudio, 'main').audio(true, 1.0) comp.add(videoNoAudio, 'overlay').audio(false) ``` ```python theme={"dark"} # Only one layer has audio - used directly comp.add(video_with_audio, 'main').audio(enabled=True, volume=1.0) comp.add(video_no_audio, 'overlay').audio(enabled=False) ``` ### Multiple Audio Sources ```typescript theme={"dark"} // Multiple layers with audio - automatically mixed comp.add(narrator, 'voice').audio(true, 0.8) // Main audio at 80% comp.add(background, 'music').audio(true, 0.3) // Background music at 30% comp.add(effects, 'sfx').audio(true, 0.6) // Sound effects at 60% // System automatically creates audio mix ``` ```python theme={"dark"} # Multiple layers with audio - automatically mixed comp.add(narrator, 'voice').audio(enabled=True, volume=0.8) # Main audio at 80% comp.add(background, 'music').audio(enabled=True, volume=0.3) # Background music at 30% comp.add(effects, 'sfx').audio(enabled=True, volume=0.6) # Sound effects at 60% # System automatically creates audio mix ``` ## Advanced Examples ### Multi-Layer News Layout ```typescript theme={"dark"} // News broadcast layout const comp = new Composition(Background.fromColor('#1E293B', 1920, 1080, 30)) // Main presenter (center-right) comp.add(presenter, 'presenter') .at(Anchor.CENTER_RIGHT, -100) .size(SizeMode.CANVAS_PERCENT, { percent: 55 }) // Breaking news ticker (bottom) comp.add(tickerVideo, 'ticker') .at(Anchor.BOTTOM_CENTER, 0, -20) .size(SizeMode.CANVAS_PERCENT, { width: 90, height: 8 }) // Logo (top-left) comp.add(logoVideo, 'logo') .at(Anchor.TOP_LEFT, 30, 30) .size(SizeMode.CANVAS_PERCENT, { percent: 12 }) .opacity(0.9) await comp.toFile('news_broadcast.mp4', EncoderProfile.h264()) ``` ```python theme={"dark"} # News broadcast layout comp = Composition(Background.from_color('#1E293B', 1920, 1080, 30)) # Main presenter (center-right) comp.add(presenter, 'presenter') \ .at(Anchor.CENTER_RIGHT, dx=-100) \ .size(SizeMode.CANVAS_PERCENT, percent=55) # Breaking news ticker (bottom) comp.add(ticker_video, 'ticker') \ .at(Anchor.BOTTOM_CENTER, dy=-20) \ .size(SizeMode.CANVAS_PERCENT, width=90, height=8) # Logo (top-left) comp.add(logo_video, 'logo') \ .at(Anchor.TOP_LEFT, dx=30, dy=30) \ .size(SizeMode.CANVAS_PERCENT, percent=12) \ .opacity(0.9) comp.to_file('news_broadcast.mp4', EncoderProfile.h264()) ``` ### Timed Presentation ```typescript theme={"dark"} // Presentation with timed elements const comp = new Composition(Background.fromImage('slide_bg.jpg', 30)) // Speaker appears throughout comp.add(speaker, 'speaker') .at(Anchor.CENTER_LEFT, 100) .size(SizeMode.CANVAS_PERCENT, { percent: 40 }) // Slide 1: 0-10 seconds comp.add(slide1, 'slide1') .start(0).duration(10) .at(Anchor.CENTER_RIGHT, -100) .size(SizeMode.CANVAS_PERCENT, { percent: 45 }) // Slide 2: 10-20 seconds comp.add(slide2, 'slide2') .start(10).duration(10) .at(Anchor.CENTER_RIGHT, -100) .size(SizeMode.CANVAS_PERCENT, { percent: 45 }) // Conclusion: 20-25 seconds comp.add(conclusion, 'conclusion') .start(20).duration(5) .at(Anchor.CENTER) .size(SizeMode.CONTAIN) ``` ```python theme={"dark"} # Presentation with timed elements comp = Composition(Background.from_image('slide_bg.jpg', fps=30)) # Speaker appears throughout comp.add(speaker, 'speaker') \ .at(Anchor.CENTER_LEFT, dx=100) \ .size(SizeMode.CANVAS_PERCENT, percent=40) # Slide 1: 0-10 seconds comp.add(slide1, 'slide1') \ .start(0).duration(10) \ .at(Anchor.CENTER_RIGHT, dx=-100) \ .size(SizeMode.CANVAS_PERCENT, percent=45) # Slide 2: 10-20 seconds comp.add(slide2, 'slide2') \ .start(10).duration(10) \ .at(Anchor.CENTER_RIGHT, dx=-100) \ .size(SizeMode.CANVAS_PERCENT, percent=45) # Conclusion: 20-25 seconds comp.add(conclusion, 'conclusion') \ .start(20).duration(5) \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) ``` ## Debugging ### Dry Run See the FFmpeg command without executing: ```typescript theme={"dark"} const command = comp.dryRun() console.log('FFmpeg command:') console.log(command) // Example output: // ffmpeg -y -f lavfi -i color=c=#FF0000:size=1920x1080:rate=30 // -i transparent.webm -filter_complex "[1:v]scale=1920:1080:force_original_aspect_ratio=decrease[layer_0_scale];[0:v][layer_0_scale]overlay=x='(W-w)/2':y='(H-h)/2'[out]" // -map [out] -map 1:a? -c:v libx264 -crf 18 -preset medium output.mp4 ``` ```python theme={"dark"} command = comp.dry_run() print('FFmpeg command:') print(command) # Example output: # ffmpeg -y -f lavfi -i color=c=#FF0000:size=1920x1080:rate=30 # -i transparent.webm -filter_complex "[1:v]scale=1920:1080:force_original_aspect_ratio=decrease[layer_0_scale];[0:v][layer_0_scale]overlay=x='(W-w)/2':y='(H-h)/2'[out]" # -map [out] -map 1:a? -c:v libx264 -crf 18 -preset medium output.mp4 ``` ### Verbose Export See FFmpeg output in real-time: ```typescript theme={"dark"} // Show FFmpeg output for debugging await comp.toFile('debug.mp4', EncoderProfile.h264(), undefined, true) ``` ```python theme={"dark"} # Show FFmpeg output for debugging comp.to_file('debug.mp4', EncoderProfile.h264(), verbose=True) ``` ## Related Classes * **[Background](/video-composition/backgrounds)**: Background creation guide * **[EncoderProfile](/api-reference/sdk-reference/encoders)**: Export format configuration * **[Video](/api-reference/sdk-reference/video)**: Video loading and background removal * **[Positioning Guide](/video-composition/positioning)**: Complete positioning and sizing guide * **[Timing Guide](/video-composition/timing)**: Timeline and duration control # EncoderProfile | Remove Video Background Export Formats Source: https://docs.videobgremover.com/sdk-reference/encoders Complete reference for EncoderProfile class. Learn how to configure H.264 MP4, VP9 WebM, ProRes MOV, and PNG sequence exports with optimal quality settings. ## Overview The `EncoderProfile` class configures how your compositions are exported. It handles video codecs, quality settings, and format-specific options for FFmpeg. **H.264 MP4, VP9 WebM** - Universal compatibility **ProRes MOV, PNG Sequence** - Maximum quality ## Standard Formats ### H.264 MP4 (Recommended) Universal compatibility with excellent compression: ```typescript theme={"dark"} import { EncoderProfile } from '@videobgremover/sdk' // Default settings (CRF 18, medium preset) const encoder = EncoderProfile.h264() // Custom quality settings const hq = EncoderProfile.h264({ crf: 15, // Higher quality (12-18 = excellent) preset: 'slow' // Better compression, slower encoding }) // Fast encoding for testing const fast = EncoderProfile.h264({ crf: 28, // Lower quality for speed preset: 'ultrafast' // Fastest encoding }) // Web delivery optimized const web = EncoderProfile.h264({ crf: 26, // Good quality for web preset: 'medium' // Balanced speed/compression }) ``` ```python theme={"dark"} from videobgremover import EncoderProfile # Default settings (CRF 18, medium preset) encoder = EncoderProfile.h264() # Custom quality settings hq = EncoderProfile.h264( crf=15, # Higher quality (12-18 = excellent) preset='slow' # Better compression, slower encoding ) # Fast encoding for testing fast = EncoderProfile.h264( crf=28, # Lower quality for speed preset='ultrafast' # Fastest encoding ) # Web delivery optimized web = EncoderProfile.h264( crf=26, # Good quality for web preset='medium' # Balanced speed/compression ) ``` ### VP9 WebM Excellent compression for web delivery: ```typescript theme={"dark"} // Default VP9 settings const encoder = EncoderProfile.vp9() // Custom VP9 settings const webOptimized = EncoderProfile.vp9({ crf: 32, // Good quality for web (30-35 typical) preset: 'fast' // Reasonable encoding speed }) // High quality VP9 const hqVp9 = EncoderProfile.vp9({ crf: 24, // Higher quality preset: 'slow' // Better compression }) ``` ```python theme={"dark"} # Default VP9 settings encoder = EncoderProfile.vp9() # Custom VP9 settings web_optimized = EncoderProfile.vp9( crf=32, # Good quality for web (30-35 typical) preset='fast' # Reasonable encoding speed ) # High quality VP9 hq_vp9 = EncoderProfile.vp9( crf=24, # Higher quality preset='slow' # Better compression ) ``` ## Professional Formats ### ProRes 4444 MOV Highest quality for professional video editing: ```typescript theme={"dark"} // ProRes 4444 (highest quality, large files) const prores = EncoderProfile.prores4444() // Perfect for: Final Cut Pro, Premiere Pro, DaVinci Resolve await comp.toFile('professional.mov', prores) ``` ```python theme={"dark"} # ProRes 4444 (highest quality, large files) prores = EncoderProfile.prores_4444() # Perfect for: Final Cut Pro, Premiere Pro, DaVinci Resolve comp.to_file('professional.mov', prores) ``` ### PNG Sequence Frame-by-frame output for maximum quality: ```typescript theme={"dark"} // PNG sequence (one file per frame) const png = EncoderProfile.pngSequence() await comp.toFile('frames/frame_%04d.png', png) // Custom frame rate const png24 = EncoderProfile.pngSequence({ fps: 24 }) await comp.toFile('frames/frame_%04d.png', png24) // Creates: frame_0001.png, frame_0002.png, frame_0003.png, ... ``` ```python theme={"dark"} # PNG sequence (one file per frame) png = EncoderProfile.png_sequence() comp.to_file('frames/frame_%04d.png', png) # Custom frame rate png24 = EncoderProfile.png_sequence(fps=24) comp.to_file('frames/frame_%04d.png', png24) # Creates: frame_0001.png, frame_0002.png, frame_0003.png, ... ``` ## Transparent Formats Perfect for further compositing or overlaying on other content: ### Transparent WebM ```typescript theme={"dark"} // Transparent WebM with alpha channel const transparent = EncoderProfile.transparentWebm() // Custom quality for transparency const hqTransparent = EncoderProfile.transparentWebm({ crf: 20 // Higher quality for clean edges }) await comp.toFile('overlay.webm', transparent) ``` ```python theme={"dark"} # Transparent WebM with alpha channel transparent = EncoderProfile.transparent_webm() # Custom quality for transparency hq_transparent = EncoderProfile.transparent_webm(crf=20) comp.to_file('overlay.webm', transparent) ``` **WebM Transparency**: Requires `libvpx-vp9` decoder for proper alpha channel support. The SDK automatically detects and uses the correct decoder when available. ## Specialized Formats ### Stacked Video Debug format showing video and mask: ```typescript theme={"dark"} // Stacked video (top: video, bottom: mask) const stacked = EncoderProfile.stackedVideo() // Custom layout const horizontal = EncoderProfile.stackedVideo({ layout: 'horizontal' // Side-by-side instead of stacked }) await comp.toFile('debug.mp4', stacked) ``` ```python theme={"dark"} # Stacked video (top: video, bottom: mask) stacked = EncoderProfile.stacked_video() # Custom layout horizontal = EncoderProfile.stacked_video(layout='horizontal') comp.to_file('debug.mp4', stacked) ``` ## Quality Guidelines ### CRF Values (Constant Rate Factor) Lower CRF = Higher quality, larger files: | CRF Range | Quality | Use Case | File Size | | --------- | ---------- | ----------------------------- | ---------- | | **12-18** | Excellent | Professional work, archival | Large | | **19-23** | High | General purpose, good balance | Medium | | **24-28** | Good | Web delivery, streaming | Small | | **29-35** | Acceptable | Previews, low bandwidth | Very Small | ### Encoding Presets Balance between speed and compression efficiency: | Preset | Speed | Compression | Use Case | | ------------- | -------- | ----------- | ----------------------------- | | **ultrafast** | Fastest | Poor | Testing, previews | | **fast** | Fast | Good | Development, iteration | | **medium** | Moderate | Better | General purpose | | **slow** | Slow | Best | Final delivery | | **veryslow** | Slowest | Excellent | Archival, maximum compression | ## Platform-Specific Recommendations ### Social Media ```typescript theme={"dark"} // Instagram feed/reels const instagram = EncoderProfile.h264({ crf: 25, preset: 'medium' }) ``` ```typescript theme={"dark"} // TikTok vertical videos const tiktok = EncoderProfile.h264({ crf: 26, preset: 'fast' }) ``` ```typescript theme={"dark"} // YouTube high quality const youtube = EncoderProfile.h264({ crf: 20, preset: 'slow' }) ``` ### Professional Workflows ```typescript theme={"dark"} // Final Cut Pro / Premiere Pro const editing = EncoderProfile.prores4444() // DaVinci Resolve const grading = EncoderProfile.h264({ crf: 12, preset: 'slow' }) // After Effects const png = EncoderProfile.pngSequence({ fps: 30 }) ``` ```python theme={"dark"} # Final Cut Pro / Premiere Pro editing = EncoderProfile.prores_4444() # DaVinci Resolve grading = EncoderProfile.h264(crf=12, preset='slow') # After Effects png = EncoderProfile.png_sequence(fps=30) ``` ## Custom Arguments Access the raw FFmpeg arguments for advanced use: ```typescript theme={"dark"} const encoder = EncoderProfile.h264({ crf: 20, preset: 'medium' }) // Get FFmpeg arguments const args = encoder.args('output.mp4') console.log('FFmpeg args:', args) // Example output: // ['-c:v', 'libx264', '-crf', '20', '-preset', 'medium', 'output.mp4'] ``` ```python theme={"dark"} encoder = EncoderProfile.h264(crf=20, preset='medium') # Get FFmpeg arguments args = encoder.args('output.mp4') print(f'FFmpeg args: {args}') # Example output: # ['-c:v', 'libx264', '-crf', '20', '-preset', 'medium', 'output.mp4'] ``` ## Encoder Properties ```typescript theme={"dark"} const encoder = EncoderProfile.h264({ crf: 20, preset: 'fast' }) console.log('Kind:', encoder.kind) // 'h264' console.log('CRF:', encoder.crf) // 20 console.log('Preset:', encoder.preset) // 'fast' ``` ```python theme={"dark"} encoder = EncoderProfile.h264(crf=20, preset='fast') print(f'Kind: {encoder.kind}') # 'h264' print(f'CRF: {encoder.crf}') # 20 print(f'Preset: {encoder.preset}') # 'fast' ``` ## Complete Export Example ```typescript theme={"dark"} // Create composition const comp = new Composition(background) comp.add(video1, 'main').at(Anchor.CENTER) comp.add(video2, 'pip').at(Anchor.TOP_RIGHT).size(SizeMode.CANVAS_PERCENT, { percent: 25 }) // Export in multiple formats console.log('Exporting preview...') await comp.toFile('preview.mp4', EncoderProfile.h264({ crf: 30, preset: 'ultrafast' })) console.log('Exporting high quality...') await comp.toFile('final.mp4', EncoderProfile.h264({ crf: 18, preset: 'slow' })) console.log('Exporting web version...') await comp.toFile('web.webm', EncoderProfile.vp9({ crf: 28 })) console.log('Exporting for editing...') await comp.toFile('edit.mov', EncoderProfile.prores4444()) console.log('✅ All exports complete!') ``` ```python theme={"dark"} # Create composition comp = Composition(background) comp.add(video1, 'main').at(Anchor.CENTER) comp.add(video2, 'pip').at(Anchor.TOP_RIGHT).size(SizeMode.CANVAS_PERCENT, percent=25) # Export in multiple formats print('Exporting preview...') comp.to_file('preview.mp4', EncoderProfile.h264(crf=30, preset='ultrafast')) print('Exporting high quality...') comp.to_file('final.mp4', EncoderProfile.h264(crf=18, preset='slow')) print('Exporting web version...') comp.to_file('web.webm', EncoderProfile.vp9(crf=28)) print('Exporting for editing...') comp.to_file('edit.mov', EncoderProfile.prores_4444()) print('✅ All exports complete!') ``` ## Format Comparison | Format | Quality | File Size | Speed | Use Case | | -------------------- | --------- | ---------- | ----- | -------------------- | | **H.264 CRF 18** | Excellent | Large | Fast | General purpose | | **H.264 CRF 28** | Good | Small | Fast | Web delivery | | **VP9 CRF 28** | Good | Very Small | Slow | Web optimized | | **ProRes 4444** | Perfect | Very Large | Fast | Professional editing | | **PNG Sequence** | Perfect | Huge | Fast | Frame-by-frame work | | **Transparent WebM** | High | Small | Slow | Further compositing | ## Advanced Settings ### Custom H.264 Settings ```typescript theme={"dark"} // Professional broadcast settings const broadcast = EncoderProfile.h264({ crf: 16, // Broadcast quality preset: 'slow', // Maximum compression efficiency profile: 'high', // H.264 profile (if supported) level: '4.1' // H.264 level (if supported) }) // Streaming optimized const streaming = EncoderProfile.h264({ crf: 24, preset: 'veryfast', // Fast encoding for live streaming tune: 'zerolatency' // Low latency (if supported) }) ``` ```python theme={"dark"} # Professional broadcast settings broadcast = EncoderProfile.h264( crf=16, # Broadcast quality preset='slow', # Maximum compression efficiency # profile='high', # H.264 profile (if supported) # level='4.1' # H.264 level (if supported) ) # Streaming optimized streaming = EncoderProfile.h264( crf=24, preset='veryfast', # Fast encoding for live streaming # tune='zerolatency' # Low latency (if supported) ) ``` ### File Size Estimation Approximate file sizes for different settings (30-second 1080p video): ```typescript theme={"dark"} // Ultra high quality: ~100MB const uhq = EncoderProfile.h264({ crf: 12, preset: 'veryslow' }) // High quality: ~50MB const hq = EncoderProfile.h264({ crf: 18, preset: 'slow' }) // Good quality: ~25MB const good = EncoderProfile.h264({ crf: 23, preset: 'medium' }) // Web quality: ~15MB const web = EncoderProfile.h264({ crf: 28, preset: 'fast' }) // Preview quality: ~8MB const preview = EncoderProfile.h264({ crf: 32, preset: 'ultrafast' }) ``` ## Troubleshooting ### Encoding Errors Common encoding issues and solutions: #### Unknown Codec ``` Error: Unknown encoder 'libx264' ``` **Solution**: Install FFmpeg with H.264 support #### Out of Memory ``` Error: Cannot allocate memory ``` **Solutions**: * Reduce video resolution * Use faster preset * Process shorter segments #### Slow Encoding **Solutions**: * Use faster preset (`fast`, `ultrafast`) * Reduce quality (higher CRF value) * Use fewer layers in composition ### Quality Issues #### Blocky/Pixelated Output **Solutions**: * Lower CRF value (higher quality) * Use slower preset for better compression * Check source video quality #### Large File Sizes **Solutions**: * Increase CRF value (lower quality) * Use VP9 instead of H.264 * Use faster preset (less compression efficiency) ## Related Classes * **[Composition](/api-reference/sdk-reference/composition)**: Video composition system * **[Export Formats Guide](/video-composition/export-formats)**: Complete export format guide * **[Background](/video-composition/backgrounds)**: Background creation * **[Positioning Guide](/video-composition/positioning)**: Layer positioning and sizing # Video & Foreground Classes - Video Background Removal SDK Source: https://docs.videobgremover.com/sdk-reference/video Complete guide to Video and Foreground classes in VideoBGRemover SDK. Learn video loading, AI-powered background removal, and transparent video handling. ## Video Class The `Video` class represents a source video file or URL. It's the starting point for background removal operations. ### Loading Videos ```typescript theme={"dark"} import { Video } from '@videobgremover/sdk' // From local file const video = Video.open('path/to/video.mp4') // From URL const video = Video.open('https://example.com/video.mp4') // From file with metadata const video = Video.open('video.mov', { contentType: 'video/mov' }) ``` ```python theme={"dark"} from videobgremover import Video # From local file video = Video.open('path/to/video.mp4') # From URL video = Video.open('https://example.com/video.mp4') # From file with metadata video = Video.open('video.mov', content_type='video/mov') ``` ### Background Removal The main method for removing backgrounds using the API: ```typescript theme={"dark"} import { VideoBGRemoverClient, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('your_api_key') const video = Video.open('input.mp4') // Basic background removal const transparent = await video.removeBackground({ client }) // With format preference const options = new RemoveBGOptions(Prefer.WEBM_VP9) const transparent = await video.removeBackground({ client, options }) // With progress tracking const statusCallback = (status: string) => { console.log(`Status: ${status}`) } const transparent = await video.removeBackground({ client, options, waitPollSeconds: 2.0, // Poll every 2 seconds onStatus: statusCallback }) ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient, RemoveBGOptions, Prefer client = VideoBGRemoverClient('your_api_key') video = Video.open('input.mp4') # Basic background removal transparent = video.remove_background(client) # With format preference options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) transparent = video.remove_background(client, options) # With progress tracking def status_callback(status): print(f'Status: {status}') transparent = video.remove_background( client, options, poll_seconds=2.0, on_status=status_callback ) ``` #### Parameters | Parameter | Type | Description | | ------------- | ---------------------- | -------------------------------------- | | `client` | `VideoBGRemoverClient` | Authenticated API client | | `options` | `RemoveBGOptions` | Processing options (optional) | | `pollSeconds` | `number` | Status polling interval (default: 2.0) | | `onStatus` | `function` | Progress callback (optional) | #### Returns Returns a `Foreground` object representing the transparent video. ## Foreground Class The `Foreground` class represents a transparent video after background removal. It can be used in compositions. ### Creating Foregrounds ```typescript theme={"dark"} import { Foreground } from '@videobgremover/sdk' // From API background removal (most common) const transparent = await video.removeBackground({ client }) // From existing transparent files const webm = Foreground.fromWebmVp9('transparent.webm') const prores = Foreground.fromMovProres('transparent.mov') const stacked = Foreground.fromStackedVideo('stacked.mp4') const bundle = Foreground.fromProBundleZip('bundle.zip') // Auto-detect format from file extension const auto = Foreground.fromFile('transparent.webm') // Detects WebM VP9 // From URL with format specification const url = Foreground.fromUrl('https://example.com/transparent.webm', { format: 'webm_vp9' }) ``` ```python theme={"dark"} from videobgremover import Foreground # From API background removal (most common) transparent = video.remove_background(client) # From existing transparent files webm = Foreground.from_webm_vp9('transparent.webm') prores = Foreground.from_mov_prores('transparent.mov') stacked = Foreground.from_stacked_video('stacked.mp4') bundle = Foreground.from_pro_bundle_zip('bundle.zip') # Auto-detect format from file extension auto = Foreground.from_file('transparent.webm') # Detects WebM VP9 ``` ### Foreground Properties ```typescript theme={"dark"} // Get format information console.log('Format:', transparent.getFormat()) // 'webm_vp9', 'mov_prores', etc. console.log('Primary path:', transparent.primaryPath) console.log('Mask path:', transparent.maskPath) // For pro_bundle format console.log('Audio path:', transparent.audioPath) // For pro_bundle format // Check if it's a URL console.log('Is URL:', transparent.isUrl()) ``` ```python theme={"dark"} # Get format information print(f'Format: {transparent.format}') # 'webm_vp9', 'mov_prores', etc. print(f'Primary path: {transparent.primary_path}') print(f'Mask path: {transparent.mask_path}') # For pro_bundle format print(f'Audio path: {transparent.audio_path}') # For pro_bundle format ``` ### Source Trimming Use only specific parts of your transparent videos: ```typescript theme={"dark"} // Use seconds 5-15 of the transparent video const trimmed = transparent.subclip(5, 15) // Use from 10 seconds to end const fromMiddle = transparent.subclip(10) // Original remains unchanged console.log('Original trim:', transparent.sourceTrim) // undefined console.log('Trimmed:', trimmed.sourceTrim) // [5, 15] ``` ```python theme={"dark"} # Use seconds 5-15 of the transparent video trimmed = transparent.subclip(5, 15) # Use from 10 seconds to end from_middle = transparent.subclip(10) # Original remains unchanged print(f'Original trim: {transparent.source_trim}') # None print(f'Trimmed: {trimmed.source_trim}') # (5, 15) ``` ## RemoveBGOptions Configure background removal processing: ```typescript theme={"dark"} import { RemoveBGOptions, Prefer, Model } from '@videobgremover/sdk' // Default options (uses videobgremover-original model) const options = new RemoveBGOptions() // Prefer specific format const webmOptions = new RemoveBGOptions(Prefer.WEBM_VP9) const proResOptions = new RemoveBGOptions(Prefer.MOV_PRORES) const stackedOptions = new RemoveBGOptions(Prefer.STACKED_VIDEO) // Using factory methods const autoOptions = RemoveBGOptions.default() const specificOptions = RemoveBGOptions.withPrefer(Prefer.WEBM_VP9) ``` ```python theme={"dark"} from videobgremover import RemoveBGOptions, Prefer, Model # Default options (uses videobgremover-original model) options = RemoveBGOptions() # Prefer specific format webm_options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) prores_options = RemoveBGOptions(prefer=Prefer.MOV_PRORES) stacked_options = RemoveBGOptions(prefer=Prefer.STACKED_VIDEO) ``` ### Format Preferences | Prefer | Best For | File Size | Compatibility | | --------------- | ----------------------- | --------- | ------------- | | `WEBM_VP9` | Web apps, APIs | Small | Good | | `MOV_PRORES` | Professional editing | Large | Excellent | | `STACKED_VIDEO` | Universal compatibility | Medium | Universal | | `PRO_BUNDLE` | Advanced workflows | Medium | Universal | | `AUTO` | Let system choose | Varies | Good | ## Complete Example Here's a complete example showing video loading, background removal, and basic composition: ```typescript theme={"dark"} import { VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, RemoveBGOptions, Prefer, Anchor, SizeMode } from '@videobgremover/sdk' async function completeExample() { // 1. Initialize client const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) // 2. Check credits const credits = await client.credits() console.log(`Credits available: ${credits.remainingCredits}`) // 3. Load and process video const video = Video.open('https://example.com/input.mp4') const options = new RemoveBGOptions(Prefer.WEBM_VP9) console.log('Removing background...') const transparent = await video.removeBackground({ client, options }) // 4. Create composition const background = Background.fromColor('#00FF00', 1920, 1080, 30) const comp = new Composition(background) comp.add(transparent, 'main').at(Anchor.CENTER).size(SizeMode.CONTAIN) // 5. Export await comp.toFile('output.mp4', EncoderProfile.h264()) console.log('✅ Complete workflow finished!') } ``` ```python theme={"dark"} from videobgremover import ( VideoBGRemoverClient, Video, Background, Composition, EncoderProfile, RemoveBGOptions, Prefer, Anchor, SizeMode ) import os def complete_example(): # 1. Initialize client client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) # 2. Check credits credits = client.credits() print(f'Credits available: {credits.remaining_credits}') # 3. Load and process video video = Video.open('https://example.com/input.mp4') options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) print('Removing background...') transparent = video.remove_background(client, options) # 4. Create composition background = Background.from_color('#00FF00', 1920, 1080, 30) comp = Composition(background) comp.add(transparent, 'main').at(Anchor.CENTER).size(SizeMode.CONTAIN) # 5. Export comp.to_file('output.mp4', EncoderProfile.h264()) print('✅ Complete workflow finished!') ``` ## Related Classes * **[VideoBGRemoverClient](/api-reference/sdk-reference/client)**: API client for authentication and job management * **[Composition](/api-reference/sdk-reference/composition)**: Video composition and layering * **[Background](/video-composition/backgrounds)**: Background creation guide * **[EncoderProfile](/api-reference/sdk-reference/encoders)**: Export format configuration # How to Remove Video Background | Guide Source: https://docs.videobgremover.com/video-background-removal/guide Step-by-step guide to remove video backgrounds with AI. Learn SDK methods, API calls, and troubleshooting for professional video background removal. ## Choose Your Approach There are two main ways to remove backgrounds from videos: **Best for**: Complete workflows, video composition **Language**: Node.js, Python **Features**: Automatic error handling, progress tracking **Best for**: Simple scripts, custom integrations **Language**: Any (HTTP requests) **Features**: Full control, webhook integration ## SDK Method (Recommended) The easiest way to get started with background removal: ```typescript theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('vbr_your_api_key') // Load video from file or URL const video = Video.open('https://example.com/video.mp4') // Configure output format (optional) const options = new RemoveBGOptions(Prefer.WEBM_VP9) // Remove background (handles everything automatically) const transparent = await video.removeBackground({ client, options }) console.log('Background removed! Download URL:', transparent.primaryPath) console.log('Format:', transparent.getFormat()) ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) # Load video from file or URL video = Video.open('https://example.com/video.mp4') # Configure output format (optional) options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) # Remove background (handles everything automatically) transparent = video.remove_background(client, options) print(f'Background removed! Download URL: {transparent.primary_path}') print(f'Format: {transparent.format}') ``` ### SDK Features * **Automatic Error Handling**: SDK catches and explains common errors * **Progress Tracking**: Optional callbacks for processing status * **Format Selection**: Easy format configuration * **File Management**: Handles uploads and downloads automatically ## Direct API Method For custom integrations and maximum control: ### URL Workflow Perfect when your videos are already hosted online: ```json theme={"dark"} POST /v1/jobs { "video_url": "https://example.com/video.mp4" } ``` **Response:** Job ID with `uploaded` status (ready to process) ```json theme={"dark"} POST /v1/jobs/{id}/start { "background": { "type": "transparent", "transparent_format": "webm_vp9" } } ``` **Credits deducted here** based on video length ```bash theme={"dark"} GET /v1/jobs/{id}/status ``` Poll until status is `completed`, then download from provided URLs ## Real-time Notifications with Webhooks Instead of polling the status endpoint, get instant notifications when processing completes: ```typescript Node.js SDK theme={"dark"} // Start processing with webhook notification const result = await video.removeBackground({client, { webhookUrl: 'https://your-app.com/api/webhooks', background: { type: 'transparent', transparentFormat: 'webm_vp9' } }}) console.log('✅ Job started! Webhook will notify when complete') ``` ```python Python SDK theme={"dark"} # Start processing with webhook notification result = video.remove_background(client, RemoveBGOptions( webhook_url='https://your-app.com/api/webhooks', background_type='transparent', transparent_format='webm_vp9' )) print('✅ Job started! Webhook will notify when complete') ``` ```bash cURL theme={"dark"} curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "webhook_url": "https://your-app.com/api/webhooks", "background": { "type": "transparent", "transparent_format": "webm_vp9" } }' ``` **Webhook Payload:** ```json theme={"dark"} { "event": "job.completed", "timestamp": "2025-10-02T10:30:00Z", "job": { "id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "processed_video_url": "https://storage.googleapis.com/.../video.webm", // ... full job status (same as GET /v1/jobs/{id}/status) } } ``` Your webhook endpoint must return a 2xx status code within 30 seconds. For detailed webhook implementation, see the [webhook deliveries endpoint documentation](/api-reference/all-endpoints). ### File Upload Workflow For local video files: ```json theme={"dark"} POST /v1/jobs { "filename": "my-video.mp4", "content_type": "video/mp4" } ``` **Response:** Upload URL and job ID ```bash theme={"dark"} PUT [upload_url] Content-Type: video/mp4 [Raw video file bytes] ``` **Note:** This is a direct upload to cloud storage ```json theme={"dark"} POST /v1/jobs/{id}/start { "background": { "type": "transparent", "transparent_format": "webm_vp9" } } ``` **Credits deducted here** based on video length ```bash theme={"dark"} GET /v1/jobs/{id}/status ``` Poll until status is `completed`, then download from provided URLs ### Complete Examples ```bash theme={"dark"} # 1. Create job from URL JOB_RESPONSE=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{"video_url": "https://example.com/video.mp4"}') JOB_ID=$(echo $JOB_RESPONSE | jq -r '.id') # 2. Start processing with color background curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "color", "color": "#FF0000" } }' # 3. Check status curl -X GET https://api.videobgremover.com/v1/jobs/$JOB_ID/status \ -H "X-Api-Key: $API_KEY" ``` ```bash theme={"dark"} # 1. Create job for file upload JOB_RESPONSE=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{"filename": "my-video.mp4", "content_type": "video/mp4"}') JOB_ID=$(echo $JOB_RESPONSE | jq -r '.id') UPLOAD_URL=$(echo $JOB_RESPONSE | jq -r '.upload_url') # 2. Upload video file curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: video/mp4" \ --data-binary @my-video.mp4 # 3. Start processing with transparent background curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "webm_vp9" } }' # 4. Check status curl -X GET https://api.videobgremover.com/v1/jobs/$JOB_ID/status \ -H "X-Api-Key: $API_KEY" ``` ```typescript theme={"dark"} import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('vbr_your_api_key') const video = Video.open('https://example.com/video.mp4') const transparent = await video.removeBackground({ client }) console.log('Background removed! Download URL:', transparent.primaryPath) console.log('Format:', transparent.getFormat()) ``` ```typescript theme={"dark"} import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('vbr_your_api_key') const video = Video.open('path/to/local/video.mp4') const transparent = await video.removeBackground({ client }) console.log('Background removed! Download URL:', transparent.primaryPath) console.log('Format:', transparent.getFormat()) ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open(src='https://example.com/video.mp4') transparent = video.remove_background(client) print(f'Background removed! Download URL: {transparent.primary_path}') print(f'Format: {transparent.format}') ``` ```python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open(src='path/to/local/video.mp4') transparent = video.remove_background(client) print(f'Background removed! Download URL: {transparent.primary_path}') print(f'Format: {transparent.format}') ``` ## Error Handling ### Common Issues ```typescript theme={"dark"} try { const transparent = await video.removeBackground({ client }) } catch (error) { if (error.message.includes('credits')) { console.log('❌ Not enough credits. Please top up your account.') } } ``` ```python theme={"dark"} try: transparent = video.remove_background(client) except Exception as e: if 'credits' in str(e).lower(): print('❌ Not enough credits. Please top up your account.') ``` ```typescript theme={"dark"} try { const transparent = await video.removeBackground({ client }) } catch (error) { if (error.message.includes('API key')) { console.log('❌ Invalid API key. Check your credentials.') } } ``` ```python theme={"dark"} try: transparent = video.remove_background(client) except Exception as e: if 'api key' in str(e).lower(): print('❌ Invalid API key. Check your credentials.') ``` ```bash theme={"dark"} # Check file size before processing FILE_SIZE=$(stat -f%z video.mp4 2>/dev/null || stat -c%s video.mp4) MAX_SIZE=$((100*1024*1024)) # 100MB in bytes if [ "$FILE_SIZE" -gt "$MAX_SIZE" ]; then echo "❌ File too large: $FILE_SIZE bytes (max: $MAX_SIZE)" exit 1 fi ``` ### API-Specific Errors | Error Code | Description | Solution | | ---------- | -------------------- | ------------------------------------ | | `401` | Invalid API key | Check key format and permissions | | `402` | Insufficient credits | Top up your account | | `413` | File too large | Reduce file size or use URL workflow | | `404` | Job not found | Verify job ID and API key match | | `422` | Invalid parameters | Check request format | ## Background Options with cURL Here are the correct cURL commands for different background types: ```bash theme={"dark"} # Red background curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "color", "color": "#FF0000" } }' # Green screen (chroma key) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "color", "color": "#00FF00" } }' # Blue background curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "color", "color": "#0000FF" } }' ``` ```bash theme={"dark"} # WebM VP9 (recommended) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "webm_vp9" } }' # MOV ProRes (professional editing) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "mov_prores" } }' # Stacked Video (universal compatibility) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "stacked_video" } }' ``` ## Format Selection Choose the format that best fits your workflow: | Format | Best For | File Size | SDK Support | | ----------------- | ----------------------- | --------- | -------------- | | **WebM VP9** | Web apps, APIs | Small | ✅ Full support | | **MOV ProRes** | Professional editing | Large | ✅ Full support | | **Stacked Video** | Universal compatibility | Medium | ✅ Full support | | **Pro Bundle** | Advanced workflows | Medium | ✅ Full support | | **PNG Sequence** | Frame-by-frame work | Large | ✅ Full support | **Note**: For detailed technical usage of each format, see the [Output Formats Guide](/video-background-removal/output-formats). ## Performance Tips ### For Large Files * Use URL workflow for files >100MB * Process long videos in segments * Consider reducing resolution before processing ### For Batch Processing * Process videos sequentially, not in parallel * Implement retry logic for network issues * Monitor credit usage to avoid depletion ### For Production Use * Use webhooks for real-time notifications (see above) * Use background threads for processing * Implement proper error handling and retry logic * Store job IDs for status tracking * Monitor your credit usage and balance ## What's Next? Layer your transparent video with colors, images, or videos Technical details for using different transparent video formats # Background Removal Models Source: https://docs.videobgremover.com/video-background-removal/models Four AI models: Original (highest quality), Light (1.5x faster), Pro (text prompts), and Human (2x faster, portrait-optimized). ## Model Comparison VideoBGRemover offers four AI models to fit different use cases: Highest quality segmentation with detailed edge detection. Best for complex scenes. * **Quality**: Highest * **Speed**: Standard * **Text Prompts**: ✅ Supported * **Pricing**: 60 credits/min (1.0 credits/sec) Fast and efficient processing optimized for speed. Great for simple backgrounds. * **Quality**: High * **Speed**: 2x faster ⚡ * **Pricing**: 45 credits/min (0.75 credits/sec) - 25% cheaper Advanced background removal for complex objects. Enables text prompting for precise segmentation. * **Quality**: Highest * **Speed**: Slowest * **Text Prompts**: ✅ Supported * **Pricing**: 180 credits/min (3.0 credits/sec) Fast matting algorithm optimized for portraits and facing people. * **Quality**: High * **Speed**: Fastest ⚡⚡ * **Best For**: Human subjects * **Pricing**: 45 credits/min (0.75 credits/sec) - 25% cheaper *** ## Quick Comparison | Feature | Original | Light | Pro | Human | | -------------------- | ------------------------------------- | ----------------------------------- | ---------------------------------------- | -------------------------------- | | **Model** | videobgremover-original | videobgremover-light | videobgremover-pro | videobgremover-human | | **Quality** | Highest | High | Highest | High | | **Processing Speed** | Standard | 2x faster | Slowest | Fastest | | **Pricing** | 60 credits/min (1.0/sec) | 45 credits/min (0.75/sec) | 180 credits/min (3.0/sec) | 45 credits/min (0.75/sec) | | **Text Prompts** | ✅ | ❌ | ✅ | ❌ | | **Best For** | Complex scenes, detailed segmentation | Fast processing, simple backgrounds | Complex objects, text-based segmentation | Human portraits, face cam videos | *** ## When to Use Each Model ### videobgremover-original (Default) Use this model when you need: * **Highest quality** segmentation with precise edge detection * **Complex scenes** with multiple objects or complex movement * **Professional output** for client deliverables * **Challenging scenarios** that require the best possible accuracy **Example use cases:** * Professional video production * E-commerce product videos with complex products * Videos with multiple subjects or objects * Content with complex movement or camera motion **Pricing**: 60 credits/min (1.0 credits/sec) *** ### videobgremover-light Use this model when you need: * **Fast processing** (2x faster than original) * **Cost savings** (25% cheaper) * **Face cam or talking head videos** (single person content) * **High volume** processing where speed matters **Example use cases:** * Face cam videos and presentations * UGC (user-generated content) with people talking * Social media content with single subjects * Quick prototypes or drafts **Pricing**: 45 credits/min (0.75 credits/sec) - 25% cheaper than original *** ### videobgremover-pro Use this model when you need: * **Text-based prompting** to specify exactly what to keep * **Complex object segmentation** (cars, furniture, animals, etc.) * **Precise control** over what gets removed * **Specific subject isolation** using natural language **Example use cases:** * Product videos where you want to isolate specific items ("red car", "wooden chair") * Animal videos ("golden retriever", "black cat") * Complex scenes with multiple objects where you need to keep specific ones * Videos where automatic detection struggles **Text prompt examples:** * "person wearing red jacket" * "golden retriever dog" * "car with blue paint" * "wooden table" **Pricing**: 180 credits/min (3.0 credits/sec) Text prompts work with `videobgremover-original` and `videobgremover-pro`. Use `prompt.mode: "text"` with natural language descriptions. *** ### videobgremover-human Use this model when you need: * **Fastest processing speed** * **Cost savings** (25% cheaper, same as Light) * **Human-focused videos** (portraits, face cam, talking heads) * **Real-time performance** for high volume processing **Example use cases:** * Portrait videos and headshots * Face cam content and webcam recordings * Talking head videos for courses or tutorials * Social media content with people facing the camera * High-volume human-centric processing **Pricing**: 45 credits/min (0.75 credits/sec) - 25% cheaper than original This model is optimized specifically for human subjects. For non-human objects or complex scenes, use `videobgremover-original` or `videobgremover-pro`. *** ## Usage Examples ### Using Models via API Client (Low-Level) ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient } from 'videobgremover' const client = new VideoBGRemoverClient(process.env.API_KEY!) // Create job const job = await client.createJobUrl({ video_url: 'https://example.com/video.mp4' }) // Option 1: Original model (default, highest quality) await client.startJob(job.id, { model: 'videobgremover-original', background: { type: 'transparent', transparent_format: 'webm_vp9' } }) // Option 2: Light model (25% cheaper, 1.5x faster) await client.startJob(job.id, { model: 'videobgremover-light', background: { type: 'transparent', transparent_format: 'webm_vp9' } }) // Option 3: Pro model with text prompt await client.startJob(job.id, { model: 'videobgremover-pro', prompt: { mode: 'text', text: 'person wearing red jacket' }, background: { type: 'transparent', transparent_format: 'webm_vp9' } }) // Option 4: Human model (50% cheaper, 2x faster, optimized for people) await client.startJob(job.id, { model: 'videobgremover-human', background: { type: 'transparent', transparent_format: 'webm_vp9' } }) // Wait for completion const result = await client.wait(job.id) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient import os client = VideoBGRemoverClient(api_key=os.getenv('API_KEY')) # Create job job = client.create_job_url({'video_url': 'https://example.com/video.mp4'}) # Option 1: Original model (default, highest quality) client.start_job(job['id'], { 'model': 'videobgremover-original', 'background': {'type': 'transparent', 'transparent_format': 'webm_vp9'} }) # Option 2: Light model (25% cheaper, 1.5x faster) client.start_job(job['id'], { 'model': 'videobgremover-light', 'background': {'type': 'transparent', 'transparent_format': 'webm_vp9'} }) # Option 3: Pro model with text prompt client.start_job(job['id'], { 'model': 'videobgremover-pro', 'prompt': {'mode': 'text', 'text': 'person wearing red jacket'}, 'background': {'type': 'transparent', 'transparent_format': 'webm_vp9'} }) # Option 4: Human model (50% cheaper, 2x faster, optimized for people) client.start_job(job['id'], { 'model': 'videobgremover-human', 'background': {'type': 'transparent', 'transparent_format': 'webm_vp9'} }) # Wait for completion result = client.wait(job['id']) ``` *** ### Using Models via cURL ```bash theme={"dark"} # Create job JOB=$(curl -s -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: $API_KEY" \ -F "file=@video.mp4") JOB_ID=$(echo $JOB | jq -r '.id') # Option 1: Light model (25% cheaper, 1.5x faster) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "videobgremover-light", "background": {"type": "transparent", "transparent_format": "webm_vp9"} }' # Option 2: Pro model with text prompt curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "videobgremover-pro", "prompt": {"mode": "text", "text": "golden retriever dog"}, "background": {"type": "transparent", "transparent_format": "webm_vp9"} }' # Option 3: Human model (50% cheaper, 2x faster) curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "videobgremover-human", "background": {"type": "transparent", "transparent_format": "webm_vp9"} }' ``` *** ## Pricing Examples ### 30-second video | Model | Calculation | Credits | Savings | | ------------ | ----------- | -------------- | ----------------------- | | **Original** | `30 × 1.0` | **30 credits** | - | | **Light** | `30 × 0.75` | **23 credits** | 7 credits (23% cheaper) | | **Pro** | `30 × 3.0` | **90 credits** | - | | **Human** | `30 × 0.75` | **23 credits** | 7 credits (23% cheaper) | ### 2-minute video | Model | Calculation | Credits | Savings | | ------------ | ------------ | --------------- | ------------------------ | | **Original** | `120 × 1.0` | **120 credits** | - | | **Light** | `120 × 0.75` | **90 credits** | 30 credits (25% cheaper) | | **Pro** | `120 × 3.0` | **360 credits** | - | | **Human** | `120 × 0.75` | **90 credits** | 30 credits (25% cheaper) | ### 5-minute video | Model | Calculation | Credits | Savings | | ------------ | ------------ | --------------- | ------------------------ | | **Original** | `300 × 1.0` | **300 credits** | - | | **Light** | `300 × 0.75` | **225 credits** | 75 credits (25% cheaper) | | **Pro** | `300 × 3.0` | **900 credits** | - | | **Human** | `300 × 0.75` | **225 credits** | 75 credits (25% cheaper) | **FPS-Based Pricing**: High frame rate videos consume additional credits. Videos at 31-60 FPS use 2x credits, 61-120 FPS use 3x credits, and >120 FPS use 4x credits (standard ≤30 FPS videos use 1x). This multiplier applies to all models. *** ## Default Behavior If you don't specify a model: * ✅ **API**: Defaults to `videobgremover-original` * ✅ **SDK**: Defaults to `videobgremover-original` * ✅ **Web UI**: Uses `videobgremover-original` *** ## Model Selection Tips **Choosing the right model:** * **Human subjects?** → Use `videobgremover-human` (fastest speed) * **Need text prompts?** → Use `videobgremover-original` (best quality) or `videobgremover-pro` (complex objects) * **Complex scenes?** → Use `videobgremover-original` (highest quality) * **Fast & cheap?** → Use `videobgremover-light` (2x faster than original) or `videobgremover-human` (fastest) Model selection cannot be changed after job starts. Choose your model when calling `startJob()`. **Pro tip**: Start with `videobgremover-light` or `videobgremover-human` for prototyping, then switch to `videobgremover-original` for final output. Use text prompts with `videobgremover-original` for best quality when targeting specific objects. *** ## Next Steps Complete guide to background removal Choose WebM, ProRes, PNG sequence, etc. Credit packages and billing # Transparent Video Formats | WebM VP9, MOV ProRes Source: https://docs.videobgremover.com/video-background-removal/output-formats Complete guide to transparent video formats. Learn about WebM VP9, MOV ProRes, PNG sequences, and Pro Bundle formats for video background removal. ## Overview The VideoBGRemover API offers multiple background options for different use cases. This guide covers the technical details of each format and how to use them in your projects. For complete workflows and implementation examples, see the [Background Removal Guide](/video-background-removal/guide). Replace background with solid colors using hex codes Create videos with transparency for custom overlays *** ## Quick Navigation * [Simple Colors](#simple-color-replacement) * [Popular Colors](#popular-colors) * [Custom Hex Codes](#custom-hex-codes) * [WebM VP9 (Recommended)](#webm-vp9-recommended) * [MOV ProRes (Professional)](#mov-prores-professional) * [PNG Sequence (Frame-by-Frame)](#png-sequence) * [Pro Bundle (Advanced)](#pro-bundle-professional-workflow) * [Stacked Video (Analysis)](#stacked-video-analysis-format) ## Color Backgrounds Perfect for simple background replacement with solid colors. No additional processing needed - just specify a hex color code. ### Simple Color Replacement Replace the background with any solid color using hex codes: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Start job with red background directly const finalStatus = await video.removeBackground({ client, options: { background: { type: 'color', color: '#FF0000' } }}) console.log('Red background video URL:', finalStatus.processed_video_url) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Start job with red background directly final_status = video.remove_background(client, { 'background': {'type': 'color', 'color': '#FF0000'} }) print(f'Red background video URL: {final_status.processed_video_url}') ``` ```bash cURL theme={"dark"} # Start processing with color background curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "color", "color": "#FF0000" } }' ``` ### Popular Colors | Color | Hex Code | Use Case | | --------- | --------- | ------------------------ | | 🔴 Red | `#FF0000` | Bold, attention-grabbing | | 🟢 Green | `#00FF00` | Chroma key standard | | 🔵 Blue | `#0000FF` | Professional, clean | | ⚪ White | `#FFFFFF` | Clean, minimal | | ⚫ Black | `#000000` | Dramatic, cinematic | | 🎨 Custom | `#7C3AED` | Any hex code | *** ## Transparent Formats For advanced compositing, custom backgrounds, and professional workflows. These formats preserve transparency for maximum flexibility. **What are transparent formats?** Video files that preserve the alpha channel (transparency) so you can overlay them on custom backgrounds. However, they can be tricky to use - WebM works in Chrome but not all browsers, MOV works in Safari but requires specific codecs. When you need custom backgrounds or advanced compositing, use transparent formats: ### Format Comparison | Format | File Size | Quality | Use Case | Compatibility | | ----------------- | ------------- | ------------ | ------------------------------------------------- | -------------------- | | **WebM VP9** | 🟢 Small | 🟢 Excellent | Easy overlay, API usage | Requires VP9 decoder | | **MOV ProRes** | 🔴 Very Large | 🟢 Perfect | Large files, professional editing | Video editors | | **PNG Sequence** | 🔴 Very Large | 🟢 Perfect | GIF creation, frame-by-frame | Universal | | **Pro Bundle** | 🟡 Medium | 🟢 Perfect | Unscreen workflows, ZIP handling | Universal | | **Stacked Video** | 🟡 Medium | 🟢 Perfect | Universal, single file (top: video, bottom: mask) | Universal | ## WebM VP9 (Recommended) **Best for:** Easy overlay workflows, API usage, small file sizes **Decoder Required:** WebM VP9 transparency requires `libvpx-vp9` decoder. Works most of the time, but not guaranteed on all systems. ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Remove background with WebM VP9 format const options = new RemoveBGOptions(Prefer.WEBM_VP9) const transparent = await video.removeBackground({ client, options }) console.log('Transparent WebM ready:', transparent.primaryPath) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Remove background with WebM VP9 format options = RemoveBGOptions(prefer=Prefer.WEBM_VP9) transparent = video.remove_background(client, options) print(f'Transparent WebM ready: {transparent.primary_path}') ``` ```bash cURL theme={"dark"} # Start processing with WebM VP9 format curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "webm_vp9" } }' ``` ### Using WebM Videos in Your Projects ```bash FFmpeg theme={"dark"} # Overlay WebM on custom background ffmpeg -i background.jpg -i transparent_video.webm \ -c:v libvpx-vp9 \ -filter_complex "[1:v]setpts=PTS-STARTPTS[video]; \ [0:v][video]overlay=x=(W-w)/2:y=(H-h)/2:shortest=1" \ -c:v libx264 -c:a aac output.mp4 # Important: Use -c:v libvpx-vp9 decoder to preserve alpha channels! ``` ```python Python theme={"dark"} import ffmpeg # Load inputs background = ffmpeg.input('background.jpg', loop=1) video = ffmpeg.input('transparent_video.webm', **{'c:v': 'libvpx-vp9'}) # Normalize timestamps and overlay video_norm = ffmpeg.filter(video, 'setpts', 'PTS-STARTPTS') output = ffmpeg.overlay(background, video_norm, x='(W-w)/2', y='(H-h)/2', shortest=1) # Export ffmpeg.output(output, 'output.mp4', vcodec='libx264', acodec='aac').run() ``` ```typescript Node.js theme={"dark"} const ffmpeg = require('fluent-ffmpeg'); // Load inputs const background = ffmpeg().input('background.jpg').loop(); const video = ffmpeg().input('transparent_video.webm').inputOptions(['-c:v', 'libvpx-vp9']); // Create overlay background .complexFilter([ { filter: 'setpts', inputs: '1:v', outputs: 'video_norm', options: 'PTS-STARTPTS' }, { filter: 'overlay', inputs: ['0:v', 'video_norm'], outputs: 'output', options: `x=(W-w)/2:y=(H-h)/2:shortest=1` } ]) .outputOptions(['-c:v', 'libx264', '-c:a', 'aac']) .output('output.mp4') .run(); ``` **WebM Alpha Channel Issue:** The default VP9 decoder strips alpha channels. Always use `libvpx-vp9` decoder for proper transparency. If unavailable, use Stacked Video format instead. ## MOV ProRes (Professional) **Best for:** Professional video editing (Final Cut Pro, Premiere Pro) ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Remove background with MOV ProRes format const options = new RemoveBGOptions(Prefer.MOV_PRORES) const transparent = await video.removeBackground({client, options}) console.log('Transparent MOV ready:', transparent.primaryPath) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Remove background with MOV ProRes format options = RemoveBGOptions(prefer=Prefer.MOV_PRORES) transparent = video.remove_background(client, options) print(f'Transparent MOV ready: {transparent.primary_path}') ``` ```bash cURL theme={"dark"} # Start processing with MOV ProRes format curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "mov_prores" } }' ``` ### Using MOV Videos ```bash FFmpeg theme={"dark"} # Overlay MOV ProRes on background ffmpeg -i background.jpg -i transparent_video.mov \ -filter_complex "[1:v]setpts=PTS-STARTPTS[video]; [0:v][video]overlay=x=100:y=200:shortest=1" \ -c:v libx264 -c:a aac output.mp4 ``` ```python Python theme={"dark"} import ffmpeg background = ffmpeg.input('background.jpg', loop=1) video = ffmpeg.input('transparent_video.mov') # Position at specific coordinates video_norm = ffmpeg.filter(video, 'setpts', 'PTS-STARTPTS') output = ffmpeg.overlay(background, video_norm, x=100, y=200, shortest=1) ffmpeg.output(output, 'output.mp4', vcodec='libx264', acodec='aac').run() ``` ```typescript Node.js theme={"dark"} const ffmpeg = require('fluent-ffmpeg'); const background = ffmpeg().input('background.jpg').loop(); const video = ffmpeg().input('transparent_video.mov'); // Position at specific coordinates background .complexFilter([ { filter: 'setpts', inputs: '1:v', outputs: 'video_norm', options: 'PTS-STARTPTS' }, { filter: 'overlay', inputs: ['0:v', 'video_norm'], outputs: 'output', options: 'x=100:y=200:shortest=1' } ]) .outputOptions(['-c:v', 'libx264', '-c:a', 'aac']) .output('output.mp4') .run(); ``` ## PNG Sequence **Best for:** GIF creation, frame-by-frame editing, maximum quality ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Remove background with PNG sequence format const options = new RemoveBGOptions(Prefer.PNG_SEQUENCE) const transparent = await video.removeBackground({client, options}) console.log('PNG sequence ready:', transparent.primaryPath) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Remove background with PNG sequence format options = RemoveBGOptions(prefer=Prefer.PNG_SEQUENCE) transparent = video.remove_background(client, options) print(f'PNG sequence ready: {transparent.primary_path}') ``` ```bash cURL theme={"dark"} # Start processing with PNG sequence format curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "png_sequence" } }' ``` ### Using PNG Sequences ```bash FFmpeg theme={"dark"} # Extract ZIP and create video from PNG sequence unzip png_sequence.zip -d frames/ # Overlay PNG sequence on background ffmpeg -loop 1 -i background.jpg \ -framerate 24 -i frames/frame_%04d.png \ -filter_complex "[1:v]setpts=PTS-STARTPTS[video]; \ [0:v][video]overlay=x=(W-w)/2:y=(H-h)/2:shortest=1" \ -c:v libx264 -t 5 output.mp4 ``` ```python Python theme={"dark"} import ffmpeg import zipfile # Extract PNG sequence with zipfile.ZipFile('png_sequence.zip', 'r') as zip_ref: zip_ref.extractall('frames/') # Create video from sequence background = ffmpeg.input('background.jpg', loop=1) frames = ffmpeg.input('frames/frame_%04d.png', framerate=24) frames_norm = ffmpeg.filter(frames, 'setpts', 'PTS-STARTPTS') output = ffmpeg.overlay(background, frames_norm, x='(W-w)/2', y='(H-h)/2', shortest=1) ffmpeg.output(output, 'output.mp4', t=5, vcodec='libx264').run() ``` ```typescript Node.js theme={"dark"} const ffmpeg = require('fluent-ffmpeg'); const fs = require('fs'); const AdmZip = require('adm-zip'); // Extract PNG sequence const zip = new AdmZip('png_sequence.zip'); zip.extractAllTo('frames/', true); // Create video from sequence ffmpeg() .input('background.jpg') .loop() .input('frames/frame_%04d.png') .inputOptions(['-framerate', '24']) .complexFilter([ { filter: 'setpts', inputs: '1:v', outputs: 'frames_norm', options: 'PTS-STARTPTS' }, { filter: 'overlay', inputs: ['0:v', 'frames_norm'], outputs: 'output', options: `x=(W-w)/2:y=(H-h)/2:shortest=1` } ]) .outputOptions(['-c:v', 'libx264', '-t', '5']) .output('output.mp4') .run(); ``` ## Pro Bundle (Professional Workflow) **Best for:** Unscreen workflows, ZIP handling, maximum flexibility ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Remove background with Pro Bundle format const options = new RemoveBGOptions(Prefer.PRO_BUNDLE) const transparent = await video.removeBackground({client, options}) console.log('Pro Bundle ready:', transparent.primaryPath) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Remove background with Pro Bundle format options = RemoveBGOptions(prefer=Prefer.PRO_BUNDLE) transparent = video.remove_background(client, options) print(f'Pro Bundle ready: {transparent.primary_path}') ``` ```bash cURL theme={"dark"} # Start processing with Pro Bundle format curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "pro_bundle" } }' ``` ### Pro Bundle Contents The Pro Bundle ZIP contains: * `color.mp4` - Normalized foreground video * `alpha.mp4` - 8-bit grayscale matte * `audio.m4a` - Audio track (if present) * `manifest.json` - Technical specifications ### Using Pro Bundle ```bash FFmpeg theme={"dark"} # Extract bundle unzip pro_bundle.zip -d bundle/ # Combine color and alpha for transparency ffmpeg -i bundle/color.mp4 -i bundle/alpha.mp4 \ -filter_complex "[0:v]format=rgba[color]; \ [1:v]format=gray[alpha]; \ [color][alpha]alphamerge[transparent]" \ transparent_video.mov # Overlay on background ffmpeg -i background.jpg -i transparent_video.mov \ -filter_complex "[1:v]setpts=PTS-STARTPTS[video]; \ [0:v][video]overlay=x=(W-w)/2:y=(H-h)/2:shortest=1" \ -c:v libx264 -c:a aac final_output.mp4 ``` ```python Python theme={"dark"} import ffmpeg import zipfile # Extract bundle with zipfile.ZipFile('pro_bundle.zip', 'r') as zip_ref: zip_ref.extractall('bundle/') # Combine color and alpha color = ffmpeg.input('bundle/color.mp4') alpha = ffmpeg.input('bundle/alpha.mp4') color_rgba = ffmpeg.filter(color, 'format', 'rgba') alpha_gray = ffmpeg.filter(alpha, 'format', 'gray') transparent = ffmpeg.filter([color_rgba, alpha_gray], 'alphamerge') # Overlay on background background = ffmpeg.input('background.jpg', loop=1) transparent_norm = ffmpeg.filter(transparent, 'setpts', 'PTS-STARTPTS') output = ffmpeg.overlay(background, transparent_norm, x='(W-w)/2', y='(H-h)/2', shortest=1) ffmpeg.output(output, 'final_output.mp4', vcodec='libx264', acodec='aac').run() ``` ```typescript Node.js theme={"dark"} const ffmpeg = require('fluent-ffmpeg'); const AdmZip = require('adm-zip'); // Extract bundle const zip = new AdmZip('pro_bundle.zip'); zip.extractAllTo('bundle/', true); // Combine color and alpha for transparency ffmpeg() .input('bundle/color.mp4') .input('bundle/alpha.mp4') .complexFilter([ { filter: 'format', inputs: '0:v', outputs: 'color', options: 'rgba' }, { filter: 'format', inputs: '1:v', outputs: 'alpha', options: 'gray' }, { filter: 'alphamerge', inputs: ['color', 'alpha'], outputs: 'transparent' } ]) .output('transparent_video.mov') .on('end', () => { // Overlay on background ffmpeg() .input('background.jpg') .loop() .input('transparent_video.mov') .complexFilter([ { filter: 'setpts', inputs: '1:v', outputs: 'video_norm', options: 'PTS-STARTPTS' }, { filter: 'overlay', inputs: ['0:v', 'video_norm'], outputs: 'output', options: `x=(W-w)/2:y=(H-h)/2:shortest=1` } ]) .outputOptions(['-c:v', 'libx264', '-c:a', 'aac']) .output('final_output.mp4') .run(); }) .run(); ``` ## Stacked Video (Universal Format) **Best for:** Universal compatibility, single file handling (top: video, bottom: mask) ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video, RemoveBGOptions, Prefer } from '@videobgremover/sdk' const client = new VideoBGRemoverClient(process.env.VIDEOBGREMOVER_API_KEY!) const video = Video.open('https://example.com/video.mp4') // Remove background with Stacked Video format const options = new RemoveBGOptions(Prefer.STACKED_VIDEO) const transparent = await video.removeBackground({client, options}) console.log('Stacked Video ready:', transparent.primaryPath) ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video, RemoveBGOptions, Prefer import os client = VideoBGRemoverClient(os.getenv('VIDEOBGREMOVER_API_KEY')) video = Video.open('https://example.com/video.mp4') # Remove background with Stacked Video format options = RemoveBGOptions(prefer=Prefer.STACKED_VIDEO) transparent = video.remove_background(client, options) print(f'Stacked Video ready: {transparent.primary_path}') ``` ```bash cURL theme={"dark"} # Start processing with Stacked Video format curl -X POST https://api.videobgremover.com/v1/jobs/$JOB_ID/start \ -H "X-Api-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "background": { "type": "transparent", "transparent_format": "stacked_video" } }' ``` ### Stacked Video Structure * **Top Half:** Original video (1080x1080) * **Bottom Half:** Grayscale mask (1080x1080) * **Total Dimensions:** 1080x2160 (2:1 aspect ratio) ### Using Stacked Videos ```bash FFmpeg theme={"dark"} # Extract and apply mask in one command ffmpeg -i background.jpg -i stacked_video.mp4 \ -filter_complex " [1:v]split=2[original][mask_source]; [original]crop=1080:1080:0:0[top]; [mask_source]crop=1080:1080:0:1080,format=gray,geq='if(gte(lum(X,Y),128),255,0)'[binary_mask]; [top]format=rgba[top_rgba]; [top_rgba][binary_mask]alphamerge[masked_video]; [0:v][masked_video]overlay=x=(W-w)/2:y=(H-h)/2:shortest=1 " \ -c:v libx264 -c:a aac output.mp4 ``` ```python Python theme={"dark"} import ffmpeg background = ffmpeg.input('background.jpg', loop=1) stacked = ffmpeg.input('stacked_video.mp4') # Extract top half (original video) top = ffmpeg.filter(stacked, 'crop', 1080, 1080, 0, 0) top_rgba = ffmpeg.filter(top, 'format', 'rgba') # Extract bottom half (mask) and make binary mask = ffmpeg.filter(stacked, 'crop', 1080, 1080, 0, 1080) mask_gray = ffmpeg.filter(mask, 'format', 'gray') binary_mask = ffmpeg.filter(mask_gray, 'geq', "if(gte(lum(X,Y),128),255,0)") # Apply mask and overlay masked_video = ffmpeg.filter([top_rgba, binary_mask], 'alphamerge') masked_norm = ffmpeg.filter(masked_video, 'setpts', 'PTS-STARTPTS') output = ffmpeg.overlay(background, masked_norm, x='(W-w)/2', y='(H-h)/2', shortest=1) ffmpeg.output(output, 'output.mp4', vcodec='libx264', acodec='aac').run() ``` ```typescript Node.js theme={"dark"} const ffmpeg = require('fluent-ffmpeg'); const background = ffmpeg().input('background.jpg').loop(); const stacked = ffmpeg().input('stacked_video.mp4'); // Extract and apply mask in one command background .complexFilter([ { filter: 'split', inputs: '1:v', outputs: ['original', 'mask_source'] }, { filter: 'crop', inputs: 'original', outputs: 'top', options: '1080:1080:0:0' }, { filter: 'crop', inputs: 'mask_source', outputs: 'mask', options: '1080:1080:0:1080' }, { filter: 'format', inputs: 'mask', outputs: 'mask_gray', options: 'gray' }, { filter: 'geq', inputs: 'mask_gray', outputs: 'binary_mask', options: "if(gte(lum(X,Y),128),255,0)" }, { filter: 'format', inputs: 'top', outputs: 'top_rgba', options: 'rgba' }, { filter: 'alphamerge', inputs: ['top_rgba', 'binary_mask'], outputs: 'masked_video' }, { filter: 'setpts', inputs: 'masked_video', outputs: 'masked_norm', options: 'PTS-STARTPTS' }, { filter: 'overlay', inputs: ['0:v', 'masked_norm'], outputs: 'output', options: `x=(W-w)/2:y=(H-h)/2:shortest=1` } ]) .outputOptions(['-c:v', 'libx264', '-c:a', 'aac']) .output('output.mp4') .run(); ``` ## Testing Your Setup Before processing videos, test your FFmpeg installation: For detailed positioning and scaling techniques, see the [Positioning Guide](/video-composition/positioning) in the Video Composition section. ```bash Test WebM Support theme={"dark"} # Check if libvpx-vp9 decoder is available ffmpeg -decoders | grep libvpx-vp9 # Should output: # V..... libvpx-vp9 libvpx VP9 (codec vp9) ``` ```python Python Test theme={"dark"} import subprocess def test_webm_support(): try: result = subprocess.run(['ffmpeg', '-decoders'], capture_output=True, text=True) if 'libvpx-vp9' in result.stdout: print("✅ WebM alpha channels supported") return True else: print("❌ Use stacked video format instead") return False except: print("❌ FFmpeg not found") return False test_webm_support() ``` ```typescript Node.js Test theme={"dark"} const { exec } = require('child_process'); function testWebmSupport() { exec('ffmpeg -decoders', (error, stdout, stderr) => { if (error) { console.log('❌ FFmpeg not found'); return false; } if (stdout.includes('libvpx-vp9')) { console.log('✅ WebM alpha channels supported'); return true; } else { console.log('❌ Use stacked video format instead'); return false; } }); } testWebmSupport(); ``` # Video Background Removal | Remove Video Background with AI Source: https://docs.videobgremover.com/video-background-removal/overview Professional AI-powered video background removal service. Remove backgrounds from videos with transparent output for creators, marketers, and developers. ## What is Video Background Removal? Video background removal uses advanced AI models to identify and remove backgrounds from your videos, leaving you with transparent videos that can be composited with custom backgrounds. State-of-the-art models identify subjects and remove backgrounds frame by frame Processing happens on our servers - no local GPU required Pay per minute of video processed High-quality results suitable for professional workflows ## How It Works Videos are processed on our servers using advanced AI models Our models identify subjects and remove backgrounds frame by frame Get back a video with transparent background in your preferred format ## Two Ways to Use Background Removal ### 1. Direct API Calls Perfect for simple background removal when you just need the transparent video: ```bash cURL theme={"dark"} # Create job from URL curl -X POST https://api.videobgremover.com/v1/jobs \ -H "X-Api-Key: vbr_your_api_key" \ -d '{"video_url": "https://example.com/video.mp4"}' # Start processing curl -X POST https://api.videobgremover.com/v1/jobs/JOB_ID/start \ -H "X-Api-Key: vbr_your_api_key" \ -d '{}' ``` ```javascript Node.js theme={"dark"} // Using fetch directly const response = await fetch('https://api.videobgremover.com/v1/jobs', { method: 'POST', headers: { 'X-Api-Key': 'vbr_your_api_key' }, body: JSON.stringify({ video_url: 'https://example.com/video.mp4' }) }) ``` ```python Python theme={"dark"} import requests # Using requests directly response = requests.post( 'https://api.videobgremover.com/v1/jobs', headers={'X-Api-Key': 'vbr_your_api_key'}, json={'video_url': 'https://example.com/video.mp4'} ) ``` ### 2. SDK Approach (Recommended) Perfect for complete workflows including video composition: ```typescript Node.js theme={"dark"} import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' const client = new VideoBGRemoverClient('vbr_your_api_key') const video = Video.open('https://example.com/video.mp4') // Remove background (API call) const transparent = await video.removeBackground({ client }) // Now you can use transparent for composition ``` ```python Python theme={"dark"} from videobgremover import VideoBGRemoverClient, Video client = VideoBGRemoverClient('vbr_your_api_key') video = Video.open('https://example.com/video.mp4') # Remove background (API call) transparent = video.remove_background(client) # Now you can use transparent for composition ``` ## Output Formats Choose the format that works best for your workflow: | Format | Best For | File Size | Compatibility | | ----------------- | ----------------------- | --------- | ------------- | | **WebM VP9** | Web apps, APIs | Small | Good | | **MOV ProRes** | Professional editing | Large | Excellent | | **Stacked Video** | Universal compatibility | Medium | Universal | | **Pro Bundle** | Advanced workflows | Medium | Universal | | **PNG Sequence** | Frame-by-frame work | Large | Universal | ## Cost & Credits * **Processing cost**: Credits per minute based on video duration (see [Models](/video-background-removal/models) for pricing) * **Processing time**: 1-3 minutes depending on video length * **Failed jobs**: Don't consume credits * **Credit check**: Always check your balance before processing ```bash cURL theme={"dark"} curl -X GET https://api.videobgremover.com/v1/credits \ -H "X-Api-Key: vbr_your_api_key" ``` ```typescript Node.js theme={"dark"} const client = new VideoBGRemoverClient('vbr_your_api_key') const credits = await client.credits() console.log(`Remaining: ${credits.remainingCredits}`) ``` ```python Python theme={"dark"} client = VideoBGRemoverClient('vbr_your_api_key') credits = client.credits() print(f"Remaining: {credits.remaining_credits}") ``` ## What Happens Next? After background removal, you have a **transparent video** that you can: Download the transparent video and use it in your video editor Use our composition tools to add colors, images, or video backgrounds Integrate into your application or automation pipeline ## Ready to Start? Complete guide to removing backgrounds See end-to-end examples with composition # Troubleshooting Source: https://docs.videobgremover.com/video-background-removal/troubleshooting Fix common video background removal problems. Resolve API errors, handle large files, optimize processing, and achieve perfect results with our guide. ## Common Issues ### Insufficient Credits (402 Error) **Problem**: You don't have enough credits to process the video. **Solution**: Check your credit balance and top up if needed. ```bash cURL theme={"dark"} # Check credit balance curl -X GET https://api.videobgremover.com/v1/credits \ -H "X-Api-Key: $API_KEY" # Response shows remaining credits { "total_credits": 100, "remaining_credits": 5, "used_credits": 95 } ``` ```typescript Node.js theme={"dark"} const client = new VideoBGRemoverClient('your_api_key') try { const credits = await client.credits() console.log(`Remaining credits: ${credits.remainingCredits}`) if (credits.remainingCredits < 10) { console.log('⚠️ Low credits. Consider topping up.') } } catch (error) { console.log('Failed to check credits:', error.message) } ``` ```python Python theme={"dark"} client = VideoBGRemoverClient('your_api_key') try: credits = client.credits() print(f"Remaining credits: {credits.remaining_credits}") if credits.remaining_credits < 10: print('⚠️ Low credits. Consider topping up.') except Exception as e: print(f'Failed to check credits: {e}') ``` ### Invalid API Key (401 Error) **Problem**: Your API key is invalid or missing. **Solutions**: 1. Check your API key format: `vbr_` followed by 32 characters 2. Verify the key exists in your [API Management](https://videobgremover.com/api-management) dashboard 3. Ensure you're using the correct header: `X-Api-Key` ```bash cURL theme={"dark"} # Correct format curl -H "X-Api-Key: vbr_your_32_character_key_here" ... # ❌ Wrong header name curl -H "Authorization: Bearer vbr_..." ... # ❌ Wrong key format curl -H "X-Api-Key: invalid_key" ... ``` ```typescript Node.js theme={"dark"} // ✅ Correct const client = new VideoBGRemoverClient('vbr_your_32_character_key') // ❌ Wrong format const client = new VideoBGRemoverClient('invalid_key') ``` ```python Python theme={"dark"} # ✅ Correct client = VideoBGRemoverClient('vbr_your_32_character_key') # ❌ Wrong format client = VideoBGRemoverClient('invalid_key') ``` ### File Too Large (413 Error) **Problem**: Your video file exceeds the 1GB limit. **Solutions**: 1. Compress your video before uploading 2. Use a shorter video clip 3. Reduce video resolution or quality ### Job Not Found (404 Error) **Problem**: The job ID doesn't exist or doesn't belong to your account. **Solutions**: 1. Verify the job ID is correct 2. Check that you're using the same API key that created the job 3. Jobs expire after 24 hours - create a new one if needed ### Processing Failed **Problem**: The job status shows "failed" with an error message. **Common causes and solutions**: For specific error messages, check the API response and ensure your video meets the format requirements. ### WebM Transparency Not Working **Problem:** WebM video appears opaque instead of transparent **Solution:** Use the correct decoder ```bash theme={"dark"} # ❌ Wrong - strips alpha channels ffmpeg -i video.webm ... # ✅ Correct - preserves alpha channels ffmpeg -c:v libvpx-vp9 -i video.webm ... ``` ## SDK-Specific Issues ### Import Errors ```typescript Node.js theme={"dark"} // ❌ Wrong import import VideoBGRemover from '@videobgremover/sdk' // ✅ Correct import import { VideoBGRemoverClient, Video } from '@videobgremover/sdk' ``` ```python Python theme={"dark"} # ❌ Wrong import import videobgremover # ✅ Correct import from videobgremover import VideoBGRemoverClient, Video ``` ### FFmpeg Not Found **Problem**: SDK can't find FFmpeg for composition operations. **Solutions**: 1. Install FFmpeg: `brew install ffmpeg` (macOS) or `apt install ffmpeg` (Ubuntu) 2. Ensure FFmpeg is in your PATH 3. Test with: `ffmpeg -version` **Error you'll see**: When FFmpeg is not available, you'll get an error like: ``` Error: FFmpeg not found. Please install FFmpeg: Command 'ffmpeg' not found ``` ```bash Test FFmpeg theme={"dark"} # Test if FFmpeg is available ffmpeg -version # Should output version information # If you get "command not found", FFmpeg is not installed ``` ```python Python theme={"dark"} # FFmpeg availability is checked automatically when creating MediaContext # If FFmpeg is not found, you'll see an error during SDK initialization from videobgremover import MediaContext try: ctx = MediaContext() print("✅ FFmpeg is available") except RuntimeError as e: print(f"❌ FFmpeg not found: {e}") ``` ```typescript Node.js theme={"dark"} // FFmpeg availability is checked automatically when creating MediaContext // If FFmpeg is not found, you'll see an error during SDK initialization import { MediaContext } from '@videobgremover/sdk' try { const ctx = new MediaContext() console.log('✅ FFmpeg is available') } catch (error) { console.log('❌ FFmpeg not found:', error.message) } ``` ## Performance Issues ### Slow Processing **Causes**: * Large video files (>100MB) * High resolution videos (4K+) * Long videos (>5 minutes) **Solutions**: 1. **Pre-process videos**: Reduce resolution to 1080p 2. **Split long videos**: Process in segments 3. **Optimize format**: Use MP4 with H.264 encoding ## Getting Help If you're still having issues: Contact [paul@videobgremover.com](mailto:paul@videobgremover.com) for technical support Report bugs on [GitHub Issues](https://github.com/videobgremover/videobgremover-node/issues) # Custom Video Backgrounds for video compositions Source: https://docs.videobgremover.com/video-composition/backgrounds Create custom backgrounds for video compositions. Complete guide for color, image, and video backgrounds in multi-layer video editing workflows. ## Background Types Choose the type of background that fits your creative vision: **Solid colors** using hex codes **Static images** (automatically looped) **Dynamic videos** as moving backgrounds ## Color Backgrounds Perfect for clean, professional looks or chroma key workflows. ```typescript Node.js theme={"dark"} import { Background } from '@videobgremover/sdk' // Solid color backgrounds const red = Background.fromColor('#FF0000', 1920, 1080, 30) const green = Background.fromColor('#00FF00', 1920, 1080, 30) // Chroma key const blue = Background.fromColor('#0000FF', 1920, 1080, 30) const white = Background.fromColor('#FFFFFF', 1920, 1080, 30) const black = Background.fromColor('#000000', 1920, 1080, 30) // Custom colors const purple = Background.fromColor('#7C3AED', 1920, 1080, 30) const orange = Background.fromColor('#FF6B35', 1920, 1080, 30) ``` ```python Python theme={"dark"} from videobgremover import Background # Solid color backgrounds red = Background.from_color('#FF0000', 1920, 1080, 30) green = Background.from_color('#00FF00', 1920, 1080, 30) # Chroma key blue = Background.from_color('#0000FF', 1920, 1080, 30) white = Background.from_color('#FFFFFF', 1920, 1080, 30) black = Background.from_color('#000000', 1920, 1080, 30) # Custom colors purple = Background.from_color('#7C3AED', 1920, 1080, 30) orange = Background.from_color('#FF6B35', 1920, 1080, 30) ``` ### Popular Colors | Color | Hex Code | Use Case | | -------- | --------- | ------------------------ | | 🔴 Red | `#FF0000` | Bold, attention-grabbing | | 🟢 Green | `#00FF00` | Chroma key standard | | 🔵 Blue | `#0000FF` | Professional, clean | | ⚪ White | `#FFFFFF` | Clean, minimal | | ⚫ Black | `#000000` | Dramatic, cinematic | ## Image Backgrounds Use static images that automatically loop to match your video duration. ```typescript Node.js theme={"dark"} import { Background } from '@videobgremover/sdk' // Image backgrounds (dimensions auto-detected) const cityscape = Background.fromImage('cityscape.jpg', 30) const nature = Background.fromImage('forest.png', 24) // From URLs const webImage = Background.fromImage('https://example.com/bg.jpg', 30) // Different frame rates const cinema = Background.fromImage('background.jpg', 24) // Cinematic const smooth = Background.fromImage('background.jpg', 60) // Smooth ``` ```python Python theme={"dark"} from videobgremover import Background # Image backgrounds (dimensions auto-detected) cityscape = Background.from_image('cityscape.jpg', fps=30) nature = Background.from_image('forest.png', fps=24) # From URLs web_image = Background.from_image('https://example.com/bg.jpg', fps=30) # Different frame rates cinema = Background.from_image('background.jpg', fps=24) # Cinematic smooth = Background.from_image('background.jpg', fps=60) # Smooth ``` ### Image Requirements * **Formats**: JPG, PNG, WebP, TIFF * **Resolution**: Any resolution (will be scaled to match composition) * **Aspect ratio**: Any aspect ratio (consider your final video dimensions) ## Video Backgrounds Use dynamic video backgrounds for more engaging compositions. ```typescript Node.js theme={"dark"} import { Background } from '@videobgremover/sdk' // Video backgrounds (dimensions and FPS auto-detected) const nature = Background.fromVideo('nature_scene.mp4') const abstract = Background.fromVideo('abstract_motion.mov') // From URLs const streaming = Background.fromVideo('https://example.com/bg_video.mp4') // With audio control const silent = Background.fromVideo('music_video.mp4').audio(false) const quiet = Background.fromVideo('ambient.mp4').audio(true, 0.3) // 30% volume ``` ```python Python theme={"dark"} from videobgremover import Background # Video backgrounds (dimensions and FPS auto-detected) nature = Background.from_video('nature_scene.mp4') abstract = Background.from_video('abstract_motion.mov') # From URLs streaming = Background.from_video('https://example.com/bg_video.mp4') # With audio control silent = Background.from_video('music_video.mp4').audio(enabled=False) quiet = Background.from_video('ambient.mp4').audio(enabled=True, volume=0.3) ``` ### Video Background Features * **Duration control**: Video backgrounds determine the final composition length * **Audio support**: Include or exclude background audio * **Trimming**: Use only part of the background video * **Auto-detection**: Dimensions and frame rate detected automatically ### Trimming Video Backgrounds Use only part of a video as background: ```typescript Node.js theme={"dark"} // Use seconds 10-30 of background video const trimmed = Background.fromVideo('long_video.mp4').subclip(10, 30) // Use from 5 seconds to end const fromMiddle = Background.fromVideo('video.mp4').subclip(5) ``` ```python Python theme={"dark"} # Use seconds 10-30 of background video trimmed = Background.from_video('long_video.mp4').subclip(10, 30) # Use from 5 seconds to end from_middle = Background.from_video('video.mp4').subclip(5) ``` ## Background Audio Control audio from video backgrounds: ```typescript Node.js theme={"dark"} // Enable background audio (default for video backgrounds) const withAudio = Background.fromVideo('music.mp4').audio(true, 1.0) // Disable background audio const silent = Background.fromVideo('music.mp4').audio(false) // Reduce background audio volume const quiet = Background.fromVideo('music.mp4').audio(true, 0.2) // 20% volume ``` ```python Python theme={"dark"} # Enable background audio (default for video backgrounds) with_audio = Background.from_video('music.mp4').audio(enabled=True, volume=1.0) # Disable background audio silent = Background.from_video('music.mp4').audio(enabled=False) # Reduce background audio volume quiet = Background.from_video('music.mp4').audio(enabled=True, volume=0.2) ``` ## Duration Rules Understanding how background types affect composition duration: ### Rule 1: Video Backgrounds Control Duration When you use a video background, the final composition duration matches the background video: ```typescript Node.js theme={"dark"} // 30-second background video = 30-second final composition const bg = Background.fromVideo('30_second_video.mp4') const comp = new Composition(bg) comp.add(shortForeground) // Even if foreground is 5 seconds // Final video will be 30 seconds (background duration) ``` ```python Python theme={"dark"} # 30-second background video = 30-second final composition bg = Background.from_video('30_second_video.mp4') comp = Composition(bg) comp.add(short_foreground) # Even if foreground is 5 seconds # Final video will be 30 seconds (background duration) ``` ### Rule 2: Color/Image Backgrounds Use Foreground Duration Color and image backgrounds adapt to your foreground duration: ```typescript Node.js theme={"dark"} // Color background adapts to foreground const bg = Background.fromColor('#FF0000', 1920, 1080, 30) const comp = new Composition(bg) comp.add(tenSecondForeground) // 10-second foreground // Final video will be 10 seconds (foreground duration) ``` ```python Python theme={"dark"} # Color background adapts to foreground bg = Background.from_color('#FF0000', 1920, 1080, 30) comp = Composition(bg) comp.add(ten_second_foreground) # 10-second foreground # Final video will be 10 seconds (foreground duration) ``` ### Rule 3: Explicit Duration Override You can always override with explicit duration: ```typescript Node.js theme={"dark"} const comp = new Composition(anyBackground) comp.setDuration(15.0) // Force 15-second duration comp.add(foreground) // Final video will be exactly 15 seconds ``` ```python Python theme={"dark"} comp = Composition(any_background) comp.set_duration(15.0) # Force 15-second duration comp.add(foreground) # Final video will be exactly 15 seconds ``` ## Examples ### Professional Interview Setup ```typescript Node.js theme={"dark"} // Clean corporate background const bg = Background.fromColor('#1E293B', 1920, 1080, 30) // Dark blue const comp = new Composition(bg) comp.add(interviewSubject, 'person') .at(Anchor.CENTER_RIGHT, -100) .size(SizeMode.CANVAS_PERCENT, { percent: 60 }) comp.add(companyLogo, 'logo') .at(Anchor.BOTTOM_LEFT, 50, -50) .size(SizeMode.CANVAS_PERCENT, { percent: 15 }) .opacity(0.8) ``` ```python Python theme={"dark"} # Clean corporate background bg = Background.from_color('#1E293B', 1920, 1080, 30) # Dark blue comp = Composition(bg) comp.add(interview_subject, 'person') \ .at(Anchor.CENTER_RIGHT, dx=-100) \ .size(SizeMode.CANVAS_PERCENT, percent=60) comp.add(company_logo, 'logo') \ .at(Anchor.BOTTOM_LEFT, dx=50, dy=-50) \ .size(SizeMode.CANVAS_PERCENT, percent=15) \ .opacity(0.8) ``` ### Creative Video-on-Video ```typescript Node.js theme={"dark"} // Dynamic video background const bg = Background.fromVideo('city_timelapse.mp4') const comp = new Composition(bg) comp.add(dancer, 'performer') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) .opacity(0.9) // Background video controls duration automatically ``` ```python Python theme={"dark"} # Dynamic video background bg = Background.from_video('city_timelapse.mp4') comp = Composition(bg) comp.add(dancer, 'performer') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) \ .opacity(0.9) # Background video controls duration automatically ``` ## Next Steps Learn precise positioning and sizing techniques Create timed sequences and animations # Remove Video Background Export Guide Source: https://docs.videobgremover.com/video-composition/export-formats Choose the right export format for video background removal. Learn about H.264 MP4, VP9 WebM, ProRes MOV, and PNG sequences for optimal results. ## Export Formats Overview Choose the export format that best fits your target platform and quality requirements: **H.264 MP4, VP9 WebM** - Universal compatibility **ProRes MOV, PNG Sequence** - Maximum quality ## Standard Formats ### H.264 MP4 (Recommended) Universal compatibility with excellent compression: ```typescript Node.js theme={"dark"} import { EncoderProfile } from '@videobgremover/sdk' // High quality (default) await comp.toFile('output.mp4', EncoderProfile.h264()) // Custom quality settings await comp.toFile('hq.mp4', EncoderProfile.h264({ crf: 18, // Higher quality (lower CRF = better quality) preset: 'slow' // Slower encoding, better compression })) // Fast encoding for testing await comp.toFile('test.mp4', EncoderProfile.h264({ crf: 28, // Lower quality for speed preset: 'ultrafast' // Fastest encoding })) ``` ```python Python theme={"dark"} from videobgremover import EncoderProfile # High quality (default) comp.to_file('output.mp4', EncoderProfile.h264()) # Custom quality settings comp.to_file('hq.mp4', EncoderProfile.h264( crf=18, # Higher quality (lower CRF = better quality) preset='slow' # Slower encoding, better compression )) # Fast encoding for testing comp.to_file('test.mp4', EncoderProfile.h264( crf=28, # Lower quality for speed preset='ultrafast' # Fastest encoding )) ``` ### VP9 WebM Excellent compression for web delivery: ```typescript Node.js theme={"dark"} // VP9 WebM (excellent compression) await comp.toFile('output.webm', EncoderProfile.vp9()) // Custom VP9 settings await comp.toFile('web.webm', EncoderProfile.vp9({ crf: 32, // Good quality for web preset: 'fast' // Reasonable encoding speed })) ``` ```python Python theme={"dark"} # VP9 WebM (excellent compression) comp.to_file('output.webm', EncoderProfile.vp9()) # Custom VP9 settings comp.to_file('web.webm', EncoderProfile.vp9( crf=32, # Good quality for web preset='fast' # Reasonable encoding speed )) ``` ## Professional Formats ### ProRes 4444 MOV Highest quality for professional editing: ```typescript Node.js theme={"dark"} // ProRes 4444 (highest quality, large files) await comp.toFile('professional.mov', EncoderProfile.prores4444()) // Best for: Final Cut Pro, Premiere Pro, DaVinci Resolve ``` ```python Python theme={"dark"} # ProRes 4444 (highest quality, large files) comp.to_file('professional.mov', EncoderProfile.prores_4444()) # Best for: Final Cut Pro, Premiere Pro, DaVinci Resolve ``` ### PNG Sequence Frame-by-frame output for maximum quality: ```typescript Node.js theme={"dark"} // PNG sequence (one file per frame) await comp.toFile('frames/frame_%04d.png', EncoderProfile.pngSequence()) // Custom frame rate await comp.toFile('frames/frame_%04d.png', EncoderProfile.pngSequence({ fps: 24 // 24 FPS output })) // Creates: frame_0001.png, frame_0002.png, frame_0003.png, ... ``` ```python Python theme={"dark"} # PNG sequence (one file per frame) comp.to_file('frames/frame_%04d.png', EncoderProfile.png_sequence()) # Custom frame rate comp.to_file('frames/frame_%04d.png', EncoderProfile.png_sequence(fps=24)) # Creates: frame_0001.png, frame_0002.png, frame_0003.png, ... ``` ## Quality Settings ### Classic FFmpeg Parameters The SDK uses standard FFmpeg encoder parameters for professional control: #### CRF (Constant Rate Factor) Controls quality vs file size trade-off (lower = higher quality): | CRF | Quality | Use Case | Code Implementation | | --------- | ---------- | ----------------------------- | ---------------------------------- | | **12-18** | Excellent | Professional work, archival | `EncoderProfile.h264({ crf: 18 })` | | **19-23** | High | General purpose, good balance | `EncoderProfile.h264({ crf: 23 })` | | **24-28** | Good | Web delivery, smaller files | `EncoderProfile.h264({ crf: 28 })` | | **29-35** | Acceptable | Very small files, previews | `EncoderProfile.h264({ crf: 32 })` | #### Encoding Presets Balance encoding speed vs compression efficiency: | Preset | Speed | File Size | Use Case | FFmpeg Args | | ------------- | -------- | --------- | ----------------------------- | ------------------- | | **ultrafast** | Fastest | Largest | Testing, previews | `-preset ultrafast` | | **fast** | Fast | Large | Development | `-preset fast` | | **medium** | Moderate | Moderate | General purpose | `-preset medium` | | **slow** | Slow | Small | Final delivery | `-preset slow` | | **veryslow** | Slowest | Smallest | Archival, maximum compression | `-preset veryslow` | #### Codec Selection Different codecs for different use cases: * **H.264**: Universal compatibility (`-c:v libx264`) * **VP9**: Web optimization (`-c:v libvpx-vp9`) * **ProRes**: Professional editing (`-c:v prores_ks`) * **PNG**: Frame sequences (`-c:v png`) #### Pixel Formats Control color space and transparency: * **yuv420p**: Standard video (no alpha) * **yuva420p**: Video with alpha channel * **rgba**: PNG sequences with transparency ## Format Recommendations ### Choose by Use Case **Use H.264 MP4** - Universal browser support ```typescript theme={"dark"} EncoderProfile.h264({ crf: 28, preset: 'fast' }) ``` **Alternative**: VP9 WebM for better compression **Use H.264 MP4** - Platform compatibility ```typescript theme={"dark"} EncoderProfile.h264({ crf: 25, preset: 'medium' }) ``` Consider platform-specific requirements (Instagram, TikTok, etc.) **Use ProRes 4444 MOV** - Highest quality ```typescript theme={"dark"} EncoderProfile.prores4444() ``` Perfect for Final Cut Pro, Premiere Pro, DaVinci Resolve **Use PNG Sequence** - Individual frames ```typescript theme={"dark"} EncoderProfile.pngSequence({ fps: 30 }) ``` Perfect for GIF creation, frame-by-frame work ## Multiple Export Example Export the same composition in different formats: ```typescript Node.js theme={"dark"} // Create composition once const comp = new Composition(background) comp.add(video1, 'main').at(Anchor.CENTER) comp.add(video2, 'pip').at(Anchor.TOP_RIGHT).size(SizeMode.CANVAS_PERCENT, { percent: 25 }) // Export in multiple formats await comp.toFile('web_delivery.mp4', EncoderProfile.h264({ crf: 28 })) await comp.toFile('high_quality.mp4', EncoderProfile.h264({ crf: 18, preset: 'slow' })) await comp.toFile('web_optimized.webm', EncoderProfile.vp9({ crf: 32 })) await comp.toFile('professional.mov', EncoderProfile.prores4444()) await comp.toFile('frames/frame_%04d.png', EncoderProfile.pngSequence()) ``` ```python Python theme={"dark"} # Create composition once comp = Composition(background) comp.add(video1, 'main').at(Anchor.CENTER) comp.add(video2, 'pip').at(Anchor.TOP_RIGHT).size(SizeMode.CANVAS_PERCENT, percent=25) # Export in multiple formats comp.to_file('web_delivery.mp4', EncoderProfile.h264(crf=28)) comp.to_file('high_quality.mp4', EncoderProfile.h264(crf=18, preset='slow')) comp.to_file('web_optimized.webm', EncoderProfile.vp9(crf=32)) comp.to_file('professional.mov', EncoderProfile.prores_4444()) comp.to_file('frames/frame_%04d.png', EncoderProfile.png_sequence()) ``` ## Progress Tracking Monitor export progress: ```typescript Node.js theme={"dark"} const progressCallback = (status: string) => { console.log(`Export status: ${status}`) } await comp.toFile('output.mp4', EncoderProfile.h264(), progressCallback) ``` ```python Python theme={"dark"} def progress_callback(status): print(f'Export status: {status}') comp.to_file('output.mp4', EncoderProfile.h264(), on_progress=progress_callback) ``` ## Debugging ### Dry Run See the FFmpeg command without executing: ```typescript Node.js theme={"dark"} // See the FFmpeg command that would be executed const command = comp.dryRun() console.log('FFmpeg command:', command) ``` ```python Python theme={"dark"} # See the FFmpeg command that would be executed command = comp.dry_run() print(f'FFmpeg command: {command}') ``` ### Verbose Output See FFmpeg output in real-time: ```typescript Node.js theme={"dark"} // Show FFmpeg output for debugging await comp.toFile('output.mp4', EncoderProfile.h264(), undefined, true) // verbose=true ``` ```python Python theme={"dark"} # Show FFmpeg output for debugging comp.to_file('output.mp4', EncoderProfile.h264(), verbose=True) ``` ## File Size Comparison Approximate file sizes for a 30-second 1080p composition: | Format | Quality | File Size | Use Case | | ---------------- | --------- | --------- | --------------------- | | **H.264 CRF 18** | Excellent | \~50MB | Professional delivery | | **H.264 CRF 23** | High | \~25MB | General purpose | | **H.264 CRF 28** | Good | \~15MB | Web delivery | | **VP9 CRF 32** | Good | \~10MB | Web optimized | | **ProRes 4444** | Perfect | \~500MB | Professional editing | | **PNG Sequence** | Perfect | \~200MB | Frame-by-frame work | ## Platform-Specific Recommendations ### Social Media Platforms ```typescript Node.js theme={"dark"} // Instagram feed/reels await comp.toFile('instagram.mp4', EncoderProfile.h264({ crf: 25, preset: 'medium' })) ``` ```python Python theme={"dark"} # Instagram feed/reels comp.to_file('instagram.mp4', EncoderProfile.h264( crf=25, preset='medium' )) ``` ```typescript Node.js theme={"dark"} // TikTok (vertical format) await comp.toFile('tiktok.mp4', EncoderProfile.h264({ crf: 26, preset: 'fast' })) ``` ```python Python theme={"dark"} # TikTok (vertical format) comp.to_file('tiktok.mp4', EncoderProfile.h264( crf=26, preset='fast' )) ``` ```typescript Node.js theme={"dark"} // YouTube (high quality) await comp.toFile('youtube.mp4', EncoderProfile.h264({ crf: 20, preset: 'slow' })) ``` ```python Python theme={"dark"} # YouTube (high quality) comp.to_file('youtube.mp4', EncoderProfile.h264( crf=20, preset='slow' )) ``` ```typescript Node.js theme={"dark"} // Twitter (size limits) await comp.toFile('twitter.mp4', EncoderProfile.h264({ crf: 28, preset: 'fast' })) ``` ```python Python theme={"dark"} # Twitter (size limits) comp.to_file('twitter.mp4', EncoderProfile.h264( crf=28, preset='fast' )) ``` ### Web Applications ```typescript Node.js theme={"dark"} // Web player (balance of quality and size) await comp.toFile('web_player.mp4', EncoderProfile.h264({ crf: 26, preset: 'medium' })) // Background video (lower quality acceptable) await comp.toFile('bg_video.mp4', EncoderProfile.h264({ crf: 30, preset: 'fast' })) // Hero video (high quality) await comp.toFile('hero.mp4', EncoderProfile.h264({ crf: 22, preset: 'slow' })) ``` ```python Python theme={"dark"} # Web player (balance of quality and size) comp.to_file('web_player.mp4', EncoderProfile.h264( crf=26, preset='medium' )) # Background video (lower quality acceptable) comp.to_file('bg_video.mp4', EncoderProfile.h264( crf=30, preset='fast' )) # Hero video (high quality) comp.to_file('hero.mp4', EncoderProfile.h264( crf=22, preset='slow' )) ``` ## Advanced Export Options ### Implementation Details The SDK implements classic FFmpeg parameters through the `EncoderProfile` class: ```typescript Node.js theme={"dark"} // See what arguments the encoder generates const encoder = EncoderProfile.h264({ crf: 20 }) const args = encoder.args('output.mp4') console.log('FFmpeg args:', args) // Modify if needed (advanced) // Note: Direct FFmpeg argument modification not exposed in current SDK ``` ```python Python theme={"dark"} # See what arguments the encoder generates encoder = EncoderProfile.h264(crf=20) args = encoder.args('output.mp4') print(f'FFmpeg args: {args}') # Modify if needed (advanced) # Note: Direct FFmpeg argument modification not exposed in current SDK ``` ### Batch Export Export multiple versions efficiently: ```typescript Node.js theme={"dark"} const exports = [ { name: 'preview.mp4', encoder: EncoderProfile.h264({ crf: 30, preset: 'ultrafast' }) }, { name: 'final.mp4', encoder: EncoderProfile.h264({ crf: 20, preset: 'slow' }) }, { name: 'web.webm', encoder: EncoderProfile.vp9({ crf: 28 }) } ] for (const exp of exports) { console.log(`Exporting ${exp.name}...`) await comp.toFile(exp.name, exp.encoder) } ``` ```python Python theme={"dark"} exports = [ {'name': 'preview.mp4', 'encoder': EncoderProfile.h264(crf=30, preset='ultrafast')}, {'name': 'final.mp4', 'encoder': EncoderProfile.h264(crf=20, preset='slow')}, {'name': 'web.webm', 'encoder': EncoderProfile.vp9(crf=28)} ] for exp in exports: print(f'Exporting {exp["name"]}...') comp.to_file(exp['name'], exp['encoder']) ``` ## Performance Tips ### Optimize Export Speed * Use `ultrafast` preset for testing * Use lower resolution for previews * Export final quality only when composition is finalized ### Optimize File Size * Use VP9 WebM for smallest files * Increase CRF value (lower quality) for smaller files * Use `slow` or `veryslow` preset for better compression ### Memory Management * Export long compositions in segments * Use appropriate quality settings for your target * Clean up intermediate files ## What's Next? See complete workflow examples with different export formats Detailed documentation for all encoder options # Video Composition Guide | Create Professional Video Layouts Source: https://docs.videobgremover.com/video-composition/overview Create professional video compositions with custom backgrounds. Learn layering, positioning, and export formats for multi-layer video editing. ## What is Video Composition? Video composition lets you layer transparent videos with custom backgrounds, effects, and positioning to create professional-looking videos. This happens **locally on your machine** using FFmpeg - no API calls or credits required. **FFmpeg-powered**: Runs on your machine, no internet required **Free operations**: Composition doesn't consume API credits **Production-ready**: Export in H.264, ProRes, WebM, PNG sequences **Pixel-perfect**: Position, scale, and time everything exactly ## Prerequisites Before you can create compositions, you need: Videos with removed backgrounds (from [background removal](/video-background-removal/overview)) FFmpeg must be available in your system PATH ([installation guide](/installation#ffmpeg-installation)) Node.js or Python SDK ([installation guide](/installation)) ## How It Works Choose from colors, images, or video backgrounds Layer your transparent videos with precise positioning Control opacity, rotation, timing, and scaling Render locally using FFmpeg in your preferred format ## Quick Example Here's a complete composition workflow: ```typescript Node.js theme={"dark"} import { Background, Composition, Foreground, EncoderProfile, Anchor, SizeMode } from '@videobgremover/sdk' // 1. Create custom background const background = Background.fromColor('#FF0000', 1920, 1080, 30) // 2. Load transparent video (from background removal) const transparent = Foreground.fromUrl('path/to/transparent.webm', { format: 'webm_vp9' }) // 3. Create composition const comp = new Composition(background) comp.add(transparent, 'main_video') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) .opacity(0.9) // 4. Export final video await comp.toFile('final_video.mp4', EncoderProfile.h264()) ``` ```python Python theme={"dark"} from videobgremover import ( Background, Composition, Foreground, EncoderProfile, Anchor, SizeMode ) # 1. Create custom background background = Background.from_color('#FF0000', 1920, 1080, 30) # 2. Load transparent video (from background removal) transparent = Foreground.from_webm_vp9('path/to/transparent.webm') # 3. Create composition comp = Composition(background) comp.add(transparent, 'main_video') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) \ .opacity(0.9) # 4. Export final video comp.to_file('final_video.mp4', EncoderProfile.h264()) ``` ## Key Concepts ### Backgrounds Create the foundation for your composition: * **Color backgrounds**: Solid colors using hex codes * **Image backgrounds**: Static images (automatically looped) * **Video backgrounds**: Dynamic video backgrounds * **Empty backgrounds**: Transparent canvas for overlays ### Layers Stack multiple transparent videos: * **Positioning**: Use anchors (CENTER, TOP\_LEFT, etc.) with pixel offsets * **Sizing**: Fit, cover, exact pixels, or percentage of canvas * **Effects**: Opacity, rotation, cropping * **Timing**: Control when layers appear and disappear ### Export Formats Render your final video: * **H.264 MP4**: Universal compatibility, good compression * **VP9 WebM**: Web-optimized, excellent compression * **ProRes MOV**: Professional editing, highest quality * **PNG Sequence**: Frame-by-frame work, maximum quality ## Composition Types ### Simple Replacement Replace video background with a solid color or image: ```typescript Node.js theme={"dark"} // Color background const bg = Background.fromColor('#00FF00', 1920, 1080, 30) const comp = new Composition(bg) comp.add(transparent).at(Anchor.CENTER) // Image background const bg = Background.fromImage('background.jpg', 30) const comp = new Composition(bg) comp.add(transparent).at(Anchor.CENTER) ``` ```python Python theme={"dark"} # Color background bg = Background.from_color('#00FF00', 1920, 1080, 30) comp = Composition(bg) comp.add(transparent).at(Anchor.CENTER) # Image background bg = Background.from_image('background.jpg', fps=30) comp = Composition(bg) comp.add(transparent).at(Anchor.CENTER) ``` ### Multi-Layer Composition Layer multiple videos with different positioning: ```typescript Node.js theme={"dark"} const comp = new Composition(background) // Main video (full screen) comp.add(video1, 'main') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) // Picture-in-picture (small, top-right) comp.add(video2, 'pip') .at(Anchor.TOP_RIGHT, -50, 50) .size(SizeMode.CANVAS_PERCENT, { percent: 25 }) .opacity(0.8) ``` ```python Python theme={"dark"} comp = Composition(background) # Main video (full screen) comp.add(video1, 'main') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) # Picture-in-picture (small, top-right) comp.add(video2, 'pip') \ .at(Anchor.TOP_RIGHT, dx=-50, dy=50) \ .size(SizeMode.CANVAS_PERCENT, percent=25) \ .opacity(0.8) ``` ### Timed Sequences Control when layers appear and disappear: ```typescript Node.js theme={"dark"} const comp = new Composition(background) // Video appears at 2 seconds, lasts 5 seconds comp.add(video1, 'intro') .start(2.0) .duration(5.0) .at(Anchor.CENTER) // Video appears at 8 seconds, ends at 15 seconds comp.add(video2, 'outro') .start(8.0) .end(15.0) .at(Anchor.TOP_RIGHT) ``` ```python Python theme={"dark"} comp = Composition(background) # Video appears at 2 seconds, lasts 5 seconds comp.add(video1, 'intro') \ .start(2.0) \ .duration(5.0) \ .at(Anchor.CENTER) # Video appears at 8 seconds, ends at 15 seconds comp.add(video2, 'outro') \ .start(8.0) \ .end(15.0) \ .at(Anchor.TOP_RIGHT) ``` ## Requirements * **FFmpeg**: Must be installed and available in PATH * **Transparent videos**: From background removal or other sources * **System resources**: Composition happens locally on your machine ## What's Next? Learn about color, image, and video backgrounds Master precise positioning and sizing Create timed sequences and animations Choose the right export format for your needs # Positioning & Sizing | Remove Video Background Positioning Source: https://docs.videobgremover.com/video-composition/positioning Master video layer positioning with 9 anchor points, pixel-perfect offsets, and multiple sizing modes. Create professional multi-layer compositions. ## Positioning System Position your video layers using anchors and offsets for pixel-perfect control: **9 anchor points** for easy positioning **Pixel offsets** for fine-tuning position **Multiple sizing options** for different needs ## Anchor Points Use anchor points to position layers relative to the canvas: | TOP\_LEFT | TOP\_CENTER | TOP\_RIGHT | | :----------: | :------------: | :-----------: | | CENTER\_LEFT | CENTER | CENTER\_RIGHT | | BOTTOM\_LEFT | BOTTOM\_CENTER | BOTTOM\_RIGHT | ```typescript Node.js theme={"dark"} import { Anchor } from '@videobgremover/sdk' // Basic positioning comp.add(transparent).at(Anchor.CENTER) comp.add(transparent).at(Anchor.TOP_LEFT) comp.add(transparent).at(Anchor.BOTTOM_RIGHT) // With pixel offsets comp.add(transparent).at(Anchor.CENTER, 100, 50) // 100px right, 50px down comp.add(transparent).at(Anchor.TOP_RIGHT, -20, 20) // 20px from edges ``` ```python Python theme={"dark"} from videobgremover import Anchor # Basic positioning comp.add(transparent).at(Anchor.CENTER) comp.add(transparent).at(Anchor.TOP_LEFT) comp.add(transparent).at(Anchor.BOTTOM_RIGHT) # With pixel offsets comp.add(transparent).at(Anchor.CENTER, dx=100, dy=50) # 100px right, 50px down comp.add(transparent).at(Anchor.TOP_RIGHT, dx=-20, dy=20) # 20px from edges ``` ## Size Modes Choose how your videos are sized within the composition: ### CONTAIN (Fit Within Canvas) Scales video to fit within canvas while preserving aspect ratio: ```typescript Node.js theme={"dark"} import { SizeMode } from '@videobgremover/sdk' // Fit transparent video within canvas (letterbox/pillarbox if needed) comp.add(transparent).size(SizeMode.CONTAIN) ``` ```python Python theme={"dark"} from videobgremover import SizeMode # Fit transparent video within canvas (letterbox/pillarbox if needed) comp.add(transparent).size(SizeMode.CONTAIN) ``` ### COVER (Fill Canvas) Scales video to fill entire canvas, may crop edges: ```typescript Node.js theme={"dark"} // Fill entire canvas (crop if needed) comp.add(transparent).size(SizeMode.COVER) ``` ```python Python theme={"dark"} # Fill entire canvas (crop if needed) comp.add(transparent).size(SizeMode.COVER) ``` ### PX (Exact Pixels) Set exact pixel dimensions: ```typescript Node.js theme={"dark"} // Exact pixel dimensions comp.add(transparent).size(SizeMode.PX, { width: 800, height: 600 }) ``` ```python Python theme={"dark"} # Exact pixel dimensions comp.add(transparent).size(SizeMode.PX, width=800, height=600) ``` ### CANVAS\_PERCENT (Percentage of Canvas) Size relative to canvas dimensions: ```typescript Node.js theme={"dark"} // Square percentage (50% of both width and height) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, { percent: 50 }) // Separate width/height percentages comp.add(transparent).size(SizeMode.CANVAS_PERCENT, { width: 75, height: 25 }) // Width only (height maintains aspect ratio) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, { width: 60 }) // Height only (width maintains aspect ratio) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, { height: 40 }) ``` ```python Python theme={"dark"} # Square percentage (50% of both width and height) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, percent=50) # Separate width/height percentages comp.add(transparent).size(SizeMode.CANVAS_PERCENT, width=75, height=25) # Width only (height maintains aspect ratio) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, width=60) # Height only (width maintains aspect ratio) comp.add(transparent).size(SizeMode.CANVAS_PERCENT, height=40) ``` ### SCALE (Relative to Original) Scale relative to the video's original dimensions: ```typescript Node.js theme={"dark"} // Uniform scaling (150% of original size) comp.add(transparent).size(SizeMode.SCALE, { scale: 1.5 }) // Non-uniform scaling (200% width, 80% height) comp.add(transparent).size(SizeMode.SCALE, { width: 2.0, height: 0.8 }) // Width-only scaling (maintains aspect ratio) comp.add(transparent).size(SizeMode.SCALE, { width: 1.2 }) // Height-only scaling (maintains aspect ratio) comp.add(transparent).size(SizeMode.SCALE, { height: 0.7 }) ``` ```python Python theme={"dark"} # Uniform scaling (150% of original size) comp.add(transparent).size(SizeMode.SCALE, scale=1.5) # Non-uniform scaling (200% width, 80% height) comp.add(transparent).size(SizeMode.SCALE, width=2.0, height=0.8) # Width-only scaling (maintains aspect ratio) comp.add(transparent).size(SizeMode.SCALE, width=1.2) # Height-only scaling (maintains aspect ratio) comp.add(transparent).size(SizeMode.SCALE, height=0.7) ``` ### FIT\_WIDTH / FIT\_HEIGHT Scale to match specific canvas dimension: ```typescript Node.js theme={"dark"} // Scale to match canvas width (height adjusts to maintain aspect ratio) comp.add(transparent).size(SizeMode.FIT_WIDTH) // Scale to match canvas height (width adjusts to maintain aspect ratio) comp.add(transparent).size(SizeMode.FIT_HEIGHT) ``` ```python Python theme={"dark"} # Scale to match canvas width (height adjusts to maintain aspect ratio) comp.add(transparent).size(SizeMode.FIT_WIDTH) # Scale to match canvas height (width adjusts to maintain aspect ratio) comp.add(transparent).size(SizeMode.FIT_HEIGHT) ``` ## Visual Effects ### Opacity Control layer transparency: ```typescript Node.js theme={"dark"} comp.add(transparent).opacity(0.7) // 70% opacity comp.add(transparent).opacity(0.3) // 30% opacity comp.add(transparent).opacity(0.0) // Invisible ``` ```python Python theme={"dark"} comp.add(transparent).opacity(0.7) # 70% opacity comp.add(transparent).opacity(0.3) # 30% opacity comp.add(transparent).opacity(0.0) # Invisible ``` ## Size Mode Comparison | Mode | Use Case | Aspect Ratio | Example | | ------------------- | -------------------- | -------------------- | ------------------ | | **CONTAIN** | Fit entire video | Preserved | Video player | | **COVER** | Fill canvas | Preserved (may crop) | Background video | | **PX** | Exact dimensions | May stretch | Fixed overlays | | **CANVAS\_PERCENT** | Responsive sizing | Preserved | Picture-in-picture | | **SCALE** | Relative to original | Configurable | Zoom effects | | **FIT\_WIDTH** | Match canvas width | Preserved | Full-width banner | | **FIT\_HEIGHT** | Match canvas height | Preserved | Sidebar video | ## Practical Examples ### Picture-in-Picture Classic PIP layout with main video and small overlay: ```typescript Node.js theme={"dark"} // Main video (full screen) comp.add(mainVideo, 'main') .at(Anchor.CENTER) .size(SizeMode.CONTAIN) // PIP video (small, top-right corner) comp.add(pipVideo, 'pip') .at(Anchor.TOP_RIGHT, -30, 30) .size(SizeMode.CANVAS_PERCENT, { percent: 25 }) .opacity(0.9) ``` ```python Python theme={"dark"} # Main video (full screen) comp.add(main_video, 'main') \ .at(Anchor.CENTER) \ .size(SizeMode.CONTAIN) # PIP video (small, top-right corner) comp.add(pip_video, 'pip') \ .at(Anchor.TOP_RIGHT, dx=-30, dy=30) \ .size(SizeMode.CANVAS_PERCENT, percent=25) \ .opacity(0.9) ``` ### Side-by-Side Comparison Two videos side by side: ```typescript Node.js theme={"dark"} // Left transparent video comp.add(transparent1) .at(Anchor.CENTER_LEFT, 50) .size(SizeMode.CANVAS_PERCENT, { width: 45 }) // Right transparent video comp.add(transparent2) .at(Anchor.CENTER_RIGHT, -50) .size(SizeMode.CANVAS_PERCENT, { width: 45 }) ``` ```python Python theme={"dark"} # Left transparent video comp.add(transparent1) \ .at(Anchor.CENTER_LEFT, dx=50) \ .size(SizeMode.CANVAS_PERCENT, width=45) # Right transparent video comp.add(transparent2) \ .at(Anchor.CENTER_RIGHT, dx=-50) \ .size(SizeMode.CANVAS_PERCENT, width=45) ``` ### Overlay Grid Multiple small overlays in a grid: ```typescript Node.js theme={"dark"} const gridSize = 20 // 20% of canvas for each video const margin = 30 // 30px margin from edges // 2x2 grid comp.add(transparent1).at(Anchor.TOP_LEFT, margin, margin) .size(SizeMode.CANVAS_PERCENT, { percent: gridSize }) comp.add(transparent2).at(Anchor.TOP_RIGHT, -margin, margin) .size(SizeMode.CANVAS_PERCENT, { percent: gridSize }) comp.add(transparent3).at(Anchor.BOTTOM_LEFT, margin, -margin) .size(SizeMode.CANVAS_PERCENT, { percent: gridSize }) comp.add(transparent4).at(Anchor.BOTTOM_RIGHT, -margin, -margin) .size(SizeMode.CANVAS_PERCENT, { percent: gridSize }) ``` ```python Python theme={"dark"} grid_size = 20 # 20% of canvas for each transparent video margin = 30 # 30px margin from edges # 2x2 grid comp.add(transparent1).at(Anchor.TOP_LEFT, dx=margin, dy=margin) \ .size(SizeMode.CANVAS_PERCENT, percent=grid_size) comp.add(transparent2).at(Anchor.TOP_RIGHT, dx=-margin, dy=margin) \ .size(SizeMode.CANVAS_PERCENT, percent=grid_size) comp.add(transparent3).at(Anchor.BOTTOM_LEFT, dx=margin, dy=-margin) \ .size(SizeMode.CANVAS_PERCENT, percent=grid_size) comp.add(transparent4).at(Anchor.BOTTOM_RIGHT, dx=-margin, dy=-margin) \ .size(SizeMode.CANVAS_PERCENT, percent=grid_size) ``` ## Z-Order (Layer Stacking) Control which layers appear in front: ```typescript Node.js theme={"dark"} // Background layer (behind everything) comp.add(backgroundVideo, 'bg').z(0) // Main content (middle layer) comp.add(mainVideo, 'main').z(10) // Overlay effects (in front) comp.add(overlayVideo, 'overlay').z(20) // Logo (always on top) comp.add(logoVideo, 'logo').z(100) ``` ```python Python theme={"dark"} # Background layer (behind everything) comp.add(background_video, 'bg').z(0) # Main content (middle layer) comp.add(main_video, 'main').z(10) # Overlay effects (in front) comp.add(overlay_video, 'overlay').z(20) # Logo (always on top) comp.add(logo_video, 'logo').z(100) ``` ## Alpha Channel Control Control transparency processing for each layer: ```typescript Node.js theme={"dark"} // Use alpha channel (default - transparent background shows through) comp.add(transparent).alpha(true) // Ignore alpha channel (opaque - background becomes black) comp.add(transparent).alpha(false) ``` ```python Python theme={"dark"} # Use alpha channel (default - transparent background shows through) comp.add(transparent).alpha(enabled=True) # Ignore alpha channel (opaque - background becomes black) comp.add(transparent).alpha(enabled=False) ``` ## Tips & Best Practices ### Responsive Design Use percentage-based sizing for responsive layouts: ```typescript theme={"dark"} // Main content takes 70% width, sidebar takes 25% comp.add(mainVideo, 'main').size(SizeMode.CANVAS_PERCENT, { width: 70 }) comp.add(sideVideo, 'side').size(SizeMode.CANVAS_PERCENT, { width: 25 }) ``` ### Visual Hierarchy * Use z-order to control layer stacking * Use opacity to create depth * Use size to emphasize importance ## What's Next? Learn how to control when layers appear and disappear Choose the right export format and quality settings # Video Timing & Duration Control | Remove Video Background Source: https://docs.videobgremover.com/video-composition/timing Master video timing control with start times, durations, and source trimming. Learn composition duration rules, layer sequencing, and dynamic videos. ## Timeline Control Control exactly when your video layers appear and disappear in your composition. The timing system has two levels: **Which part** of the source video to use (trimming) **When to show** the layer in the final video ## Composition Timeline Control when layers appear in your final video: ### Start Time Set when a layer begins appearing: ```typescript Node.js theme={"dark"} // Layer appears at 2 seconds comp.add(transparent).start(2.0) // Layer appears immediately (default) comp.add(transparent).start(0.0) ``` ```python Python theme={"dark"} # Layer appears at 2 seconds comp.add(transparent).start(2.0) # Layer appears immediately (default) comp.add(transparent).start(0.0) ``` ### Duration Control Control how long layers are visible: ```typescript Node.js theme={"dark"} // Show for exactly 5 seconds comp.add(transparent).start(2.0).duration(5.0) // Appears at 2s, disappears at 7s // Show from 10s to 15s comp.add(transparent).start(10.0).end(15.0) // Appears at 10s, disappears at 15s // Show from start time until end of composition comp.add(transparent).start(5.0) // Appears at 5s, continues until composition ends ``` ```python Python theme={"dark"} # Show for exactly 5 seconds comp.add(transparent).start(2.0).duration(5.0) # Appears at 2s, disappears at 7s # Show from 10s to 15s comp.add(transparent).start(10.0).end(15.0) # Appears at 10s, disappears at 15s # Show from start time until end of composition comp.add(transparent).start(5.0) # Appears at 5s, continues until composition ends ``` ## Source Trimming Use only specific parts of your source videos: ```typescript Node.js theme={"dark"} // Use seconds 5-10 of the source video const trimmed = transparent.subclip(5, 10) comp.add(trimmed) // Use from 3 seconds to end of source const fromMiddle = transparent.subclip(3) comp.add(fromMiddle) // Or trim directly in composition comp.add(transparent).subclip(2, 8) ``` ```python Python theme={"dark"} # Use seconds 5-10 of the source video trimmed = transparent.subclip(5, 10) comp.add(trimmed) # Use from 3 seconds to end of source from_middle = transparent.subclip(3) comp.add(from_middle) # Or trim directly in composition comp.add(transparent).subclip(2, 8) ``` ## Combined Timing You can combine source trimming with composition timing: ```typescript Node.js theme={"dark"} // Use seconds 1-4 of source (3 seconds of content) // Show it at 10-13 seconds in the final video comp.add(transparent) .subclip(1, 4) // Source: use 1-4s (3s of content) .start(10) // Composition: show at 10s .duration(3) // Composition: show for 3s (10-13s) ``` ```python Python theme={"dark"} # Use seconds 1-4 of source (3 seconds of content) # Show it at 10-13 seconds in the final video comp.add(transparent) \ .subclip(1, 4) \ # Source: use 1-4s (3s of content) .start(10) \ # Composition: show at 10s .duration(3) # Composition: show for 3s (10-13s) ``` ## Staggered Animations Create dynamic sequences with layers appearing at different times: ```typescript Node.js theme={"dark"} const videos = [transparent1, transparent2, transparent3, transparent4] const positions = [ Anchor.TOP_LEFT, Anchor.TOP_RIGHT, Anchor.BOTTOM_LEFT, Anchor.BOTTOM_RIGHT ] videos.forEach((vid, i) => { comp.add(vid) .at(positions[i], 50, 50) .size(SizeMode.CANVAS_PERCENT, { percent: 40 }) .start(i * 2) // Start every 2 seconds: 0s, 2s, 4s, 6s .duration(6) // Each visible for 6 seconds .opacity(0.8) }) ``` ```python Python theme={"dark"} videos = [transparent1, transparent2, transparent3, transparent4] positions = [ Anchor.TOP_LEFT, Anchor.TOP_RIGHT, Anchor.BOTTOM_LEFT, Anchor.BOTTOM_RIGHT ] for i, (vid, pos) in enumerate(zip(videos, positions)): comp.add(vid) \ .at(pos, dx=50, dy=50) \ .size(SizeMode.CANVAS_PERCENT, percent=40) \ .start(i * 2) \ # Start every 2 seconds: 0s, 2s, 4s, 6s .duration(6) \ # Each visible for 6 seconds .opacity(0.8) ``` ## Audio Timing Control audio from your layers: ```typescript Node.js theme={"dark"} // Layer with full audio comp.add(transparent1) .start(0) .audio(true, 1.0) // Full volume // Layer with reduced audio comp.add(transparent2) .start(5) .audio(true, 0.3) // 30% volume // Silent layer comp.add(transparent3) .start(10) .audio(false) // No audio ``` ```python Python theme={"dark"} # Layer with full audio comp.add(transparent1) \ .start(0) \ .audio(enabled=True, volume=1.0) # Full volume # Layer with reduced audio comp.add(transparent2) \ .start(5) \ .audio(enabled=True, volume=0.3) # 30% volume # Silent layer comp.add(transparent3) \ .start(10) \ .audio(enabled=False) # No audio ``` ## Duration Rules Understanding how composition duration is determined: ### Rule 1: Video Background Controls Duration When you use a video background, it determines the final length: ```typescript Node.js theme={"dark"} // 30-second background video = 30-second final composition const bg = Background.fromVideo('30_second_bg.mp4') const comp = new Composition(bg) comp.add(transparent) // Even if foreground is 5 seconds // Final video will be 30 seconds ``` ```python Python theme={"dark"} # 30-second background video = 30-second final composition bg = Background.from_video('30_second_bg.mp4') comp = Composition(bg) comp.add(transparent) # Even if foreground is 5 seconds # Final video will be 30 seconds ``` ### Rule 2: Color/Image Backgrounds Use Longest Foreground Color and image backgrounds adapt to your content: ```typescript Node.js theme={"dark"} // Color background adapts to content const bg = Background.fromColor('#FF0000', 1920, 1080, 30) const comp = new Composition(bg) comp.add(tenSecondTransparent) // 10-second transparent video comp.add(fiveSecondTransparent) // 5-second transparent video // Final video will be 10 seconds (longest foreground) ``` ```python Python theme={"dark"} # Color background adapts to content bg = Background.from_color('#FF0000', 1920, 1080, 30) comp = Composition(bg) comp.add(ten_second_transparent) # 10-second transparent video comp.add(five_second_transparent) # 5-second transparent video # Final video will be 10 seconds (longest foreground) ``` ### Rule 3: Explicit Duration Override You can always force a specific duration: ```typescript Node.js theme={"dark"} const comp = new Composition(anyBackground) comp.setDuration(20.0) // Force 20-second duration comp.add(transparent) // Final video will be exactly 20 seconds ``` ```python Python theme={"dark"} comp = Composition(any_background) comp.set_duration(20.0) # Force 20-second duration comp.add(transparent) # Final video will be exactly 20 seconds ``` ## Source Trimming Use only specific parts of your source videos: ### Basic Trimming ```typescript Node.js theme={"dark"} // Method 1: Trim the foreground before adding const trimmed = video.subclip(10, 20) // Use seconds 10-20 comp.add(trimmed, 'segment') // Method 2: Trim in the composition comp.add(transparent).subclip(10, 20) // Method 3: Open-ended trim (from 5s to end) comp.add(transparent).subclip(5) ``` ```python Python theme={"dark"} # Method 1: Trim the foreground before adding trimmed = transparent.subclip(10, 20) # Use seconds 10-20 comp.add(trimmed, 'segment') # Method 2: Trim in the composition comp.add(transparent).subclip(10, 20) # Method 3: Open-ended trim (from 5s to end) comp.add(transparent).subclip(5) ``` ### Advanced Trimming ```typescript Node.js theme={"dark"} // Multiple segments from same source comp.add(transparent).subclip(0, 3).start(0) // 0-3s of source at 0s comp.add(transparent).subclip(10, 15).start(5) // 10-15s of source at 5s comp.add(transparent).subclip(25, 30).start(12) // 25-30s of source at 12s // Re-trimming (trim a trimmed video) const firstTrim = transparent.subclip(5, 20) // 5-20s of original const secondTrim = firstTrim.subclip(2, 8) // 2-8s of first trim = 7-13s of original ``` ```python Python theme={"dark"} # Multiple segments from same source comp.add(transparent).subclip(0, 3).start(0) # 0-3s of source at 0s comp.add(transparent).subclip(10, 15).start(5) # 10-15s of source at 5s comp.add(transparent).subclip(25, 30).start(12) # 25-30s of source at 12s # Re-trimming (trim a trimmed video) first_trim = transparent.subclip(5, 20) # 5-20s of original second_trim = first_trim.subclip(2, 8) # 2-8s of first trim = 7-13s of original ``` ## Audio Synchronization Control audio timing with your video layers: ### Audio with Timing ```typescript Node.js theme={"dark"} // Transparent video with audio that starts at 3 seconds comp.add(transparent) .start(3.0) .audio(true, 1.0) // Audio automatically delayed to match video // Multiple audio sources with different timing comp.add(transparent1).start(0).audio(true, 0.8) // Main audio comp.add(transparent2).start(5).audio(true, 0.3) // Background music comp.add(transparent3).start(10).audio(true, 0.5) // Sound effects ``` ```python Python theme={"dark"} # Transparent video with audio that starts at 3 seconds comp.add(transparent) \ .start(3.0) \ .audio(enabled=True, volume=1.0) # Audio automatically delayed to match video # Multiple audio sources with different timing comp.add(transparent1).start(0).audio(enabled=True, volume=0.8) # Main audio comp.add(transparent2).start(5).audio(enabled=True, volume=0.3) # Background music comp.add(transparent3).start(10).audio(enabled=True, volume=0.5) # Sound effects ``` ### Audio Mixing The system automatically mixes audio from multiple layers: * **Single audio source**: Used directly * **Multiple audio sources**: Mixed with volume control * **Timing**: Audio delays automatically match video timing ## Performance Tips ### Optimize for Speed * **Shorter segments**: Trim videos to only needed parts * **Reasonable overlaps**: Avoid too many overlapping layers * **Fast encoding**: Use faster encoder presets for testing ### Memory Management * **Large videos**: Consider trimming before composition * **Many layers**: Test with fewer layers first * **Long compositions**: Break into segments if needed ## What's Next? Choose the right export format and quality settings Explore complete timing and animation examples