The libcamera-based Python interface to Raspberry Pi cameras, based on the original Picamera library
—
Preview system supporting multiple display methods including Qt widgets, DRM/KMS direct rendering, and headless operation. The preview system provides real-time camera feed display with overlay support and platform-specific optimizations.
Start, stop, and manage camera preview display.
def start_preview(
self,
preview: Preview = None,
**kwargs
):
"""
Start camera preview display.
Parameters:
- preview: Preview type ("null", "drm", "qt", "qtgl") or Preview object
- **kwargs: Preview-specific parameters
Common kwargs:
- width: int, preview window width
- height: int, preview window height
- x: int, window x position
- y: int, window y position
- fullscreen: bool, fullscreen display
- title: str, window title
Raises:
- RuntimeError: If preview system fails to initialize
"""
def stop_preview(self):
"""
Stop camera preview display.
Closes preview window and releases display resources.
"""
def attach_preview(self, preview):
"""
Attach custom preview object.
Parameters:
- preview: Preview instance (NullPreview, DrmPreview, etc.)
"""
def detach_preview(self):
"""
Detach current preview object.
Preview remains running but is no longer managed by camera.
"""
def set_overlay(self, overlay):
"""
Set preview overlay content.
Parameters:
- overlay: PIL Image or numpy array for overlay graphics
"""Enumeration of available preview display methods.
class Preview(Enum):
"""Preview display types."""
NULL = "null" # No display (headless)
DRM = "drm" # Direct DRM/KMS rendering
QT = "qt" # Qt widget display
QTGL = "qtgl" # Qt OpenGL displayBase preview interface and concrete implementations.
class PreviewBase:
"""Base class for preview implementations."""
def __init__(self, **kwargs):
"""
Initialize preview with parameters.
Common parameters:
- width: int, display width
- height: int, display height
- x: int, window x position
- y: int, window y position
"""
def start(self, picam2: Picamera2):
"""
Start preview with camera instance.
Parameters:
- picam2: Picamera2 instance providing frames
"""
def stop(self):
"""Stop preview and clean up resources."""
def set_overlay(self, overlay):
"""
Set overlay graphics.
Parameters:
- overlay: PIL Image or numpy array
"""
def render_request(self, completed_request: CompletedRequest):
"""
Render frame from completed request.
Parameters:
- completed_request: CompletedRequest with frame data
"""
class NullPreview(PreviewBase):
"""
Null preview for headless operation.
Provides preview interface without actual display.
Useful for server applications and automated capture.
"""
class DrmPreview(PreviewBase):
"""
Direct rendering via DRM/KMS.
High-performance preview using direct hardware access.
Requires DRM/KMS support and appropriate permissions.
Parameters:
- x: int, display x offset
- y: int, display y offset
- width: int, display width (0 = full screen width)
- height: int, display height (0 = full screen height)
- plane_alpha: float, alpha blending (0.0-1.0)
"""
class QtPreview(PreviewBase):
"""
Qt widget-based preview display.
Cross-platform preview using Qt framework.
Provides window management and user interaction.
Parameters:
- parent: QWidget, parent widget
- width: int, window width
- height: int, window height
- keep_ar: bool, maintain aspect ratio
- title: str, window title
"""
class QtGlPreview(PreviewBase):
"""
Qt OpenGL-based preview display.
Hardware-accelerated preview using OpenGL rendering.
Provides better performance than QtPreview for high-resolution streams.
Parameters: Same as QtPreview plus:
- shader: str, custom fragment shader
- vertex_shader: str, custom vertex shader
"""from picamera2 import Picamera2, Preview
picam2 = Picamera2()
preview_config = picam2.create_preview_configuration()
picam2.configure(preview_config)
# Start with automatic preview detection
picam2.start(show_preview=True)
# Or explicitly start preview
picam2.start()
picam2.start_preview()
# Keep preview running
input("Press Enter to stop preview...")
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
# Qt widget preview with custom window
picam2.start_preview(Preview.QT, width=800, height=600, title="Camera Feed")
time.sleep(5)
# Switch to OpenGL preview for better performance
picam2.stop_preview()
picam2.start_preview(Preview.QTGL, width=1024, height=768)
time.sleep(5)
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
# Full-screen DRM preview (requires root or appropriate permissions)
picam2.start_preview(Preview.DRM,
x=0, y=0,
width=0, height=0, # 0 = full screen
plane_alpha=1.0)
input("Press Enter to stop full-screen preview...")
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2
from picamera2.previews import QtPreview
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
# Create custom preview with specific settings
preview = QtPreview(width=640, height=480, keep_ar=True, title="My Camera")
# Attach and start
picam2.attach_preview(preview)
picam2.start()
# Preview is now active
time.sleep(10)
# Can detach for independent control
picam2.detach_preview()
# Preview continues running independently
# Stop preview manually
preview.stop()
picam2.close()from picamera2 import Picamera2, Preview
from PIL import Image, ImageDraw, ImageFont
import numpy as np
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
picam2.start_preview(Preview.QT)
# Create overlay graphics
overlay = Image.new("RGBA", (640, 480), (0, 0, 0, 0)) # Transparent
draw = ImageDraw.Draw(overlay)
# Draw overlay elements
draw.rectangle([10, 10, 200, 50], fill=(255, 0, 0, 128)) # Semi-transparent red
draw.text((20, 20), "RECORDING", fill=(255, 255, 255, 255))
# Apply overlay to preview
picam2.set_overlay(overlay)
time.sleep(10)
# Update overlay
draw.rectangle([10, 60, 200, 100], fill=(0, 255, 0, 128)) # Green bar
draw.text((20, 70), "LIVE", fill=(255, 255, 255, 255))
picam2.set_overlay(overlay)
time.sleep(5)
# Remove overlay
picam2.set_overlay(None)
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
from PIL import Image, ImageDraw
import threading
import time
import datetime
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
picam2.start_preview(Preview.QT)
def update_overlay():
"""Update overlay with current timestamp."""
while running:
# Create overlay with timestamp
overlay = Image.new("RGBA", (640, 480), (0, 0, 0, 0))
draw = ImageDraw.Draw(overlay)
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
draw.rectangle([10, 10, 300, 40], fill=(0, 0, 0, 128))
draw.text((15, 18), timestamp, fill=(255, 255, 255, 255))
picam2.set_overlay(overlay)
time.sleep(1)
# Start overlay update thread
running = True
overlay_thread = threading.Thread(target=update_overlay)
overlay_thread.start()
input("Press Enter to stop...")
# Stop overlay updates
running = False
overlay_thread.join()
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
# For server/headless applications
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
# Use null preview (no display)
picam2.start_preview(Preview.NULL)
# Camera runs without display - good for capture-only applications
for i in range(10):
picam2.capture_file(f"headless_{i:03d}.jpg")
time.sleep(1)
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
picam2 = Picamera2()
# Configure with multiple streams
config = picam2.create_video_configuration(
main={"size": (1920, 1080), "format": "YUV420"},
lores={"size": (640, 480), "format": "YUV420"}
)
# Specify which stream to display
config.display = "lores" # Use low-res stream for preview
picam2.configure(config)
picam2.start()
picam2.start_preview(Preview.QT)
# Preview shows low-res stream while main stream can be used for recording
# This reduces preview overhead while maintaining recording quality
time.sleep(10)
picam2.stop_preview()
picam2.close()from picamera2 import Picamera2, Preview
from picamera2.platform import Platform, get_platform
picam2 = Picamera2()
picam2.configure(picam2.create_preview_configuration())
picam2.start()
# Choose preview based on platform capabilities
platform = get_platform()
if platform == Platform.VC4:
# Raspberry Pi 4 and earlier - use DRM for best performance
picam2.start_preview(Preview.DRM)
elif platform == Platform.PISP:
# Raspberry Pi 5 - can use Qt or DRM
picam2.start_preview(Preview.QTGL) # Hardware accelerated
else:
# Generic platform
picam2.start_preview(Preview.QT)
time.sleep(10)
picam2.stop_preview()
picam2.close()Install with Tessl CLI
npx tessl i tessl/pypi-picamera2