This documentation page is also available as an interactive notebook. You can launch the notebook in
Kaggle or Colab, or download it for use with an IDE or local Jupyter installation, by clicking one of the
above links.
Burn text, captions, or watermarks directly into video files.
Problem
You need to add text to videos—captions, watermarks, titles, or dynamic
labels. Manual video editing doesn’t scale for batch processing.
Solution
What’s in this recipe:
- Add simple text overlays
- Create styled captions with backgrounds
- Position text with alignment options
- Crop a rectangular region from a video
Use video.overlay_text() to burn text into videos with full control
over styling and position, and video.crop() to extract a rectangular
region.
Setup
%pip install -qU pixeltable
# Create a fresh directory
pxt.drop_dir('overlay_demo', force=True)
pxt.create_dir('overlay_demo')
Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata
Created directory ‘overlay_demo’.
<pixeltable.catalog.dir.Dir at 0x17e873990>
Load sample videos
# Create a video table
videos = pxt.create_table(
'overlay_demo/videos', {'video': pxt.Video, 'title': pxt.String}
)
# Insert a sample video
videos.insert(
[
{
'video': 's3://multimedia-commons/data/videos/mp4/ffe/ffb/ffeffbef41bbc269810b2a1a888de.mp4',
'title': 'Sample Video',
}
]
)
Created table ‘videos’.
Inserted 1 row with 0 errors in 3.21 s (0.31 rows/s)
1 row inserted.
Add a simple text overlay
# Add a simple watermark in the corner
videos.add_computed_column(
watermarked=videos.video.overlay_text(
'My Brand',
font_size=24,
color='white',
opacity=0.7,
horizontal_align='right',
horizontal_margin=20,
vertical_align='top',
vertical_margin=20,
)
)
Added 1 column value with 0 errors in 1.25 s (0.80 rows/s)
1 row updated.
Add YouTube-style captions
# Add a caption with a semi-transparent background box
videos.add_computed_column(
captioned=videos.video.overlay_text(
'This is a sample caption',
font_size=32,
color='white',
box=True, # Add background box
box_color='black',
box_opacity=0.8,
box_border=[6, 14], # Padding: [top/bottom, left/right]
horizontal_align='center',
vertical_align='bottom',
vertical_margin=70, # Distance from bottom
)
)
Added 1 column value with 0 errors in 1.08 s (0.92 rows/s)
1 row updated.
Add dynamic titles from table columns
# Add video title as an overlay (dynamic per video)
videos.add_computed_column(
titled=videos.video.overlay_text(
videos.title, # Use the title column!
font_size=48,
color='yellow',
opacity=1.0,
horizontal_align='center',
vertical_align='top',
vertical_margin=30,
)
)
Added 1 column value with 0 errors in 1.15 s (0.87 rows/s)
1 row updated.
# View all versions
videos.select(
videos.title,
videos.video,
videos.watermarked,
videos.captioned,
videos.titled,
).collect()
Crop a region from a video
Use video.crop() to extract a rectangular region from a video. This is
useful for focusing on a specific area of interest, removing borders, or
preparing clips for object-specific analysis.
# Crop using xywh format (default): [x, y, width, height]
videos.add_computed_column(cropped=videos.video.crop([100, 50, 320, 240]))
# Crop using xyxy format (common in object detection pipelines):
# videos.add_computed_column(
# cropped_xyxy=videos.video.crop([100, 50, 420, 290], bbox_format='xyxy')
# )
Added 1 column value with 0 errors in 0.56 s (1.78 rows/s)
1 row updated.
Explanation
Positioning options:
Styling options:
Background box options:
Requirements:
- FFmpeg must be installed and in PATH
See also