Working with Camera Streams
Relevant source files
The following files were used as context for generating this wiki page:In the picamera2 library, streams are the fundamental mechanism for getting image data from the camera. The library is designed around configuring one or more streams, each with specific properties like resolution and pixel format, to suit different use cases such as live preview, high-resolution still capture, or video encoding. A set of stream configurations is managed within a CameraConfiguration object, which acts as a blueprint for a specific camera "mode".
The system supports up to three primary types of streams simultaneously: main, lores (low-resolution), and raw. The main stream is typically used for the highest quality output, such as still images or primary video. The lores stream provides a lower-resolution, often YUV, feed suitable for efficient preview or secondary encoding. The raw stream provides direct, unprocessed data from the camera sensor. By defining and switching between different configurations, an application can dynamically change the camera's behavior to perform various tasks.
Sources: picamera2/picamera2.py:1003-1006, 1026-1029, 1049-1052
Stream Configuration
At the heart of stream management is the CameraConfiguration object, which is essentially a Python dictionary that defines all aspects of a camera mode, including the properties of each active stream.
Sources: picamera2/configuration.py:10-15, picamera2/picamera2.py:1120-1126
The CameraConfiguration Object
A CameraConfiguration defines a complete camera mode. It is generated by helper methods like create_preview_configuration and then applied to the camera using picam2.configure(). It contains stream definitions (main, lores, raw) and other parameters like transform, colour_space, and buffer_count.
The diagram below shows the conceptual structure of a camera configuration.
This diagram illustrates the key components of a CameraConfiguration dictionary, including stream definitions and global settings.
Sources: picamera2/picamera2.py:1003-1025
Stream Types
picamera2 supports three named streams that can be configured simultaneously:
main: The primary stream. It is mandatory and typically configured for the main purpose, such as high-resolution still capture or video recording.lores: An optional, lower-resolution stream. It must be a YUV format on VC4 platforms. It's useful for tasks that can operate on smaller images, like running a preview window while encoding a higher-resolution main stream. Its dimensions cannot exceed the main stream's dimensions.raw: An optional stream that provides raw Bayer data directly from the sensor. This is only available on Raspberry Pi cameras, not USB webcams. It is used for applications requiring maximum image quality and post-processing control.
Sources: picamera2/picamera2.py:1097-1104, picamera2/picamera2.py:1168-1170
The StreamConfiguration Object
Each stream (main, lores, raw) is defined by a StreamConfiguration object, which is a dictionary specifying its properties.
| Parameter | Type | Description |
|---|---|---|
format | str | The pixel format of the stream (e.g., "XBGR8888", "YUV420", "SRGGB10_CSI2P"). |
size | tuple(int, int) | The resolution of the stream as (width, height). Width and height must be even. |
stride | int | The number of bytes in a row of image data. If not set, it's determined automatically. |
framesize | int | The total size of the buffer in bytes. This is determined by libcamera after configuration. |
preserve_ar | bool | Whether to preserve the aspect ratio when the camera adjusts the resolution. Defaults to True for main and False for lores. |
Sources: picamera2/picamera2.py:971-985, 1215-1219, picamera2/configuration.py:18-22
Creating Configurations
The Picamera2 class provides helper methods to easily create standard configurations for common use cases. These methods return a CameraConfiguration dictionary that can be further customized before being applied.
Configuration Helpers
The primary helper methods are:
create_preview_configuration(): Creates a configuration suitable for live preview. Defaults to a moderate resolution (640x480) and an RGB format (XBGR8888) for themainstream.create_still_configuration(): Creates a configuration for high-resolution still captures. Defaults to the full sensor resolution and aBGR888format.create_video_configuration(): Creates a configuration for video recording. Defaults to a standard video resolution (1280x720).
Each of these methods accepts arguments to customize the main, lores, and raw streams.
The following diagram shows the process of creating and applying a configuration.
This flowchart shows how a user creates a configuration using a helper, customizes it, and applies it to the camera.
Sources: picamera2/picamera2.py:1003-1078
Disabling Streams
To disable an optional stream (lores or raw), you can pass None for its configuration. This is useful for saving memory and processing power when a stream is not needed.
# From tests/no_raw.py
# Create a preview configuration without a raw stream.
config = picam2.create_preview_configuration(raw=None)
picam2.configure(config)
Sources: tests/no_raw.py:8-12
Applying Configurations and Switching Modes
Once a CameraConfiguration is created, it must be applied to the camera. The library also supports seamlessly switching between different configurations, which is essential for applications that need to transition between a live preview and a high-resolution capture.
Applying a Configuration
A configuration is applied by calling the picam2.configure() method. This can only be done when the camera is stopped.
# Create and apply a preview configuration
preview_config = picam2.create_preview_configuration()
picam2.configure(preview_config)
picam2.start()
Sources: picamera2/picamera2.py:1379-1381
Switching Modes
The picam2.switch_mode() method provides a high-level way to stop the camera, apply a new configuration, and restart it. More advanced methods like switch_mode_and_capture_file() combine this with a capture operation, making it easy to perform tasks like taking a full-resolution photo while a preview is running.
The sequence diagram below illustrates the switch_mode_and_capture_file operation.
This diagram shows the internal steps picamera2 takes to switch from a preview mode to a still capture mode and back again.
Sources: picamera2/picamera2.py:1571-1599, examples/switch_mode.py
A common pattern is to switch from a preview mode to a still capture mode and then back.
# From examples/switch_mode.py
picam2 = Picamera2()
preview_config = picam2.create_preview_configuration()
picam2.configure(preview_config)
picam2.start_preview(Preview.QTGL)
picam2.start()
time.sleep(2)
still_config = picam2.create_still_configuration()
picam2.switch_mode_and_capture_file(still_config, "test.jpg")
picam2.stop_preview()
picam2.stop()
Sources: examples/switch_mode.py:8-22
Accessing Stream Data
After a frame is captured, its data is available through a CompletedRequest object. This object provides several methods to access the image data from different streams in various formats.
The CompletedRequest Object
A CompletedRequest wraps a completed libcamera request and holds the buffers for all configured streams for a single frame. You can obtain one by calling methods like picam2.capture_request(). It's crucial to call release() on the request object when you are finished with it to return the underlying buffers to the camera system.
Sources: picamera2/request.py:46-55
Access Methods
The CompletedRequest object offers several methods to get image data:
make_array(name): Returns a 2D NumPy array for the specified stream. This involves a memory copy.make_buffer(name): Returns a 1D NumPy array (a view of the buffer).make_image(name): Returns a PIL Image object.save(name, file_output): Saves the stream data to a file (e.g., as a JPEG).save_dng(file_output): Saves the raw stream data as a DNG file.
Sources: picamera2/request.py:130-151, 203-228
Direct Buffer Access with MappedArray
For zero-copy access to a stream's buffer, you can use the MappedArray context manager. This maps the camera's memory buffer directly into a NumPy array, avoiding a copy. This is highly efficient but requires careful handling, as the buffer is only valid within the with block.
This diagram shows the relationship between the main Picamera2 class, its configurations, and the objects used to access captured stream data.
Sources: picamera2/request.py:29-44, picamera2/picamera2.py, picamera2/configuration.py
Multiple Outputs and Encoders
picamera2 allows streams to be directed to different outputs, such as a preview window and a video encoder, simultaneously.
Designating Streams for Display and Encoding
When creating a configuration, the display and encode parameters specify which named stream should be used for preview and for encoding, respectively. This allows, for example, a low-resolution lores stream to be sent to a preview window while the main stream is sent to a video encoder.
# Configure main stream for video, lores for preview
video_config = picam2.create_video_configuration(
main={"size": (1920, 1080)},
lores={"size": (640, 480), "format": "YUV420"},
display="lores",
encode="main"
)
picam2.configure(video_config)
Sources: picamera2/picamera2.py:992-998, apps/app_full.py:73-74
The flow for splitting output is shown below.
This diagram illustrates how a single capture can be routed to both a preview display and a video encoder by designating different streams.
Sources: picamera2/picamera2.py:1260-1265
Using Multiple Encoders
The library supports running multiple encoders simultaneously, either on the same stream or on different streams. This is managed by adding Encoder objects to the picam2.encoders set.
# From CHANGELOG.md, indicating the feature exists
# "Support for running multiple encoders, either on the same or different streams."
Sources: CHANGELOG.md:200
Conclusion
Working with camera streams is a core concept in picamera2. The library provides a flexible and powerful system for managing them through CameraConfiguration objects. By defining main, lores, and raw streams, developers can create tailored camera modes for preview, still capture, and video recording. Helper functions simplify the creation of standard configurations, while methods like switch_mode enable dynamic transitions between them. Finally, the CompletedRequest object provides versatile and efficient methods for accessing image data, including zero-copy access with MappedArray, enabling a wide range of applications from simple image capture to complex, multi-stream video processing.