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():
async with MultiCameraManager(
camera_ids=["1234", "5678", "9012"],
) as manager:
# Connect all cameras (BLE only by default)
results = await manager.connect_all()
print(f"Connection results: {results}")
# {"1234": True, "5678": True, "9012": False}
# Start recording on all cameras
await manager.execute_all(lambda c: c.start_recording())
await asyncio.sleep(10)
# Stop recording on all cameras
await manager.execute_all(lambda c: c.stop_recording())
asyncio.run(main())
Synchronized Recording with WiFi¶
import asyncio
from gopro_sdk import MultiCameraManager
async def synchronized_recording(duration: int = 10):
"""Record on multiple cameras simultaneously."""
async with MultiCameraManager(
camera_ids=["1234", "5678"],
wifi_ssid="your-wifi",
wifi_password="password",
offline_mode=False,
) as manager:
await manager.connect_all()
# All cameras start at the same time
await manager.execute_all(lambda c: c.start_recording())
await asyncio.sleep(duration)
await manager.execute_all(lambda c: c.stop_recording())
print("Recording completed on all cameras")
asyncio.run(synchronized_recording())
Error Handling and Status Tracking¶
import asyncio
from gopro_sdk import MultiCameraManager
async def robust_multi_camera():
"""Handle errors in multi-camera scenarios."""
async with MultiCameraManager(
camera_ids=["1234", "5678", "9012"],
) as manager:
# connect_all returns per-camera success/failure
results = await manager.connect_all()
# Check which cameras connected
connected = manager.get_connected_cameras()
failed = manager.get_failed_cameras()
print(f"Connected: {connected}, Failed: {failed}")
# Execute commands on connected cameras only
results = await manager.execute_all(
lambda c: c.start_recording(),
camera_ids=connected,
)
for cam_id, (success, result) in results.items():
if success:
print(f"{cam_id}: Recording started")
else:
print(f"{cam_id}: Failed - {result}")
# Get overall manager status
status = manager.get_manager_status()
print(f"Total: {status['total_cameras']}, "
f"Connected: {status['connected_cameras']}")
asyncio.run(robust_multi_camera())
Dynamic Camera Management¶
import asyncio
from gopro_sdk import MultiCameraManager
async def dynamic_cameras():
"""Add and remove cameras dynamically."""
async with MultiCameraManager(
camera_ids=["1234"],
) as manager:
await manager.connect_all()
# Add another camera (with auto-connect)
await manager.add_camera("5678", auto_connect=True)
# Execute on all connected cameras
await manager.execute_all(lambda c: c.start_recording())
await asyncio.sleep(5)
await manager.execute_all(lambda c: c.stop_recording())
# Remove a camera
await manager.remove_camera("5678")
asyncio.run(dynamic_cameras())
See Also¶
- GoProClient - Single camera control
- CohnConfigManager - Configuration management