#!/usr/bin/env python3
# The Picamera2 Library supports multiple cameras.
# This wrapper forwards the given commands to all cameras.
# Picamera2 Manual:
# https://datasheets.raspberrypi.com/camera/picamera2-manual.pdf
__author__ = "Gernot Walzl"
__date__ = "2025-12-21"
import argparse
import time
import libcamera
from picamera2 import Picamera2
from picamera2.encoders import H264Encoder, Quality
class MultiPicam2:
def __init__(self):
"""Picamera2 Manual - 8.7. Multiple Cameras"""
self._picams = []
for cam_info in Picamera2.global_camera_info():
self._picams.append(Picamera2(cam_info['Num']))
def configure_still(self):
for idx, picam2 in enumerate(self._picams):
flip = idx % 2
capture_config = picam2.create_still_configuration(
transform=libcamera.Transform(hflip=flip, vflip=flip)
)
picam2.configure(capture_config)
def start(self):
for picam2 in self._picams:
picam2.start()
def stop(self):
for picam2 in self._picams:
picam2.stop()
def autofocus(self):
"""Picamera2 Manual - 5.3.4. Triggering an Autofocus Cycle"""
success = True
af_jobs = []
for picam2 in self._picams:
af_jobs.append(picam2.autofocus_cycle(wait=False))
for idx, picam2 in enumerate(self._picams):
success &= picam2.wait(af_jobs[idx])
return success
def capture_files(self, filename="img_{:03d}_{:01d}.jpg",
num_files=10, delay=0.5):
for idx_file in range(num_files):
time_started = time.time()
for idx_cam, picam2 in enumerate(self._picams):
picam2.capture_file(filename.format(idx_file, idx_cam))
sleep_secs = delay - (time.time() - time_started)
if sleep_secs > 0.0:
time.sleep(sleep_secs)
def start_and_capture_files(self, filename="img_{:03d}_{:01d}.jpg",
initial_delay=1.0,
num_files=10, delay=0.5):
"""Picamera2 Manual - 2.4. Picamera2′s high-level API"""
self.configure_still()
self.start()
time.sleep(initial_delay)
self.autofocus()
self.capture_files(filename, num_files, delay)
self.stop()
def configure_video(self):
for idx, picam2 in enumerate(self._picams):
flip = idx % 2
capture_config = picam2.create_video_configuration(
transform=libcamera.Transform(hflip=flip, vflip=flip)
)
picam2.configure(capture_config)
def start_recording(self, filename="vid_{:01d}.h264"):
for idx_cam, picam2 in enumerate(self._picams):
encoder = H264Encoder()
picam2.start_recording(
encoder, filename.format(idx_cam), quality=Quality.HIGH)
def stop_recording(self):
for picam2 in self._picams:
picam2.stop_recording()
def start_and_record_videos(self, filename="vid_{:01d}.h264",
initial_delay=1.0, duration=10.0):
"""Picamera2 Manual - 2.4. Picamera2′s high-level API"""
self.configure_video()
time.sleep(initial_delay)
self.start_recording(filename)
time.sleep(duration)
self.stop_recording()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument(
'-o', '--output', type=str, default="img_{:03d}_{:01d}.jpg")
parser.add_argument(
'--initial-delay', type=float, default=1.0)
parser.add_argument(
'--num-files', type=int, default=10)
parser.add_argument(
'--delay', type=float, default=0.5)
args = parser.parse_args()
multipicam2 = MultiPicam2()
multipicam2.start_and_capture_files(
args.output, args.initial_delay, args.num_files, args.delay)