├── usage ├── rust │ ├── .gitignore │ ├── Cargo.toml │ ├── src │ │ └── main.rs │ └── Cargo.lock └── go │ └── definitions.go ├── README.md └── PROTOCOL.json /usage/rust/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /usage/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blackmagic-camera-protocol-example" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | serde = { version = "1.0", features = ["derive"] } 10 | serde_json = "1.0" -------------------------------------------------------------------------------- /usage/go/definitions.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | ) 8 | 9 | type BlackmagicCameraProtocol struct { 10 | Information struct { 11 | Readme string `json:"readme"` 12 | Source string `json:"source"` 13 | Git string `json:"git"` 14 | } `json:"information"` 15 | Groups []Group `json:"groups"` 16 | BluetoothServices []BluetoothService `json:"bluetooth_services"` 17 | } 18 | 19 | type Group struct { 20 | Name string `json:"name"` 21 | NormalizedName string `json:"normalized_name"` 22 | ID int `json:"id"` 23 | Parameters []Parameter `json:"parameters"` 24 | } 25 | 26 | type Parameter struct { 27 | ID int `json:"id"` 28 | Group string `json:"group"` 29 | GroupID int `json:"group_id"` 30 | Parameter string `json:"parameter"` 31 | Type string `json:"type"` 32 | Index []string `json:"index"` 33 | Minimum float32 `json:"minimum,omitempty"` 34 | Maximum float32 `json:"maximum,omitempty"` 35 | Interpretation string `json:"interpretation"` 36 | } 37 | 38 | type BluetoothService struct { 39 | Name string `json:"name"` 40 | NormalizedName string `json:"normalized_name"` 41 | UUID string `json:"uuid"` 42 | Characteristics []Characteristic `json:"characteristics"` 43 | } 44 | 45 | type Characteristic struct { 46 | Name string `json:"name"` 47 | NormalizedName string `json:"normalized_name"` 48 | UUID string `json:"uuid"` 49 | Description string `json:"description"` 50 | } 51 | 52 | func main() { 53 | definition, _ := ioutil.ReadFile("../../PROTOCOL.json") 54 | var decoded BlackmagicCameraProtocol 55 | 56 | err := json.Unmarshal(definition, &decoded) 57 | if err != nil { 58 | panic(err) 59 | } 60 | 61 | fmt.Println(decoded) 62 | } 63 | -------------------------------------------------------------------------------- /usage/rust/src/main.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use std::fs; 3 | 4 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 5 | #[serde(rename_all = "camelCase")] 6 | pub struct BlackmagicCameraProtocol { 7 | pub information: Information, 8 | pub groups: Vec, 9 | #[serde(rename = "bluetooth_services")] 10 | pub bluetooth_services: Vec, 11 | } 12 | 13 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 14 | #[serde(rename_all = "camelCase")] 15 | pub struct Information { 16 | pub readme: String, 17 | pub source: String, 18 | pub git: String, 19 | } 20 | 21 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 22 | #[serde(rename_all = "camelCase")] 23 | pub struct Group { 24 | pub name: String, 25 | #[serde(rename = "normalized_name")] 26 | pub normalized_name: String, 27 | pub id: i64, 28 | pub parameters: Vec, 29 | } 30 | 31 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 32 | #[serde(rename_all = "camelCase")] 33 | pub struct Parameter { 34 | pub id: i64, 35 | pub group: String, 36 | #[serde(rename = "group_id")] 37 | pub group_id: i64, 38 | pub parameter: String, 39 | #[serde(rename = "type")] 40 | pub type_field: String, 41 | pub index: Vec, 42 | pub interpretation: Option, 43 | pub minimum: Option, 44 | pub maximum: Option, 45 | } 46 | 47 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 48 | #[serde(rename_all = "camelCase")] 49 | pub struct BluetoothService { 50 | pub name: String, 51 | #[serde(rename = "normalized_name")] 52 | pub normalized_name: String, 53 | pub uuid: String, 54 | pub characteristics: Vec, 55 | } 56 | 57 | #[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)] 58 | #[serde(rename_all = "camelCase")] 59 | pub struct Characteristic { 60 | pub name: String, 61 | #[serde(rename = "normalized_name")] 62 | pub normalized_name: String, 63 | pub uuid: String, 64 | pub description: Option, 65 | pub decription: Option, 66 | } 67 | 68 | fn main() { 69 | let data = fs::read_to_string("../../PROTOCOL.json").unwrap(); 70 | let cfg: BlackmagicCameraProtocol = serde_json::from_str(&data).unwrap(); 71 | 72 | dbg!(cfg); 73 | } 74 | -------------------------------------------------------------------------------- /usage/rust/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "blackmagic-camera-protocol-example" 7 | version = "0.1.0" 8 | dependencies = [ 9 | "serde", 10 | "serde_json", 11 | ] 12 | 13 | [[package]] 14 | name = "itoa" 15 | version = "0.4.8" 16 | source = "registry+https://github.com/rust-lang/crates.io-index" 17 | checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" 18 | 19 | [[package]] 20 | name = "proc-macro2" 21 | version = "1.0.28" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" 24 | dependencies = [ 25 | "unicode-xid", 26 | ] 27 | 28 | [[package]] 29 | name = "quote" 30 | version = "1.0.9" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 33 | dependencies = [ 34 | "proc-macro2", 35 | ] 36 | 37 | [[package]] 38 | name = "ryu" 39 | version = "1.0.5" 40 | source = "registry+https://github.com/rust-lang/crates.io-index" 41 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 42 | 43 | [[package]] 44 | name = "serde" 45 | version = "1.0.128" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834" 48 | dependencies = [ 49 | "serde_derive", 50 | ] 51 | 52 | [[package]] 53 | name = "serde_derive" 54 | version = "1.0.128" 55 | source = "registry+https://github.com/rust-lang/crates.io-index" 56 | checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4" 57 | dependencies = [ 58 | "proc-macro2", 59 | "quote", 60 | "syn", 61 | ] 62 | 63 | [[package]] 64 | name = "serde_json" 65 | version = "1.0.66" 66 | source = "registry+https://github.com/rust-lang/crates.io-index" 67 | checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" 68 | dependencies = [ 69 | "itoa", 70 | "ryu", 71 | "serde", 72 | ] 73 | 74 | [[package]] 75 | name = "syn" 76 | version = "1.0.75" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" 79 | dependencies = [ 80 | "proc-macro2", 81 | "quote", 82 | "unicode-xid", 83 | ] 84 | 85 | [[package]] 86 | name = "unicode-xid" 87 | version = "0.2.2" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blackmagic Camera Control Protocol - Now in a machine-readable format 2 | 3 | The Blackmagic line of cameras are extremely powerful for the price. Especially considering their ability to be controlled both over SDI and Bluetooth, making this a very fun camera to use in situations where you need absolute control. 4 | 5 | This repo contains a machine-readable file called `PROTOCOL.json` which you can use to build your own application around the camera. It supplements the [Blackmagic Camera Control PDF](https://documents.blackmagicdesign.com/DeveloperManuals/BlackmagicCameraControl.pdf?_v=1539929000000). This should work for the Blackmagic Pocket Cinema Camera range, URSA range and Studio camera. 6 | 7 | `PROTOCOL.json` contains both the documentation of the parameters from both PDFs (camera protocol & pocket cameras) + information about the bluetooth services. The format of the data in the protocol is little endian. This is a small example of how the file is structured: 8 | 9 | ```json 10 | { 11 | "information": "", 12 | "groups": [ 13 | { 14 | "name": "Lens", 15 | "normalized_name": "lens", 16 | "id": 0, 17 | "parameters": [ 18 | { 19 | "id": 0, 20 | "group": "Lens", 21 | "group_id": 0, 22 | "parameter": "Focus", 23 | "type": "fixed16", 24 | "index": [], 25 | "minimum": 0, 26 | "maximum": 1, 27 | "interpretation": "0.0 = near, 1.0 = far" 28 | } 29 | ] 30 | } 31 | ], 32 | "bluetooth_services": [ 33 | { 34 | "name": "Blackmagic Camera Service", 35 | "normalized_name": "blackmagic_camera_service", 36 | "uuid": "291d567a-6d75-11e6-8b77-86f30ca893d3", 37 | "characteristics": [ 38 | { 39 | "name": "Outgoing Camera Control", 40 | "normalized_name": "outgoing_camera_control", 41 | "uuid": "5dd3465f-1aee-4299-8493-d2eca2f8e1bb", 42 | "description": "Send Camera Control messages" 43 | } 44 | ] 45 | } 46 | ] 47 | } 48 | ``` 49 | 50 | I also provided some demos of how to deserialize this file (CALL ME IF YOU GET LOST LUL). You can find them under `/usage`. For the Go demo, just `cd` to the folder and run `go run definitions.go`. For the Rust demo, `cd` to the folder and run `cargo run`. 51 | 52 | ## Prompt to Blackmagic Design 53 | 54 | The cameras Blackmagic makes are amazing, there is no doubt about it. The developer experience around them however aren't. While it probably sounded like a terrific idea on paper to just use the same protocol that works over SDI it feels like missing 20 years of progress in software engineering. Why should I have to manually decode some vendor specific protocol when we have tools such as [Protobuf](https://developers.google.com/protocol-buffers)? 55 | 56 | On top of that, the documentation provided for this protocol is "truly broadcast" in the sense that it's atrocious. Sure, plus points to the fact that it actually exists in the open in the first place compared to many other vendors but if you actually have the data that generated that table in the PDF, why not supplement this documentation with a machine-readable file? It doesn't have to be JSON, it could be XML for all I care but I just don't find it funny implementing this from a PDF. 57 | 58 | ## Contributing 59 | 60 | Submit a PR LUL 61 | -------------------------------------------------------------------------------- /PROTOCOL.json: -------------------------------------------------------------------------------- 1 | { 2 | "information": { 3 | "readme": "This serves as a machine-readable specification for the Blackmagic camera protocol. If any BM devs end up reading this, please provide something like this in the future, this isn't 1995 anymore ffs.", 4 | "source": "https://github.com/coral/blackmagic-camera-protocol", 5 | "git": "https://github.com/coral/blackmagic-camera-protocol.git" 6 | }, 7 | "groups": [ 8 | { 9 | "name": "Lens", 10 | "normalized_name": "lens", 11 | "id": 0, 12 | "parameters": [ 13 | { 14 | "id": 0, 15 | "group": "Lens", 16 | "group_id": 0, 17 | "parameter": "Focus", 18 | "normalized_parameter": "focus", 19 | "type": "fixed16", 20 | "index": [], 21 | "minimum": 0, 22 | "maximum": 1, 23 | "interpretation": "0.0 = near, 1.0 = far" 24 | }, 25 | { 26 | "id": 1, 27 | "group": "Lens", 28 | "group_id": 0, 29 | "parameter": "Instantaneous autofocus", 30 | "normalized_parameter": "instantaneous_autofocus", 31 | "type": "void", 32 | "index": [], 33 | "interpretation": "trigger instantaneous autofocus" 34 | }, 35 | { 36 | "id": 2, 37 | "group": "Lens", 38 | "group_id": 0, 39 | "parameter": "Aperture (f-stop)", 40 | "normalized_parameter": "aperture_f_stop", 41 | "type": "fixed16", 42 | "index": [], 43 | "minimum": -1, 44 | "maximum": 16, 45 | "interpretation": "Aperture Value (where fnumber\n= sqrt(2^AV))" 46 | }, 47 | { 48 | "id": 3, 49 | "group": "Lens", 50 | "group_id": 0, 51 | "parameter": "Aperture (normalised)", 52 | "normalized_parameter": "aperture_normalised", 53 | "type": "fixed16", 54 | "index": [], 55 | "minimum": 0, 56 | "maximum": 1, 57 | "interpretation": "0.0 = smallest, 1.0 = largest" 58 | }, 59 | { 60 | "id": 4, 61 | "group": "Lens", 62 | "group_id": 0, 63 | "parameter": "Aperture (ordinal)", 64 | "normalized_parameter": "aperture_ordinal", 65 | "type": "int16", 66 | "index": [], 67 | "minimum": 0, 68 | "maximum": 256, 69 | "interpretation": "Steps through available aperture values from minimum (0) to maximum (n)" 70 | }, 71 | { 72 | "id": 5, 73 | "group": "Lens", 74 | "group_id": 0, 75 | "parameter": "Instantaneous auto aperture", 76 | "normalized_parameter": "instantaneous_auto_aperture", 77 | "type": "void", 78 | "index": [], 79 | "interpretation": "trigger instantaneous auto aperture" 80 | }, 81 | { 82 | "id": 6, 83 | "group": "Lens", 84 | "group_id": 0, 85 | "parameter": "Optical image stabilisation", 86 | "normalized_parameter": "optical_image_stabilisation", 87 | "type": "boolean", 88 | "index": [], 89 | "interpretation": "true = enabled, false = disabled" 90 | }, 91 | { 92 | "id": 7, 93 | "group": "Lens", 94 | "group_id": 0, 95 | "parameter": "Set absolute zoom (mm)", 96 | "normalized_parameter": "set_absolute_zoom_mm", 97 | "type": "int16", 98 | "index": [], 99 | "minimum": 0, 100 | "maximum": 4000, 101 | "interpretation": "Move to specified focal length in mm, from minimum (0) to maximum (max)" 102 | }, 103 | { 104 | "id": 8, 105 | "group": "Lens", 106 | "group_id": 0, 107 | "parameter": "Set absolute zoom (normalised)", 108 | "normalized_parameter": "set_absolute_zoom_normalised", 109 | "type": "fixed16", 110 | "index": [], 111 | "minimum": 0, 112 | "maximum": 1, 113 | "interpretation": "Move to specified focal length:\n0.0 = wide, 1.0 = tele" 114 | }, 115 | { 116 | "id": 9, 117 | "group": "Lens", 118 | "group_id": 0, 119 | "parameter": "Set continuous zoom (speed)", 120 | "normalized_parameter": "set_continuous_zoom_speed", 121 | "type": "fixed16", 122 | "index": [], 123 | "minimum": -1, 124 | "maximum": 1, 125 | "interpretation": "Start/stop zooming at specified rate: -1.0 = zoom wider fast, 0.0\n= stop,\n+1 = zoom tele fast" 126 | } 127 | ] 128 | }, 129 | { 130 | "name": "Video", 131 | "normalized_name": "video", 132 | "id": 1, 133 | "parameters": [ 134 | { 135 | "id": 0, 136 | "group": "Video", 137 | "group_id": 1, 138 | "parameter": "Video mode", 139 | "normalized_parameter": "video_mode", 140 | "type": "int8", 141 | "index": [ 142 | "frame rate", 143 | "M-rate", 144 | "dimensions", 145 | "interlaced", 146 | "Color space" 147 | ], 148 | "interpretation": "0 = YUV" 149 | }, 150 | { 151 | "id": 1, 152 | "group": "Video", 153 | "group_id": 1, 154 | "parameter": "Gain (up to Camera 4.9)", 155 | "normalized_parameter": "gain_up_to_camera_4_9", 156 | "type": "int8", 157 | "index": [], 158 | "minimum": 1, 159 | "maximum": 128, 160 | "interpretation": "1x, 2x, 4x, 8x, 16x, 32x, 64x, 128x\ngain" 161 | }, 162 | { 163 | "id": 2, 164 | "group": "Video", 165 | "group_id": 1, 166 | "parameter": "Manual White Balance", 167 | "normalized_parameter": "manual_white_balance", 168 | "type": "int16", 169 | "index": ["color temp", "tint"], 170 | "minimum": -50, 171 | "maximum": 50, 172 | "interpretation": "tint" 173 | }, 174 | { 175 | "id": 3, 176 | "group": "Video", 177 | "group_id": 1, 178 | "parameter": "Set auto WB", 179 | "normalized_parameter": "set_auto_wb", 180 | "type": "void", 181 | "index": [], 182 | "interpretation": "Calculate and set auto white balance" 183 | }, 184 | { 185 | "id": 4, 186 | "group": "Video", 187 | "group_id": 1, 188 | "parameter": "Restore auto WB", 189 | "normalized_parameter": "restore_auto_wb", 190 | "type": "void", 191 | "index": [], 192 | "interpretation": "Use latest auto white balance setting" 193 | }, 194 | { 195 | "id": 5, 196 | "group": "Video", 197 | "group_id": 1, 198 | "parameter": "Exposure (us)", 199 | "normalized_parameter": "exposure_us", 200 | "type": "int32", 201 | "index": [], 202 | "minimum": 1, 203 | "maximum": 42000, 204 | "interpretation": "time in us" 205 | }, 206 | { 207 | "id": 6, 208 | "group": "Video", 209 | "group_id": 1, 210 | "parameter": "Exposure (ordinal)", 211 | "normalized_parameter": "exposure_ordinal", 212 | "type": "int16", 213 | "index": [], 214 | "minimum": 0, 215 | "maximum": null, 216 | "interpretation": "Steps through available exposure values from minimum\n(0) to maximum (n)" 217 | }, 218 | { 219 | "id": 7, 220 | "group": "Video", 221 | "group_id": 1, 222 | "parameter": "Dynamic Range Mode", 223 | "normalized_parameter": "dynamic_range_mode", 224 | "type": "int8", 225 | "index": [], 226 | "minimum": 0, 227 | "maximum": 2, 228 | "interpretation": "0 = film, 1 = video, 2 = extended video" 229 | }, 230 | { 231 | "id": 8, 232 | "group": "Video", 233 | "group_id": 1, 234 | "parameter": "Video sharpening level", 235 | "normalized_parameter": "video_sharpening_level", 236 | "type": "int8", 237 | "index": [], 238 | "minimum": 0, 239 | "maximum": 3, 240 | "interpretation": "0 = off, 1 = low, 2 = medium,\n3 = high" 241 | }, 242 | { 243 | "id": 9, 244 | "group": "Video", 245 | "group_id": 1, 246 | "parameter": "Recording format", 247 | "normalized_parameter": "recording_format", 248 | "type": "int16", 249 | "index": [ 250 | "file frame rate", 251 | "sensor frame rate", 252 | "frame width", 253 | "frame height", 254 | "flags" 255 | ], 256 | "interpretation": "[4] = windowed mode" 257 | }, 258 | { 259 | "id": 10, 260 | "group": "Video", 261 | "group_id": 1, 262 | "parameter": "Set auto exposure mode", 263 | "normalized_parameter": "set_auto_exposure_mode", 264 | "type": "int8", 265 | "index": [], 266 | "minimum": 0, 267 | "maximum": 4, 268 | "interpretation": "0 = Manual Trigger, 1 = Iris,\n2 = Shutter, 3 = Iris + Shutter, 4 = Shutter + Iris" 269 | }, 270 | { 271 | "id": 11, 272 | "group": "Video", 273 | "group_id": 1, 274 | "parameter": "Shutter angle", 275 | "normalized_parameter": "shutter_angle", 276 | "type": "int32", 277 | "index": [], 278 | "minimum": 100, 279 | "maximum": 36000, 280 | "interpretation": "Shutter angle in degrees, multiplied by 100" 281 | }, 282 | { 283 | "id": 12, 284 | "group": "Video", 285 | "group_id": 1, 286 | "parameter": "Shutter speed", 287 | "normalized_parameter": "shutter_speed", 288 | "type": "int32", 289 | "index": [], 290 | "minimum": 1, 291 | "maximum": 5000, 292 | "interpretation": "Shutter speed value as a fraction of 1, so 50 for 1/50th of a second" 293 | }, 294 | { 295 | "id": 13, 296 | "group": "Video", 297 | "group_id": 1, 298 | "parameter": "Gain", 299 | "normalized_parameter": "gain", 300 | "type": "int8", 301 | "index": [], 302 | "minimum": -128, 303 | "maximum": 127, 304 | "interpretation": "Gain in decibel (dB)" 305 | }, 306 | { 307 | "id": 14, 308 | "group": "Video", 309 | "group_id": 1, 310 | "parameter": "ISO", 311 | "normalized_parameter": "iso", 312 | "type": "int32", 313 | "index": [], 314 | "minimum": 0, 315 | "maximum": 2147483647, 316 | "interpretation": "ISO value" 317 | }, 318 | { 319 | "id": 15, 320 | "group": "Video", 321 | "group_id": 1, 322 | "parameter": "Display LUT", 323 | "normalized_parameter": "display_lut", 324 | "type": "int8", 325 | "index": ["selected LUT", "enabled or not"], 326 | "interpretation": "0 = Not enabled, 1 = Enabled" 327 | }, 328 | { 329 | "id": 16, 330 | "group": "Video", 331 | "group_id": 1, 332 | "parameter": "ND Filter", 333 | "normalized_parameter": "nd_filter", 334 | "type": "fixed16", 335 | "index": ["stops"], 336 | "minimum": 0, 337 | "maximum": 16, 338 | "interpretation": "f-stop of ND filter to use" 339 | } 340 | ] 341 | }, 342 | { 343 | "name": "Audio", 344 | "normalized_name": "audio", 345 | "id": 2, 346 | "parameters": [ 347 | { 348 | "id": 0, 349 | "group": "Audio", 350 | "group_id": 2, 351 | "parameter": "Mic level", 352 | "normalized_parameter": "mic_level", 353 | "type": "fixed16", 354 | "index": [], 355 | "minimum": 0, 356 | "maximum": 1, 357 | "interpretation": "0.0 = minimum, 1.0 = maximum" 358 | }, 359 | { 360 | "id": 1, 361 | "group": "Audio", 362 | "group_id": 2, 363 | "parameter": "Headphone level", 364 | "normalized_parameter": "headphone_level", 365 | "type": "fixed16", 366 | "index": [], 367 | "minimum": 0.1, 368 | "maximum": 1, 369 | "interpretation": "0.0 = minimum, 1.0 = maximum" 370 | }, 371 | { 372 | "id": 2, 373 | "group": "Audio", 374 | "group_id": 2, 375 | "parameter": "Headphone program mix", 376 | "normalized_parameter": "headphone_program_mix", 377 | "type": "fixed16", 378 | "index": [], 379 | "minimum": 0.1, 380 | "maximum": 1, 381 | "interpretation": "0.0 = minimum, 1.0 = maximum" 382 | }, 383 | { 384 | "id": 3, 385 | "group": "Audio", 386 | "group_id": 2, 387 | "parameter": "Speaker level", 388 | "normalized_parameter": "speaker_level", 389 | "type": "fixed16", 390 | "index": [], 391 | "minimum": 0.1, 392 | "maximum": 1, 393 | "interpretation": "0.0 = minimum, 1.0 = maximum" 394 | }, 395 | { 396 | "id": 4, 397 | "group": "Audio", 398 | "group_id": 2, 399 | "parameter": "Input type", 400 | "normalized_parameter": "input_type", 401 | "type": "int8", 402 | "index": [], 403 | "minimum": 0, 404 | "maximum": 3, 405 | "interpretation": "0 = internal mic,\n1 = line level input,\n2 = low mic level input, 3 = high mic level input" 406 | }, 407 | { 408 | "id": 5, 409 | "group": "Audio", 410 | "group_id": 2, 411 | "parameter": "Input levels", 412 | "normalized_parameter": "input_levels", 413 | "type": "fixed16", 414 | "index": ["ch0", "ch1"], 415 | "minimum": 0, 416 | "maximum": 1, 417 | "interpretation": "0.0 = minimum, 1.0 = maximum" 418 | }, 419 | { 420 | "id": 6, 421 | "group": "Audio", 422 | "group_id": 2, 423 | "parameter": "Phantom power", 424 | "normalized_parameter": "phantom_power", 425 | "type": "boolean", 426 | "index": [], 427 | "interpretation": "true = powered, false = not powered" 428 | } 429 | ] 430 | }, 431 | { 432 | "name": "Output", 433 | "normalized_name": "output", 434 | "id": 3, 435 | "parameters": [ 436 | { 437 | "id": 0, 438 | "group": "Output", 439 | "group_id": 3, 440 | "parameter": "Overlay enables", 441 | "normalized_parameter": "overlay_enables", 442 | "type": "uint16_bit_field", 443 | "index": [], 444 | "interpretation": "bit flags:\n[0] = display status,\n[1] = display frame guides\nSome cameras don't allow separate control of frame guides and status overlays." 445 | }, 446 | { 447 | "id": 1, 448 | "group": "Output", 449 | "group_id": 3, 450 | "parameter": "Frame guides style (Camera 3.x)", 451 | "normalized_parameter": "frame_guides_style_camera_3_x", 452 | "type": "int8", 453 | "index": [], 454 | "minimum": 0, 455 | "maximum": 8, 456 | "interpretation": "0 = HDTV, 1 = 4:3, 2 = 2.4:1,\n3 = 2.39:1, 4 = 2.35:1,\n5 = 1.85:1, 6 = thirds" 457 | }, 458 | { 459 | "id": 2, 460 | "group": "Output", 461 | "group_id": 3, 462 | "parameter": "Frame guides opacity (Camera 3.x)", 463 | "normalized_parameter": "frame_guides_opacity_camera_3_x", 464 | "type": "fixed16", 465 | "index": [], 466 | "minimum": 0.1, 467 | "maximum": 1, 468 | "interpretation": "0.0 = transparent, 1.0 = opaque" 469 | }, 470 | { 471 | "id": 3, 472 | "group": "Output", 473 | "group_id": 3, 474 | "parameter": "Overlays (replaces .1 and .2 above from Cameras 4.0)", 475 | "normalized_parameter": "overlays_replaces_1_and_2_above_from_cameras_4_0", 476 | "type": "int8", 477 | "index": [ 478 | "frame guides style", 479 | "frame guide opacity", 480 | "safe area percentage", 481 | "grid style" 482 | ], 483 | "interpretation": "bit flags:\n[0] = display thirds,\n[1] = display cross hairs,\n[2] = display center dot,\n[3] = display horizon", 484 | "minimum": 0, 485 | "maximum": 100 486 | } 487 | ] 488 | }, 489 | { 490 | "name": "Display", 491 | "normalized_name": "display", 492 | "id": 4, 493 | "parameters": [ 494 | { 495 | "id": 0, 496 | "group": "Display", 497 | "group_id": 4, 498 | "parameter": "Brightness", 499 | "normalized_parameter": "brightness", 500 | "type": "fixed16", 501 | "index": [], 502 | "minimum": 0, 503 | "maximum": 1, 504 | "interpretation": "0.0 = minimum, 1.0 = maximum" 505 | }, 506 | { 507 | "id": 1, 508 | "group": "Display", 509 | "group_id": 4, 510 | "parameter": "Exposure and focus tools", 511 | "normalized_parameter": "exposure_and_focus_tools", 512 | "type": "int16_bit_field", 513 | "index": [ 514 | "0x1 = zebra,\n0x2 = focus assist, 0x4 = false color" 515 | ], 516 | "interpretation": "0 = disable, 1 = enable" 517 | }, 518 | { 519 | "id": 2, 520 | "group": "Display", 521 | "group_id": 4, 522 | "parameter": "Zebra level", 523 | "normalized_parameter": "zebra_level", 524 | "type": "fixed16", 525 | "index": [], 526 | "minimum": 0, 527 | "maximum": 1, 528 | "interpretation": "0.0 = minimum, 1.0 = maximum" 529 | }, 530 | { 531 | "id": 3, 532 | "group": "Display", 533 | "group_id": 4, 534 | "parameter": "Peaking level", 535 | "normalized_parameter": "peaking_level", 536 | "type": "fixed16", 537 | "index": [], 538 | "minimum": 0, 539 | "maximum": 1, 540 | "interpretation": "0.0 = minimum, 1.0 = maximum" 541 | }, 542 | { 543 | "id": 4, 544 | "group": "Display", 545 | "group_id": 4, 546 | "parameter": "Color bar enable", 547 | "normalized_parameter": "color_bar_enable", 548 | "type": "int8", 549 | "index": [], 550 | "minimum": 0, 551 | "maximum": 30, 552 | "interpretation": "0 = disable bars,\n1-30 = enable bars with timeout (seconds)" 553 | }, 554 | { 555 | "id": 5, 556 | "group": "Display", 557 | "group_id": 4, 558 | "parameter": "Focus Assist", 559 | "normalized_parameter": "focus_assist", 560 | "type": "int8", 561 | "index": ["focus assist method", "focus line color"], 562 | "interpretation": "0 = Red,\n1 = Green,\n2 = Blue,\n3 = White,\n4 = Black" 563 | }, 564 | { 565 | "id": 6, 566 | "group": "Display", 567 | "group_id": 4, 568 | "parameter": "Program return feed enable", 569 | "normalized_parameter": "program_return_feed_enable", 570 | "type": "int8", 571 | "index": [], 572 | "minimum": 0, 573 | "maximum": 30, 574 | "interpretation": "0 = disable, 1-30 = enable with timeout (seconds)" 575 | } 576 | ] 577 | }, 578 | { 579 | "name": "Tally", 580 | "normalized_name": "tally", 581 | "id": 5, 582 | "parameters": [ 583 | { 584 | "id": 0, 585 | "group": "Tally", 586 | "group_id": 5, 587 | "parameter": "Tally brightness", 588 | "normalized_parameter": "tally_brightness", 589 | "type": "fixed16", 590 | "index": [], 591 | "minimum": 0, 592 | "maximum": 1, 593 | "interpretation": "Sets the tally front and tally rear brightness to the same level.\n0.0 = minimum,\n1.0 = maximum" 594 | }, 595 | { 596 | "id": 1, 597 | "group": "Tally", 598 | "group_id": 5, 599 | "parameter": "Front tally brightness", 600 | "normalized_parameter": "front_tally_brightness", 601 | "type": "fixed16", 602 | "index": [], 603 | "minimum": 0, 604 | "maximum": 1, 605 | "interpretation": "Sets the tally front brightness.\n0.0 = minimum,\n1.0 = maximum" 606 | }, 607 | { 608 | "id": 2, 609 | "group": "Tally", 610 | "group_id": 5, 611 | "parameter": "Rear tally brightness", 612 | "normalized_parameter": "rear_tally_brightness", 613 | "type": "fixed16", 614 | "index": [], 615 | "minimum": 0, 616 | "maximum": 1, 617 | "interpretation": "Sets the tally rear brightness.\n0.0 = minimum,\n1.0 = maximum\nTally rear brightness cannot be turned off" 618 | } 619 | ] 620 | }, 621 | { 622 | "name": "Reference", 623 | "normalized_name": "reference", 624 | "id": 6, 625 | "parameters": [ 626 | { 627 | "id": 0, 628 | "group": "Reference", 629 | "group_id": 6, 630 | "parameter": "Source", 631 | "normalized_parameter": "source", 632 | "type": "int8", 633 | "index": [], 634 | "minimum": 0, 635 | "maximum": 2, 636 | "interpretation": "0 = internal,\n1 = program,\n2 = external" 637 | }, 638 | { 639 | "id": 1, 640 | "group": "Reference", 641 | "group_id": 6, 642 | "parameter": "Offset", 643 | "normalized_parameter": "offset", 644 | "type": "int32", 645 | "index": [], 646 | "interpretation": "+/- offset in pixels" 647 | } 648 | ] 649 | }, 650 | { 651 | "name": "Configuration", 652 | "normalized_name": "configuration", 653 | "id": 7, 654 | "parameters": [ 655 | { 656 | "id": 0, 657 | "group": "Configuration", 658 | "group_id": 7, 659 | "parameter": "Real Time Clock", 660 | "normalized_parameter": "real_time_clock", 661 | "type": "int32", 662 | "index": ["time", "date"], 663 | "interpretation": "BCD - YYYYMMDD" 664 | }, 665 | { 666 | "id": 1, 667 | "group": "Configuration", 668 | "group_id": 7, 669 | "parameter": "System language", 670 | "normalized_parameter": "system_language", 671 | "type": "string", 672 | "index": ["[0-1]"], 673 | "interpretation": "ISO-639-1 two character language code" 674 | }, 675 | { 676 | "id": 2, 677 | "group": "Configuration", 678 | "group_id": 7, 679 | "parameter": "Timezone", 680 | "normalized_parameter": "timezone", 681 | "type": "int32", 682 | "index": [], 683 | "interpretation": "Minutes offset from UTC" 684 | }, 685 | { 686 | "id": 3, 687 | "group": "Configuration", 688 | "group_id": 7, 689 | "parameter": "Location", 690 | "normalized_parameter": "location", 691 | "type": "int64", 692 | "index": ["latitude", "longitude"], 693 | "interpretation": "BCD - sDDDdddddddddddd where s is the sign: 0 = west (-), 1 = east (+); DDD degrees, dddddddddddd decimal degrees" 694 | } 695 | ] 696 | }, 697 | { 698 | "name": "Color Correction", 699 | "normalized_name": "color_correction", 700 | "id": 8, 701 | "parameters": [ 702 | { 703 | "id": 0, 704 | "group": "Color Correction", 705 | "group_id": 8, 706 | "parameter": "Lift Adjust", 707 | "normalized_parameter": "lift_adjust", 708 | "type": "fixed16", 709 | "index": ["red", "green", "blue", "luma"], 710 | "minimum": -2, 711 | "maximum": 2, 712 | "interpretation": "default 0.0" 713 | }, 714 | { 715 | "id": 1, 716 | "group": "Color Correction", 717 | "group_id": 8, 718 | "parameter": "Gamma Adjust", 719 | "normalized_parameter": "gamma_adjust", 720 | "type": "fixed16", 721 | "index": ["red", "green", "blue", "luma"], 722 | "minimum": -4, 723 | "maximum": 4, 724 | "interpretation": "default 0.0" 725 | }, 726 | { 727 | "id": 2, 728 | "group": "Color Correction", 729 | "group_id": 8, 730 | "parameter": "Gain Adjust", 731 | "normalized_parameter": "gain_adjust", 732 | "type": "fixed16", 733 | "index": ["red", "green", "blue", "luma"], 734 | "minimum": 0, 735 | "maximum": 16, 736 | "interpretation": "default 1.0" 737 | }, 738 | { 739 | "id": 3, 740 | "group": "Color Correction", 741 | "group_id": 8, 742 | "parameter": "Offset Adjust", 743 | "normalized_parameter": "offset_adjust", 744 | "type": "fixed16", 745 | "index": ["red", "green", "blue", "luma"], 746 | "minimum": -8, 747 | "maximum": 8, 748 | "interpretation": "default 0.0" 749 | }, 750 | { 751 | "id": 4, 752 | "group": "Color Correction", 753 | "group_id": 8, 754 | "parameter": "Contrast Adjust", 755 | "normalized_parameter": "contrast_adjust", 756 | "type": "fixed16", 757 | "index": ["pivot", "adj"], 758 | "minimum": 0, 759 | "maximum": 2, 760 | "interpretation": "default 1.0" 761 | }, 762 | { 763 | "id": 5, 764 | "group": "Color Correction", 765 | "group_id": 8, 766 | "parameter": "Luma mix", 767 | "normalized_parameter": "luma_mix", 768 | "type": "fixed16", 769 | "index": [], 770 | "minimum": 0, 771 | "maximum": 1, 772 | "interpretation": "default 1.0" 773 | }, 774 | { 775 | "id": 6, 776 | "group": "Color Correction", 777 | "group_id": 8, 778 | "parameter": "Color Adjust", 779 | "normalized_parameter": "color_adjust", 780 | "type": "fixed16", 781 | "index": ["hue", "sat"], 782 | "minimum": 0, 783 | "maximum": 2, 784 | "interpretation": "default 1.0" 785 | }, 786 | { 787 | "id": 7, 788 | "group": "Color Correction", 789 | "group_id": 8, 790 | "parameter": "Correction Reset Default", 791 | "normalized_parameter": "correction_reset_default", 792 | "type": "void", 793 | "index": [], 794 | "interpretation": "reset to defaults" 795 | } 796 | ] 797 | }, 798 | { 799 | "name": "Media", 800 | "normalized_name": "media", 801 | "id": 10, 802 | "parameters": [ 803 | { 804 | "id": 0, 805 | "group": "Media", 806 | "group_id": 10, 807 | "parameter": "Codec", 808 | "normalized_parameter": "codec", 809 | "type": "int8", 810 | "index": ["basic codec", "code variant"], 811 | "interpretation": "Blackmagic RAW: 0 = Q0,\n1 = Q5,\n2 = 3:1,\n3 = 5:1,\n4 = 8:1,\n5 = 12:1" 812 | }, 813 | { 814 | "id": 1, 815 | "group": "Media", 816 | "group_id": 10, 817 | "parameter": "Transport mode", 818 | "normalized_parameter": "transport_mode", 819 | "type": "int8", 820 | "index": [ 821 | "mode", 822 | "speed", 823 | "flags", 824 | "slot 1 storage medium", 825 | "slot 2 storage medium" 826 | ], 827 | "interpretation": "0 = CFast card, 1 = SD Card,\n2 = SSD Recorder,\n3 = USB" 828 | }, 829 | { 830 | "id": 2, 831 | "group": "Media", 832 | "group_id": 10, 833 | "parameter": "Playback Control", 834 | "normalized_parameter": "playback_control", 835 | "type": "int8", 836 | "index": ["clip"], 837 | "interpretation": "0 = Previous,\n1 = Next" 838 | }, 839 | { 840 | "id": 3, 841 | "group": "Media", 842 | "group_id": 10, 843 | "parameter": "Still Capture", 844 | "normalized_parameter": "still_capture", 845 | "type": "void", 846 | "index": [], 847 | "interpretation": "Capture" 848 | } 849 | ] 850 | }, 851 | { 852 | "name": "PTZ Control", 853 | "normalized_name": "ptz_control", 854 | "id": 11, 855 | "parameters": [ 856 | { 857 | "id": 0, 858 | "group": "PTZ Control", 859 | "group_id": 11, 860 | "parameter": "Pan/Tilt Velocity", 861 | "normalized_parameter": "pan_tilt_velocity", 862 | "type": "fixed16", 863 | "index": ["pan velocity", "tilt velocity"], 864 | "minimum": -1, 865 | "maximum": 1, 866 | "interpretation": "-1.0 = full speed down,\n1.0 = full speed up" 867 | }, 868 | { 869 | "id": 1, 870 | "group": "PTZ Control", 871 | "group_id": 11, 872 | "parameter": "Memory Preset", 873 | "normalized_parameter": "memory_preset", 874 | "type": "int8", 875 | "index": ["preset command", "=\npreset slot"], 876 | "interpretation": "0 = reset,\n1 = store location, 2 = recall location", 877 | "minimum": 0, 878 | "maximum": 5 879 | } 880 | ] 881 | }, 882 | { 883 | "name": "Metadata", 884 | "normalized_name": "metadata", 885 | "id": 12, 886 | "parameters": [ 887 | { 888 | "id": 0, 889 | "group": "Metadata", 890 | "group_id": 12, 891 | "parameter": "Reel", 892 | "normalized_parameter": "reel", 893 | "type": "int16", 894 | "index": ["reel"], 895 | "minimum": 0, 896 | "maximum": 999 897 | }, 898 | { 899 | "id": 1, 900 | "group": "Metadata", 901 | "group_id": 12, 902 | "parameter": "Scene Tags", 903 | "normalized_parameter": "scene_tags", 904 | "type": "int8", 905 | "index": [ 906 | "scene tags", 907 | "interior / exterior", 908 | "day / night" 909 | ], 910 | "interpretation": "0 = Night\n1 = Day" 911 | }, 912 | { 913 | "id": 2, 914 | "group": "Metadata", 915 | "group_id": 12, 916 | "parameter": "Scene", 917 | "normalized_parameter": "scene", 918 | "type": "string", 919 | "index": ["[0-4] = scene"] 920 | }, 921 | { 922 | "id": 3, 923 | "group": "Metadata", 924 | "group_id": 12, 925 | "parameter": "Take", 926 | "normalized_parameter": "take", 927 | "type": "int8", 928 | "index": ["take number", "take tags"], 929 | "minimum": 1, 930 | "maximum": 99, 931 | "interpretation": "1 = None\n0 = PU\n1 = VFX\n2 = SER" 932 | }, 933 | { 934 | "id": 4, 935 | "group": "Metadata", 936 | "group_id": 12, 937 | "parameter": "Good Take", 938 | "normalized_parameter": "good_take", 939 | "type": "void", 940 | "index": ["good take"] 941 | }, 942 | { 943 | "id": 5, 944 | "group": "Metadata", 945 | "group_id": 12, 946 | "parameter": "Camera ID", 947 | "normalized_parameter": "camera_id", 948 | "type": "string", 949 | "index": ["[0-28] = ID"] 950 | }, 951 | { 952 | "id": 6, 953 | "group": "Metadata", 954 | "group_id": 12, 955 | "parameter": "Camera Operator", 956 | "normalized_parameter": "camera_operator", 957 | "type": "string", 958 | "index": ["[0-28] = operator"] 959 | }, 960 | { 961 | "id": 7, 962 | "group": "Metadata", 963 | "group_id": 12, 964 | "parameter": "Director", 965 | "normalized_parameter": "director", 966 | "type": "string", 967 | "index": ["[0-27] = director"] 968 | }, 969 | { 970 | "id": 8, 971 | "group": "Metadata", 972 | "group_id": 12, 973 | "parameter": "Project Name", 974 | "normalized_parameter": "project_name", 975 | "type": "string", 976 | "index": ["[0-28] = project"] 977 | }, 978 | { 979 | "id": 9, 980 | "group": "Metadata", 981 | "group_id": 12, 982 | "parameter": "Lens Type", 983 | "normalized_parameter": "lens_type", 984 | "type": "string", 985 | "index": ["[0-55] = type"] 986 | }, 987 | { 988 | "id": 10, 989 | "group": "Metadata", 990 | "group_id": 12, 991 | "parameter": "Lens Iris", 992 | "normalized_parameter": "lens_iris", 993 | "type": "string", 994 | "index": ["[0-19] = iris"] 995 | }, 996 | { 997 | "id": 11, 998 | "group": "Metadata", 999 | "group_id": 12, 1000 | "parameter": "Lens Focal Length", 1001 | "normalized_parameter": "lens_focal_length", 1002 | "type": "string", 1003 | "index": ["[0-29] = focal length"] 1004 | }, 1005 | { 1006 | "id": 12, 1007 | "group": "Metadata", 1008 | "group_id": 12, 1009 | "parameter": "Lens Distance", 1010 | "normalized_parameter": "lens_distance", 1011 | "type": "string", 1012 | "index": ["[0-49] = distance"] 1013 | }, 1014 | { 1015 | "id": 13, 1016 | "group": "Metadata", 1017 | "group_id": 12, 1018 | "parameter": "Lens Filter", 1019 | "normalized_parameter": "lens_filter", 1020 | "type": "string", 1021 | "index": ["[0-29] = filter"] 1022 | }, 1023 | { 1024 | "id": 14, 1025 | "group": "Metadata", 1026 | "group_id": 12, 1027 | "parameter": "Slate Mode", 1028 | "normalized_parameter": "slate_mode", 1029 | "type": "int8", 1030 | "index": ["type"], 1031 | "interpretation": "0 = Recording\n1 = Playback" 1032 | } 1033 | ] 1034 | } 1035 | ], 1036 | "bluetooth_services": [ 1037 | { 1038 | "name": "Device Information Service", 1039 | "normalized_name": "device_information_service", 1040 | "uuid": "0000180a-0000-1000-8000-00805f9b34fb", 1041 | "characteristics": [ 1042 | { 1043 | "name": "Camera Manufacturer", 1044 | "normalized_name": "camera_manufacturer", 1045 | "uuid": "00002a29-0000-1000-8000-00805f9b34fb", 1046 | "description": "Read the name of the manufacturer (always “Blackmagic Design”)" 1047 | }, 1048 | { 1049 | "name": "Camera Model", 1050 | "normalized_name": "camera_model", 1051 | "uuid": "00002a24-0000-1000-8000-00805f9b34fb", 1052 | "description": "Read the name of the camera model (eg. “URSA Mini Pro”)" 1053 | } 1054 | ] 1055 | }, 1056 | { 1057 | "name": "Blackmagic Camera Service", 1058 | "normalized_name": "blackmagic_camera_service", 1059 | "uuid": "291d567a-6d75-11e6-8b77-86f30ca893d3", 1060 | "characteristics": [ 1061 | { 1062 | "name": "Outgoing Camera Control", 1063 | "normalized_name": "outgoing_camera_control", 1064 | "uuid": "5dd3465f-1aee-4299-8493-d2eca2f8e1bb", 1065 | "description": "Send Camera Control messages" 1066 | }, 1067 | { 1068 | "name": "Incoming Camera Control", 1069 | "normalized_name": "incoming_camera_control", 1070 | "uuid": "b864e140-76a0-416a-bf30-5876504537d9", 1071 | "description": "Request notifications for this characteristic to receive Camera Control messages from the camera" 1072 | }, 1073 | { 1074 | "name": "Timecode", 1075 | "normalized_name": "timecode", 1076 | "uuid": "6d8f2110-86f1-41bf-9afb-451d87e976c8", 1077 | "description": "Timecode (HH:MM:SS:mm) is represented by a 32-bit BCD number: (eg. 09:12:53:10 = 0x09125310)" 1078 | }, 1079 | { 1080 | "name": "Camera Status", 1081 | "normalized_name": "camera_status", 1082 | "uuid": "7fe8691d-95dc-4fc5-8abd-ca74339b51b9", 1083 | "decription": "Request notifications for this characteristic to receive camera status updates.\n\nThe camera status is represented by flags contained in an 8-bit integer:\nNone = 0x00\nCamera Power On = 0x01\nConnected = 0x02\nPaired = 0x04\nVersions Verified = 0x08\nInitial Payload Received = 0x10\nCamera Ready = 0x20" 1084 | }, 1085 | { 1086 | "name": "Device Name", 1087 | "normalized_name": "device_name", 1088 | "uuid": "ffac0c52-c9fb-41a0-b063-cc76282eb89c", 1089 | "decription": "Send a device name to the camera (max. 32 characters). The camera will display this name in the Bluetooth Setup Menu" 1090 | }, 1091 | { 1092 | "name": "Protocol Version", 1093 | "normalized_name": "protocol_version", 1094 | "uuid": "8f1fd018-b508-456f-8f82-3d392bee2706", 1095 | "description": "Read this value to determine the camera’s supported CCU protocol version" 1096 | } 1097 | ] 1098 | } 1099 | ] 1100 | } 1101 | --------------------------------------------------------------------------------