MultiCameraManager¶
gopro_sdk.multi_camera.MultiCameraManager
¶
MultiCameraManager(
camera_ids: list[str] | None = None,
timeout_config: TimeoutConfig | None = None,
config_manager: CohnConfigManager | None = None,
max_concurrent: int = 5,
wifi_ssid: str | None = None,
wifi_password: str | None = None,
offline_mode: bool = True,
)
Multi-camera manager.
Supports managing multiple GoPro cameras simultaneously, providing: 1. Batch connection/disconnection 2. Concurrent command execution 3. Status synchronization 4. Error isolation 5. Health monitoring
Example usage:
async with MultiCameraManager(["9811", "9812", "9813"]) as manager:
# Batch connect
await manager.connect_all()
# Execute commands concurrently
results = await manager.execute_all(lambda client: client.start_recording())
# Get all statuses
statuses = await manager.get_all_status()
Initialize multi-camera manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_ids
|
list[str] | None
|
List of camera serial numbers (last four digits), default empty |
None
|
timeout_config
|
TimeoutConfig | None
|
Timeout configuration, default uses default values |
None
|
config_manager
|
CohnConfigManager | None
|
COHN configuration manager, default creates new instance |
None
|
max_concurrent
|
int
|
Maximum concurrency limit (prevents overload) |
5
|
wifi_ssid
|
str | None
|
WiFi SSID (used for camera HTTP connection) |
None
|
wifi_password
|
str | None
|
WiFi password (used with wifi_ssid) |
None
|
offline_mode
|
bool
|
Offline mode (default True), BLE connection only, no preview/download support |
True
|
Source code in src/gopro_sdk/multi_camera.py
Attributes¶
semaphore
property
¶
Lazy create semaphore (ensures creation in correct event loop).
global_lock
property
¶
Lazy create global lock (ensures creation in correct event loop).
Functions¶
__aenter__
async
¶
__aexit__
async
¶
connect_all
async
¶
Batch connect all cameras.
Default uses BLE+HTTP hybrid mode (automatically manages COHN).
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Connection result for each camera {camera_id: success} |
Usage example:
Source code in src/gopro_sdk/multi_camera.py
disconnect_all
async
¶
Batch disconnect all cameras.
Source code in src/gopro_sdk/multi_camera.py
reconnect_all
async
¶
Batch reconnect all cameras.
Default uses BLE+HTTP hybrid mode.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Reconnection result for each camera {camera_id: success} |
Source code in src/gopro_sdk/multi_camera.py
execute_all
async
¶
execute_all(
command: Callable[[GoProClient], Any],
camera_ids: list[str] | None = None,
) -> dict[str, tuple[bool, Any]]
Execute command concurrently on all (or specified) cameras.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
Callable[[GoProClient], Any]
|
Command to execute (lambda or function) |
required |
camera_ids
|
list[str] | None
|
Target camera list, None means all cameras |
None
|
Returns:
| Type | Description |
|---|---|
dict[str, tuple[bool, Any]]
|
Execution result for each camera {camera_id: (success, result_or_error)} |
Usage example:
# Start recording on all cameras
results = await manager.execute_all(lambda client: client.start_recording())
# Get status from specific cameras
results = await manager.execute_all(lambda client: client.get_status(), camera_ids=["9811", "9812"])
Source code in src/gopro_sdk/multi_camera.py
execute_sequentially
async
¶
execute_sequentially(
command: Callable[[GoProClient], Any],
camera_ids: list[str] | None = None,
delay: float = 0.0,
) -> dict[str, tuple[bool, Any]]
Execute command sequentially on all (or specified) cameras.
Suitable for scenarios requiring strict ordering or avoiding conflicts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
command
|
Callable[[GoProClient], Any]
|
Command to execute |
required |
camera_ids
|
list[str] | None
|
Target camera list, None means all cameras |
None
|
delay
|
float
|
Delay between each command (seconds) |
0.0
|
Returns:
| Type | Description |
|---|---|
dict[str, tuple[bool, Any]]
|
Execution result for each camera {camera_id: (success, result_or_error)} |
Source code in src/gopro_sdk/multi_camera.py
check_all_health
async
¶
Check health status of all cameras.
Returns:
| Type | Description |
|---|---|
dict[str, bool]
|
Health status for each camera {camera_id: is_healthy} |
Source code in src/gopro_sdk/multi_camera.py
get_all_status
async
¶
Get status information for all cameras.
Returns:
| Type | Description |
|---|---|
dict[str, dict[str, Any]]
|
Status dictionary for each camera {camera_id: status_dict} |
Source code in src/gopro_sdk/multi_camera.py
get_manager_status
¶
Get overall manager status.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
Manager status dictionary |
Source code in src/gopro_sdk/multi_camera.py
get_client
¶
Get client for specified camera.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
Returns:
| Type | Description |
|---|---|
GoProClient | None
|
Client instance, None if not found |
Source code in src/gopro_sdk/multi_camera.py
get_connected_cameras
¶
get_healthy_cameras
¶
get_failed_cameras
¶
add_camera
async
¶
Add camera to manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
auto_connect
|
bool
|
Whether to automatically connect |
False
|
Returns:
| Type | Description |
|---|---|
bool
|
Whether addition was successful |
Usage example:
# Add without connecting
await manager.add_camera("9814")
# Add and automatically connect
await manager.add_camera("9815", auto_connect=True)
Source code in src/gopro_sdk/multi_camera.py
remove_camera
async
¶
Remove camera from manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
disconnect
|
bool
|
Whether to disconnect first |
True
|
Returns:
| Type | Description |
|---|---|
bool
|
Whether removal was successful |
Usage example:
# Remove and disconnect
await manager.remove_camera("9814")
# Remove only, don't disconnect
await manager.remove_camera("9814", disconnect=False)
Source code in src/gopro_sdk/multi_camera.py
has_camera
¶
Check if camera is in manager.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether it exists |
is_connected
¶
Check if camera is connected.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
Returns:
| Type | Description |
|---|---|
bool
|
Whether it is connected |
Source code in src/gopro_sdk/multi_camera.py
get_camera_status
¶
Get camera status.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
camera_id
|
str
|
Camera serial number |
required |
Returns:
| Type | Description |
|---|---|
CameraStatus | None
|
Camera status, None if not found |
list_all_cameras
¶
clear_all
async
¶
Clear all cameras (disconnect and remove).
Source code in src/gopro_sdk/multi_camera.py
Usage Examples¶
Basic Multi-Camera Control¶
import asyncio
from gopro_sdk import MultiCameraManager
async def main():
manager = MultiCameraManager()
cameras = {
"cam1": "1234",
"cam2": "5678",
"cam3": "9012",
}
try:
# Connect all cameras
await manager.connect_all(
cameras,
ssid="your-wifi",
password="password"
)
# Start recording on all cameras
await manager.execute_all("set_shutter", on=True)
# Wait for recording
await asyncio.sleep(10)
# Stop recording on all cameras
await manager.execute_all("set_shutter", on=False)
# Get status from all cameras
statuses = await manager.get_all_status()
for cam_id, status in statuses.items():
battery = status.get('battery_percent', 'N/A')
print(f"{cam_id}: Battery {battery}%")
finally:
await manager.disconnect_all()
asyncio.run(main())
Synchronized Recording¶
async def synchronized_recording(
camera_ids: dict,
duration: int,
wifi_ssid: str,
wifi_password: str
):
"""Record on multiple cameras simultaneously."""
manager = MultiCameraManager()
try:
await manager.connect_all(camera_ids, wifi_ssid, wifi_password)
# All cameras start at the same time
await manager.execute_all("set_shutter", on=True)
await asyncio.sleep(duration)
await manager.execute_all("set_shutter", on=False)
print("Recording completed on all cameras")
finally:
await manager.disconnect_all()
Error Handling¶
async def robust_multi_camera():
"""Handle errors in multi-camera scenarios."""
manager = MultiCameraManager()
cameras = {"cam1": "1234", "cam2": "5678"}
try:
await manager.connect_all(cameras, "wifi", "password")
except Exception as e:
print(f"Failed to connect all cameras: {e}")
# Check which cameras connected
for cam_id, client in manager.clients.items():
if client:
print(f"{cam_id}: Connected")
else:
print(f"{cam_id}: Failed")
# Continue with connected cameras only
await manager.execute_all("set_shutter", on=True)
See Also¶
- GoProClient - Single camera control
- CohnConfigManager - Configuration management