# Script Switch All Cameras

Switch between cameras by pressing a key.

This example requires the DepthAI v3 API, see [installation instructions](https://docs.luxonis.com/software-v3/depthai.md).

## Pipeline

### examples/script_switch_all_cameras.pipeline.json

```json
{"pipeline": {"connections": [{"node1Id": 6, "node1Output": "out", "node1OutputGroup": "", "node2Id": 3, "node2Input": "control", "node2InputGroup": "io"}, {"node1Id": 3, "node1Output": "out", "node1OutputGroup": "io", "node2Id": 7, "node2Input": "in", "node2InputGroup": ""}, {"node1Id": 2, "node1Output": "0", "node1OutputGroup": "dynamicOutputs", "node2Id": 3, "node2Input": "2", "node2InputGroup": "io"}, {"node1Id": 1, "node1Output": "0", "node1OutputGroup": "dynamicOutputs", "node2Id": 3, "node2Input": "1", "node2InputGroup": "io"}, {"node1Id": 0, "node1Output": "0", "node1OutputGroup": "dynamicOutputs", "node2Id": 3, "node2Input": "0", "node2InputGroup": "io"}], "globalProperties": {"calibData": null, "cameraTuningBlobSize": null, "cameraTuningBlobUri": "", "leonCssFrequencyHz": 700000000.0, "leonMssFrequencyHz": 700000000.0, "pipelineName": null, "pipelineVersion": null, "sippBufferSize": 18432, "sippDmaBufferSize": 16384, "xlinkChunkSize": -1}, "nodes": [[7, {"alias": "", "id": 7, "ioInfo": [[["", "in"], {"blocking": true, "group": "", "id": 18, "name": "in", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "XLinkOut", "parentId": -1, "properties": {"maxFpsLimit": -1.0, "metadataOnly": false, "streamName": "__x_3_out"}}], [6, {"alias": "", "id": 6, "ioInfo": [[["", "out"], {"blocking": false, "group": "", "id": 17, "name": "out", "queueSize": 8, "type": 0, "waitForMessage": false}]], "logLevel": 3, "name": "XLinkIn", "parentId": -1, "properties": {"maxDataSize": 5242880, "numFrames": 8, "streamName": "__x_3_io_control"}}], [3, {"alias": "", "id": 3, "ioInfo": [[["io", "0"], {"blocking": false, "group": "io", "id": 15, "name": "0", "queueSize": 1, "type": 3, "waitForMessage": false}], [["io", "2"], {"blocking": false, "group": "io", "id": 13, "name": "2", "queueSize": 1, "type": 3, "waitForMessage": false}], [["io", "out"], {"blocking": false, "group": "io", "id": 16, "name": "out", "queueSize": 8, "type": 0, "waitForMessage": false}], [["io", "1"], {"blocking": false, "group": "io", "id": 14, "name": "1", "queueSize": 1, "type": 3, "waitForMessage": false}], [["io", "control"], {"blocking": true, "group": "io", "id": 12, "name": "control", "queueSize": 8, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "Script", "parentId": -1, "properties": {"processor": 1, "scriptName": "<script>", "scriptUri": "asset:__script"}}], [2, {"alias": "", "id": 2, "ioInfo": [[["dynamicOutputs", "0"], {"blocking": false, "group": "dynamicOutputs", "id": 11, "name": "0", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "raw"], {"blocking": false, "group": "", "id": 10, "name": "raw", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "mockIsp"], {"blocking": true, "group": "", "id": 9, "name": "mockIsp", "queueSize": 8, "type": 3, "waitForMessage": false}], [["", "inputControl"], {"blocking": true, "group": "", "id": 8, "name": "inputControl", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "Camera", "parentId": -1, "properties": {"boardSocket": 2, "cameraName": "", "fps": -1.0, "imageOrientation": -1, "initialControl": {"aeLockMode": false, "aeMaxExposureTimeUs": 0, "aeRegion": {"height": 0, "priority": 191204352, "width": 0, "x": 0, "y": 0}, "afRegion": {"height": 0, "priority": 0, "width": 5, "x": 24085, "y": 0}, "antiBandingMode": 100, "autoFocusMode": 3, "awbLockMode": false, "awbMode": 119, "brightness": 0, "captureIntent": 116, "chromaDenoise": 116, "cmdMask": 0, "contrast": 97, "controlMode": 104, "effectMode": 0, "enableHdr": false, "expCompensation": 0, "expManual": {"exposureTimeUs": 24085, "frameDurationUs": 0, "sensitivityIso": 0}, "frameSyncMode": 0, "lensPosAutoInfinity": 112, "lensPosAutoMacro": 139, "lensPosition": 0, "lensPositionRaw": 0.0, "lowPowerNumFramesBurst": 193, "lowPowerNumFramesDiscard": 14, "lumaDenoise": 105, "miscControls": [], "saturation": 100, "sceneMode": 105, "sharpness": 100, "strobeConfig": {"activeLevel": 0, "enable": 0, "gpioNumber": 0}, "strobeTimings": {"durationUs": 24085, "exposureBeginOffsetUs": 0, "exposureEndOffsetUs": 191204352}, "wbColorTemp": 28271}, "isp3aFps": 0, "mockIspHeight": -1, "mockIspWidth": -1, "numFramesPoolIsp": 3, "numFramesPoolPreview": 4, "numFramesPoolRaw": 3, "numFramesPoolStill": 4, "numFramesPoolVideo": 4, "outputRequests": [{"enableUndistortion": null, "fps": {"value": null}, "resizeMode": 0, "size": {"value": {"index": 0, "value": [1280, 800]}}, "type": null}], "resolutionHeight": -1, "resolutionWidth": -1}}], [1, {"alias": "", "id": 1, "ioInfo": [[["dynamicOutputs", "0"], {"blocking": false, "group": "dynamicOutputs", "id": 7, "name": "0", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "raw"], {"blocking": false, "group": "", "id": 6, "name": "raw", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "mockIsp"], {"blocking": true, "group": "", "id": 5, "name": "mockIsp", "queueSize": 8, "type": 3, "waitForMessage": false}], [["", "inputControl"], {"blocking": true, "group": "", "id": 4, "name": "inputControl", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "Camera", "parentId": -1, "properties": {"boardSocket": 1, "cameraName": "", "fps": -1.0, "imageOrientation": -1, "initialControl": {"aeLockMode": false, "aeMaxExposureTimeUs": 1852403110, "aeRegion": {"height": 51816, "priority": 14721348, "width": 29796, "x": 42434, "y": 26999}, "afRegion": {"height": 41216, "priority": 51833, "width": 0, "x": 30881, "y": 202}, "antiBandingMode": 166, "autoFocusMode": 3, "awbLockMode": false, "awbMode": 0, "brightness": -54, "captureIntent": 104, "chromaDenoise": 164, "cmdMask": 0, "contrast": 63, "controlMode": 101, "effectMode": 105, "enableHdr": false, "expCompensation": 115, "expManual": {"exposureTimeUs": 1869523456, "frameDurationUs": 1684372073, "sensitivityIso": 1818324338}, "frameSyncMode": 103, "lensPosAutoInfinity": 202, "lensPosAutoMacro": 68, "lensPosition": 0, "lensPositionRaw": 0.0, "lowPowerNumFramesBurst": 101, "lowPowerNumFramesDiscard": 1, "lumaDenoise": 158, "miscControls": [], "saturation": -41, "sceneMode": 0, "sharpness": 239, "strobeConfig": {"activeLevel": 116, "enable": 104, "gpioNumber": -51}, "strobeTimings": {"durationUs": 2593718595, "exposureBeginOffsetUs": 2019650982, "exposureEndOffsetUs": -898404282}, "wbColorTemp": 28793}, "isp3aFps": 0, "mockIspHeight": -1, "mockIspWidth": -1, "numFramesPoolIsp": 3, "numFramesPoolPreview": 4, "numFramesPoolRaw": 3, "numFramesPoolStill": 4, "numFramesPoolVideo": 4, "outputRequests": [{"enableUndistortion": null, "fps": {"value": null}, "resizeMode": 0, "size": {"value": {"index": 0, "value": [1280, 800]}}, "type": null}], "resolutionHeight": -1, "resolutionWidth": -1}}], [0, {"alias": "", "id": 0, "ioInfo": [[["dynamicOutputs", "0"], {"blocking": false, "group": "dynamicOutputs", "id": 3, "name": "0", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "raw"], {"blocking": false, "group": "", "id": 2, "name": "raw", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "mockIsp"], {"blocking": true, "group": "", "id": 1, "name": "mockIsp", "queueSize": 8, "type": 3, "waitForMessage": false}], [["", "inputControl"], {"blocking": true, "group": "", "id": 0, "name": "inputControl", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "Camera", "parentId": -1, "properties": {"boardSocket": 0, "cameraName": "", "fps": -1.0, "imageOrientation": -1, "initialControl": {"aeLockMode": false, "aeMaxExposureTimeUs": 0, "aeRegion": {"height": 0, "priority": 0, "width": 0, "x": 0, "y": 0}, "afRegion": {"height": 0, "priority": 0, "width": 0, "x": 0, "y": 0}, "antiBandingMode": 0, "autoFocusMode": 3, "awbLockMode": false, "awbMode": 0, "brightness": 0, "captureIntent": 0, "chromaDenoise": 0, "cmdMask": 0, "contrast": 0, "controlMode": 0, "effectMode": 0, "enableHdr": false, "expCompensation": 0, "expManual": {"exposureTimeUs": 0, "frameDurationUs": 0, "sensitivityIso": 0}, "frameSyncMode": 0, "lensPosAutoInfinity": 0, "lensPosAutoMacro": 0, "lensPosition": 0, "lensPositionRaw": 0.0, "lowPowerNumFramesBurst": 0, "lowPowerNumFramesDiscard": 0, "lumaDenoise": 0, "miscControls": [], "saturation": 0, "sceneMode": 0, "sharpness": 0, "strobeConfig": {"activeLevel": 0, "enable": 0, "gpioNumber": 0}, "strobeTimings": {"durationUs": 0, "exposureBeginOffsetUs": 0, "exposureEndOffsetUs": 0}, "wbColorTemp": 0}, "isp3aFps": 0, "mockIspHeight": -1, "mockIspWidth": -1, "numFramesPoolIsp": 3, "numFramesPoolPreview": 4, "numFramesPoolRaw": 3, "numFramesPoolStill": 4, "numFramesPoolVideo": 4, "outputRequests": [{"enableUndistortion": null, "fps": {"value": null}, "resizeMode": 0, "size": {"value": {"index": 0, "value": [4056, 3040]}}, "type": null}], "resolutionHeight": -1, "resolutionWidth": -1}}]]}}
```

## Source code

#### Python

```python
import depthai as dai
import time
import cv2

# Create pipeline
device = dai.Device()
pipeline = dai.Pipeline(device)

cameras = [
    pipeline.create(dai.node.Camera).build(socket)
    for socket in device.getConnectedCameras()
]
inputKeys = []
script = pipeline.create(dai.node.Script)

for i, camera in enumerate(cameras):
    inputName = str(i)
    camera.requestFullResolutionOutput().link(script.inputs[inputName])
    script.inputs[inputName].setBlocking(False)
    script.inputs[inputName].setMaxSize(1)
    inputKeys.append(inputName)

controlQueue = script.inputs["control"].createInputQueue()
preview = script.outputs["out"].createOutputQueue()

inputKeysSize = len(inputKeys)
script.setScript(
    f"""
    inputToStream = 0
    maxID = {inputKeysSize} - 1
    while True:
        controlMessage = node.inputs["control"].tryGet()
        if controlMessage is not None:
            if(inputToStream < maxID):
                inputToStream += 1
            else:
                inputToStream = 0
        frame = node.inputs[str(inputToStream)].get()
        node.outputs["out"].send(frame)
"""
)

pipeline.start()
print("To switch between streams, press 's'")
with pipeline:
    while pipeline.isRunning():
        previewMessage = preview.get()
        assert isinstance(previewMessage, dai.ImgFrame)
        cv2.imshow("preview", previewMessage.getCvFrame())
        key = cv2.waitKey(1)
        if key == ord("s"):
            controlQueue.send(dai.Buffer())
        if key == ord("q"):
            break
```

#### C++

```cpp
#include <atomic>
#include <csignal>
#include <iostream>
#include <memory>
#include <opencv2/opencv.hpp>
#include <vector>

#include "depthai/depthai.hpp"

// Global flag for graceful shutdown
std::atomic<bool> quitEvent(false);

// Signal handler
void signalHandler(int signum) {
    quitEvent = true;
}

int main() {
    // Set up signal handlers
    signal(SIGTERM, signalHandler);
    signal(SIGINT, signalHandler);

    try {
        // Create device and pipeline
        std::shared_ptr<dai::Device> device = std::make_shared<dai::Device>();
        dai::Pipeline pipeline(device);

        // Get connected cameras and create camera nodes
        std::vector<std::shared_ptr<dai::node::Camera>> cameras;
        std::vector<std::string> inputKeys;

        for(const auto& socket : device->getConnectedCameras()) {
            auto camera = pipeline.create<dai::node::Camera>();
            camera->build(socket);
            cameras.push_back(camera);
            inputKeys.push_back(std::to_string(cameras.size() - 1));
        }

        // Create script node
        auto script = pipeline.create<dai::node::Script>();

        // Link cameras to script inputs
        for(size_t i = 0; i < cameras.size(); i++) {
            std::string inputName = std::to_string(i);
            cameras[i]->requestFullResolutionOutput()->link(script->inputs[inputName]);
            script->inputs[inputName].setBlocking(false);
            script->inputs[inputName].setMaxSize(1);
        }

        // Create control and preview queues
        auto controlQueue = script->inputs["control"].createInputQueue();
        auto preview = script->outputs["out"].createOutputQueue();

        // Set the script content
        std::string scriptContent = R"(
            inputToStream = 0
            maxID = )" + std::to_string(inputKeys.size() - 1)
                                    + R"(
            while True:
                controlMessage = node.inputs["control"].tryGet()
                if controlMessage is not None:
                    if(inputToStream < maxID):
                        inputToStream += 1
                    else:
                        inputToStream = 0
                frame = node.inputs[str(inputToStream)].get()
                node.outputs["out"].send(frame)
        )";
        script->setScript(scriptContent);

        // Start pipeline
        pipeline.start();
        std::cout << "To switch between streams, press 's'" << std::endl;

        // Main loop
        while(pipeline.isRunning() && !quitEvent) {
            auto previewMessage = preview->get<dai::ImgFrame>();
            cv::Mat frame = previewMessage->getCvFrame();
            cv::imshow("preview", frame);

            int key = cv::waitKey(1);
            if(key == 's') {
                auto controlMessage = std::make_shared<dai::Buffer>();
                controlQueue->send(controlMessage);
            } else if(key == 'q') {
                break;
            }
        }

        // Cleanup
        pipeline.stop();
        pipeline.wait();

    } catch(const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
