Outputs (File, FFMpeg, Circular)
Relevant source files
The following files were used as context for generating this wiki page:The picamera2.outputs module provides a flexible framework for handling encoded camera data. It defines a set of classes responsible for directing the output of encoders to various destinations, such as files, network streams, or in-memory buffers. This system is designed to be extensible, with a base Output class that other more specialized output handlers inherit from.
The core responsibility of an output class is to receive encoded frames from an encoder (e.g., H264Encoder, JpegEncoder) and process them. This could mean writing them to a file (FileOutput), muxing them into a container format like MP4 (FfmpegOutput, PyavOutput), or holding them in a temporary buffer for pre-event recording (CircularOutput, CircularOutput2). These output objects are typically passed to the Picamera2.start_encoder() method.
Architecture and Class Hierarchy
All output classes inherit from the base Output class, which defines the fundamental interface for handling encoded frames. This includes methods for starting, stopping, and processing frames.
The following diagram illustrates the inheritance structure of the main output classes.
Core Output Class
The Output class is the abstract base for all other output handlers.
outputframe(frame, keyframe, timestamp, packet, audio): The primary method called by an encoder to pass an encoded frame.start()/stop(): Control the recording state.start()setsself.recording = True, andstop()sets it toFalse.outputtimestamp(timestamp): An optional method to write frame timestamps to a separate file if aptsfile is provided during initialization.
Sources: picamera2/outputs/output.py:8-39
FileOutput
FileOutput is the simplest output handler, designed to write encoded data directly to a file-like object. This can be a local file, a network socket, or any io.BufferedIOBase object.
Key Features
- Flexible Destination: Can write to a file path (string or
Path), an existing file handle, or a network socket. - Automatic File Handling: If given a path, it automatically opens the file for writing in binary mode (
"wb") and closes it onstop(). - Datagram Splitting: When writing to a UDP socket (
SOCK_DGRAM), it can automatically split frames into packets smaller than the maximum UDP datagram size (65507 bytes by default). - Connection Error Handling: Provides a
connectiondeadcallback to handle exceptions likeBrokenPipeErrorthat occur during network streaming.
Initialization
| Parameter | Type | Description |
|---|---|---|
file | str, Path, io.BufferedIOBase | The destination file or stream. |
pts | str, BufferedWriter | Optional file to write presentation timestamps to. |
split | int | Maximum size for splitting data, primarily for UDP datagrams. |
Sources: picamera2/outputs/fileoutput.py:11-23
Frame Handling Flow
The following diagram shows how FileOutput processes an incoming frame.
FfmpegOutput
FfmpegOutput leverages an external FFmpeg process to mux video and audio streams into various container formats (e.g., MP4, MKV). It communicates with the FFmpeg process via standard input pipes.
Key Features
- Wide Format Support: Supports any container format and codec that FFmpeg can handle.
- Audio Muxing: Can take an audio stream from a specified device and mux it with the video. Audio is handled in a separate thread.
- Process Management: Manages the lifecycle of the FFmpeg subprocess, starting it on
start()and terminating it onstop().
Initialization
| Parameter | Type | Description |
|---|---|---|
output_file | str | The output filename. '-' can be used for stdout. |
audio_device | str | ALSA device for audio input (e.g., 'plughw:1,0'). |
audio_samplerate | int | Sample rate for the audio stream. |
audio_channels | int | Number of audio channels. |
audio_codec | str | The audio codec to use. |
audio_bitrate | int | The bitrate for the audio stream. |
audio_filter | str | Custom audio filter to apply. |
vflip | bool | Vertically flip the video. |
hflip | bool | Horizontally flip the video. |
bitrate | int | Bitrate for the video stream. |
repeat | bool | Repeats the I-frame header for every P-frame. |
iperiod | int | The I-frame interval. |
pts | str | Optional file to write presentation timestamps to. |
on_error | func | Callback function to be executed if FFmpeg terminates unexpectedly. |
Sources: picamera2/outputs/ffmpegoutput.py:16-44
Example Usage
In apps/app_full.py, FfmpegOutput is used to save video recordings to various container formats like .mp4.
// Source: apps/app_full.py:161-165
if vid_tab.filetype.currentText() in ["mp4", "mkv", "mov", "ts", "avi"]:
output = FfmpegOutput(
f"{vid_tab.filename.text() if vid_tab.filename.text() else 'test'}.{vid_tab.filetype.currentText()}"
)
Circular Buffers
Circular buffers are designed for pre-event recording, where the camera continuously records to a buffer of a fixed duration. When an event of interest occurs, the application can save the contents of the buffer, thereby capturing footage from before the event was triggered.
CircularOutput
This is the original circular buffer implementation. It inherits from FileOutput and writes frames to an in-memory collections.deque. It can save the buffer's content to a new FileOutput object upon request.
start_recording(output, format): Begins saving the circular buffer content to the specified output file.stop_recording(): Stops saving to the output file but continues to fill the circular buffer.
Sources: picamera2/outputs/circularoutput.py
CircularOutput2
A more modern and flexible implementation that inherits directly from Output. Instead of being tied to FileOutput, it can be composed with any other Output object (like PyavOutput), allowing for features like time-shifted recording of video and audio directly to an MP4 file.
buffer_duration_ms: A configurable property to set the buffer length in milliseconds.open_output(output): Starts draining the circular buffer into the providedoutputobject. The buffer continues to be filled.close_output(): Stops draining the buffer to the current output, which can then be finalized.
Sources: picamera2/outputs/circularoutput2.py:13-70
CircularOutput2 Logic
The following diagram shows the logic for handling frames in CircularOutput2.
PyavOutput
PyavOutput provides a more efficient alternative to FfmpegOutput by using PyAV, which are Python bindings for the libav libraries used by FFmpeg. This avoids the overhead of creating and communicating with an external process.
Key Features
- Direct
libavIntegration: Calls directly intolibavfunctions for muxing, which is more efficient than piping to an FFmpeg process. - Accurate Timestamps: Can pass precise timestamps from the encoder directly to the muxer.
- Stream Management: An encoder notifies
PyavOutputof its streams (_add_stream), andPyavOutputcreates corresponding output streams in the container. When a frame arrives, its packet is muxed into the container.
Frame Handling
When outputframe is called, PyavOutput takes the av.Packet (or creates one if not provided), associates it with the correct stream in the output container, and calls self._container.mux(packet) to write it.
Sources: picamera2/outputs/pyavoutput.py:46-72
Summary
The picamera2.outputs module offers a tiered set of tools for handling encoded data. For simple file writing, FileOutput is sufficient. For creating standard video files like MP4, FfmpegOutput provides a robust solution by leveraging the power of an external FFmpeg process, while PyavOutput offers a more tightly integrated and efficient alternative. For applications requiring pre-event capture, CircularOutput and the more versatile CircularOutput2 provide powerful in-memory buffering capabilities. The choice of output class depends on the specific requirements of the application, from simple file saving to complex multimedia muxing.
Sources: picamera2/outputs/init.py, apps/app_full.py, tests/quality_check.py