# 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