# Video record

This example demonstrates how to record a video stream and showcases how to use the
[RecordVideo](https://docs.luxonis.com/software-v3/depthai/depthai-components/host_nodes/record_video.md) node for capturing and
saving frames.

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

## Pipeline

### examples/record_video.pipeline.json

```json
{"pipeline": {"connections": [{"node1Id": 1, "node1Output": "out", "node1OutputGroup": "", "node2Id": 3, "node2Input": "in", "node2InputGroup": ""}, {"node1Id": 0, "node1Output": "0", "node1OutputGroup": "dynamicOutputs", "node2Id": 1, "node2Input": "in", "node2InputGroup": ""}], "globalProperties": {"calibData": null, "cameraTuningBlobSize": null, "cameraTuningBlobUri": "", "leonCssFrequencyHz": 700000000.0, "leonMssFrequencyHz": 700000000.0, "pipelineName": null, "pipelineVersion": null, "sippBufferSize": 18432, "sippDmaBufferSize": 16384, "xlinkChunkSize": -1}, "nodes": [[3, {"alias": "", "id": 3, "ioInfo": [[["", "in"], {"blocking": true, "group": "", "id": 7, "name": "in", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "XLinkOut", "parentId": -1, "properties": {"maxFpsLimit": -1.0, "metadataOnly": false, "streamName": "__x_1__out"}}], [1, {"alias": "", "id": 1, "ioInfo": [[["", "out"], {"blocking": false, "group": "", "id": 6, "name": "out", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "bitstream"], {"blocking": false, "group": "", "id": 5, "name": "bitstream", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "in"], {"blocking": true, "group": "", "id": 4, "name": "in", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "VideoEncoder", "parentId": -1, "properties": {"bitrate": 0, "frameRate": 30.0, "keyframeFrequency": 30, "lossless": false, "maxBitrate": 0, "numBFrames": 0, "numFramesPool": 0, "outputFrameSize": 0, "profile": 2, "quality": 80, "rateCtrlMode": 0}}], [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": [1280, 720]}}, "type": 22}], "resolutionHeight": -1, "resolutionWidth": -1}}]]}}
```

## Source code

#### Python

```python
import depthai as dai
import argparse
import time
import signal
from pathlib import Path

parser = argparse.ArgumentParser()
parser.add_argument("-o", "--output", default="test_video", help="Output file name (without extension)")

args = parser.parse_args()

with dai.Pipeline() as pipeline:
    def signal_handler(sig, frame):
        print("Interrupted, stopping the pipeline")
        pipeline.stop()
    signal.signal(signal.SIGINT, signal_handler)

    cam = pipeline.create(dai.node.Camera).build(dai.CameraBoardSocket.CAM_A)

    videoEncoder = pipeline.create(dai.node.VideoEncoder).build(cam.requestOutput((1280, 720), dai.ImgFrame.Type.NV12))
    videoEncoder.setProfile(dai.VideoEncoderProperties.Profile.H264_MAIN)

    record = pipeline.create(dai.node.RecordVideo)
    record.setRecordVideoFile(Path(f"{args.output}.mp4"))

    videoEncoder.out.link(record.input)

    pipeline.start()
    print("Recording video. Press Ctrl+C to stop.")
    while pipeline.isRunning():
        time.sleep(1)
```

#### C++

```cpp
#include <atomic>
#include <chrono>
#include <csignal>
#include <filesystem>
#include <iostream>
#include <memory>
#include <thread>

#include "depthai/depthai.hpp"

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

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

int main(int argc, char** argv) {
    // Parse command line arguments
    std::string outputFile = "test_video";
    for(int i = 1; i < argc; i++) {
        std::string arg = argv[i];
        if(arg == "-o" || arg == "--output") {
            if(i + 1 < argc) {
                outputFile = argv[++i];
            }
        }
    }

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

    try {
        // Create pipeline
        dai::Pipeline pipeline;

        // Create color camera node
        auto cam = pipeline.create<dai::node::Camera>()->build(dai::CameraBoardSocket::CAM_A);

        // Create video encoder node
        auto videoEncoder = pipeline.create<dai::node::VideoEncoder>();
        videoEncoder->setProfile(dai::VideoEncoderProperties::Profile::H264_MAIN);
        cam->requestOutput(std::make_pair(1280, 720), dai::ImgFrame::Type::NV12)->link(videoEncoder->input);

        // Create record node
        auto record = pipeline.create<dai::node::RecordVideo>();
        record->setRecordVideoFile(std::filesystem::path(outputFile + ".mp4"));
        videoEncoder->out.link(record->input);

        // Start pipeline
        pipeline.start();
        std::cout << "Recording video. Press Ctrl+C to stop." << std::endl;

        // Main loop
        while(pipeline.isRunning() && !quitEvent) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }

        // 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.
