Skip to content

sensslen/Cgf.CameraControl.Main

Repository files navigation

Cgf.CameraControl.Main

TypeScript application that uses a Gamepad to control a Video mixer and multiple cameras.

Quick start

To start using this project use the following steps:

  • install node.js
  • clone the repository (git clone https://github.com/sensslen/Cgf.CameraControl.Main.git)
  • install dependencies by calling npm install
  • edit Cli/src/config.json to match your setup or just create a new configuration and run the application with the config parameter.
  • compile the app : npm run build
  • run the application using npm start (which runs node Cli/dist/index.js) or pass a custom config via node Cli/dist/index.js --config path/to/my/config.json

Configuration

Configuration of the application is stored as a JSON file. There is a default configuration (Cli/src/config.json) which is loaded when the config parameter is omitted when starting the application. Additionally, the application may be started with a custom configuration that may be located anywhere on the file system.

The configuration file has three main sections: cams (camera connections), videoMixers (video mixer connections), and interfaces (controller/gamepad configurations).

Complete Configuration Example

{
    "cams": [
        {
            "instance": 1,
            "type": "websocket/ptzlanc",
            "ip": "192.168.1.100",
            "panTiltInvert": false,
            "showTallyLight": true
        },
        {
            "instance": 2,
            "type": "signalr/ptzlanc",
            "connectionUrl": "http://192.168.1.101:5000",
            "connectionPort": "COM6",
            "panTiltInvert": false
        },
        {
            "instance": 3,
            "type": "viscaoverip",
            "ip": "192.168.1.102",
            "port": 52381,
            "panTiltInvert": false
        }
    ],
    "videoMixers": [
        {
            "instance": 1,
            "type": "blackmagicdesign/atem",
            "ip": "192.168.1.240",
            "mixEffectBlock": 0
        }
    ],
    "interfaces": [
        {
            "instance": 1,
            "type": "logitech/gamepadf310",
            "serialNumber": "optional-serial-number",
            "videoMixer": 1,
            "enableChangingProgram": true,
            "connectionChange": {
                "type": "direct",
                "default": {
                    "up": 1,
                    "right": 2,
                    "down": 3,
                    "left": 4
                },
                "alt": {
                    "up": 5,
                    "right": 6,
                    "down": 7,
                    "left": 8
                },
                "altLower": {
                    "up": 9,
                    "right": 10,
                    "down": 11,
                    "left": 12
                }
            },
            "specialFunction": {
                "default": {
                    "down": {
                        "type": "key",
                        "index": 1
                    },
                    "up": {
                        "type": "macroToggle",
                        "indexOn": 23,
                        "indexOff": 24,
                        "condition": {
                            "type": "key",
                            "key": 0
                        }
                    },
                    "left": {
                        "type": "macroLoop",
                        "indexes": [1, 2, 3]
                    }
                }
            },
            "cameraMap": {
                "1": 1,
                "2": 2,
                "3": 3,
                "4": 4
            }
        }
    ]
}

Camera Connections

The cams array defines the camera connections that the application can control. Each camera has:

  • instance: Unique numeric identifier for the camera
  • type: Type of camera connection. Supported types:
    • "websocket/ptzlanc": WebSocket-based PTZ LANC camera control
    • "signalr/ptzlanc": SignalR-based PTZ LANC camera control
    • "viscaoverip": VISCA over IP camera control

For detailed module documentation, see:

WebSocket PTZ LANC Camera

{
    "instance": 1,
    "type": "websocket/ptzlanc",
    "ip": "192.168.1.100",
    "panTiltInvert": false,
    "showTallyLight": true
}
  • ip: IP address of the camera controller
  • panTiltInvert: (Optional, default: false) Invert pan/tilt controls
  • showTallyLight: (Optional, default: true) Enable tally light on camera

SignalR PTZ LANC Camera

{
    "instance": 2,
    "type": "signalr/ptzlanc",
    "connectionUrl": "http://192.168.1.101:5000",
    "connectionPort": "COM6",
    "panTiltInvert": false
}
  • connectionUrl: URL of the SignalR camera controller
  • connectionPort: Serial port identifier
  • panTiltInvert: (Optional, default: false) Invert pan/tilt controls

VISCA over IP Camera (untested)

{
    "instance": 3,
    "type": "viscaoverip",
    "ip": "192.168.1.102",
    "port": 52381,
    "panTiltInvert": false
}
  • ip: IP address of the camera
  • port: (Optional, default: 52381) UDP port of the camera
  • panTiltInvert: (Optional, default: false) Invert pan/tilt controls

Video Mixer Connections

The videoMixers array defines the video mixer connections. Multiple video mixers can be configured.

{
    "instance": 1,
    "type": "blackmagicdesign/atem",
    "ip": "192.168.1.240",
    "mixEffectBlock": 0
}
  • instance: Unique numeric identifier for the video mixer
  • type: Type of video mixer. Currently supported: "blackmagicdesign/atem"
  • ip: IP address of the ATEM switcher
  • mixEffectBlock: Zero-based ME block index to control (0-3 depending on ATEM model)

Gamepads/Controllers (Interfaces)

The interfaces array defines the gamepad/controller configurations. Each gamepad connects to exactly one video mixer and controls the cameras mapped to it.

{
    "instance": 1,
    "type": "logitech/gamepadf310",
    "serialNumber": "optional-serial-number",
    "videoMixer": 1,
    "enableChangingProgram": true,
    "connectionChange": { /* ... */ },
    "specialFunction": { /* ... */ },
    "cameraMap": { /* ... */ }
}

Basic Configuration

  • instance: Unique numeric identifier for the interface
  • type: Type of gamepad. Supported types:
    • "logitech/gamepadf310": Logitech F310 gamepad
    • "logitech/rumblepad2": Logitech Rumblepad 2
  • serialNumber: (Optional) Serial number to identify specific gamepad
  • videoMixer: Instance number of the video mixer this interface controls
  • enableChangingProgram: (Optional, default: true) Allow this controller to cut/switch program output

Camera Map

The cameraMap maps ATEM input numbers to camera instance numbers:

"cameraMap": {
    "1": 1,  // ATEM input 1 -> camera instance 1
    "2": 2,  // ATEM input 2 -> camera instance 2
    "3": 3,  // ATEM input 3 -> camera instance 3
    "4": 4   // ATEM input 4 -> camera instance 4
}

Connection Change Configuration

Defines how the D-pad buttons change camera selection. Two types are supported:

Direct Mode: Maps each D-pad direction to a specific camera instance

"connectionChange": {
    "type": "direct",
    "default": {
        "up": 1,
        "right": 2,
        "down": 3,
        "left": 4
    },
    "alt": {  // Optional: used when "alt" modifier is held
        "up": 5,
        "right": 6,
        "down": 7,
        "left": 8
    },
    "altLower": {  // Optional: used when "altLower" modifier is held
        "up": 9,
        "right": 10,
        "down": 11,
        "left": 12
    }
}

Directional Mode: Allows navigation between cameras in a directional manner

"connectionChange": {
    "type": "directional",
    "directions": {
        "1": {  // From camera instance 1
            "right": 2,
            "down": 3
        },
        "2": {  // From camera instance 2
            "left": 1,
            "down": 4
        }
    }
}

Special Functions

Maps gamepad buttons (A, B, X, Y) to special functions. Available in default, alt, and altLower contexts.

Button directions: "up" (Y), "down" (A), "left" (X), "right" (B)

Key Toggle: Toggle an ATEM upstream key

{
    "type": "key",
    "index": 1  // Key index (1-based)
}

Macro Loop: Cycle through a series of macros

{
    "type": "macroLoop",
    "indexes": [1, 2, 3]  // Array of macro indexes to cycle through
}

Macro Toggle: Toggle between two macros based on a condition

{
    "type": "macroToggle",
    "indexOn": 23,   // Macro to run when condition is false
    "indexOff": 24,  // Macro to run when condition is true
    "condition": {
        "type": "key",  // Check if a key is active
        "key": 0        // Key index to check
    }
}
{
    "type": "macroToggle",
    "indexOn": 20,
    "indexOff": 21,
    "condition": {
        "type": "aux_selection",  // Check AUX output selection
        "aux": 5,                 // AUX output index
        "selection": 16           // Expected source selection
    }
}

Connection Change: Trigger camera selection change via button

{
    "type": "connectionChange"
}

Keyboard Interface

A lightweight interface that reacts to the keyboard and supports only a subset of the gamepad functionality:

  • Arrow keys pan/tilt the currently selected (preview) camera.
  • Number keys 1–9 select the mixer input (and therefore the camera) of the same number.
  • Enter and Space optionally perform a mixer cut or auto transition (see transitionKeys below).

It is added to the interfaces array just like a gamepad:

{
    "instance": 2,
    "type": "keyboard",
    "videoMixer": 1,
    "cameraMap": {
        "1": 1,
        "2": 2,
        "3": 3
    },
    "moveSpeed": 1,
    "stopDelayMs": 250,
    "transitionKeys": {
        "enter": "cut",
        "space": "auto"
    }
}
  • instance: Unique numeric identifier for the interface
  • type: Must be "keyboard"
  • videoMixer: Instance number of the video mixer this interface controls
  • cameraMap: Maps mixer input numbers (the number key pressed) to camera instance numbers
  • moveSpeed: (Optional, default: 1) Pan/tilt speed in the range ]0 .. 1] while an arrow key is held
  • stopDelayMs: (Optional, default: 250) Time in milliseconds after the last arrow key event before movement is stopped. Because the terminal only reports key presses (there is no key-release event), movement is kept alive by the operating system's key repeat. This value must be larger than the key repeat interval so that holding an arrow key results in continuous movement.
  • transitionKeys: (Optional) Binds the Enter and Space keys to a mixer transition. Each of enter/space may be set to "cut" (immediate cut) or "auto" (transitioned cut), or omitted to leave that key unassigned.

Note: The keyboard interface reads from the terminal (standard input), so the application must be started in an interactive terminal (a TTY). Press Ctrl+C to quit.

About

Core Library of the Camera Control Software initially developped for usage at Chrischona Frauenfeld

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors