156 lines
4.9 KiB
TypeScript
156 lines
4.9 KiB
TypeScript
import type { NodeTypeDef, ParamDef } from './types'
|
||
|
||
export const RESOLUTION_OPTIONS = [
|
||
{ label: '1280×720', value: '1280x720' },
|
||
{ label: '1920×1080', value: '1920x1080' },
|
||
{ label: '3840×2160', value: '3840x2160' },
|
||
]
|
||
|
||
export const FPS_OPTIONS = [
|
||
{ label: '23.98', value: '23.98' },
|
||
{ label: '24', value: '24' },
|
||
{ label: '25', value: '25' },
|
||
{ label: '29.97', value: '29.97' },
|
||
{ label: '30', value: '30' },
|
||
{ label: '50', value: '50' },
|
||
{ label: '59.94', value: '59.94' },
|
||
{ label: '60', value: '60' },
|
||
]
|
||
|
||
export const DEVICE_OPTIONS = [
|
||
{ label: 'DeckLink SDI (1)', value: 0 },
|
||
{ label: 'DeckLink SDI (2)', value: 1 },
|
||
{ label: 'DeckLink SDI (3)', value: 2 },
|
||
{ label: 'DeckLink SDI (4)', value: 3 },
|
||
]
|
||
|
||
export const PATTERN_OPTIONS = [
|
||
{ label: 'SMPTE bars 75%', value: 'bars' },
|
||
{ label: 'IRE bars', value: 'ire' },
|
||
{ label: 'Black solid', value: 'black' },
|
||
{ label: 'White solid', value: 'white' },
|
||
]
|
||
|
||
export const MIX_MODE_OPTIONS = [
|
||
{ label: 'Fade', value: 'fade' },
|
||
{ label: 'Dissolve', value: 'dissolve' },
|
||
{ label: 'Wipe', value: 'wipe' },
|
||
{ label: 'A/B', value: 'ab' },
|
||
]
|
||
|
||
export const TRANSITION_OPTIONS = [
|
||
{ label: 'Cut', value: 'cut' },
|
||
{ label: 'Cross', value: 'cross' },
|
||
{ label: 'Slide', value: 'slide' },
|
||
{ label: 'Push', value: 'push' },
|
||
]
|
||
|
||
// Format params shown on source nodes; values go into edge format (not node params)
|
||
const FORMAT_PARAMS: ParamDef[] = [
|
||
{ key: 'res', label: 'Resolution', type: 'select', options: RESOLUTION_OPTIONS, default: '1920x1080', isFormat: true },
|
||
{ key: 'fps', label: 'FPS', type: 'select', options: FPS_OPTIONS, default: '25', isFormat: true },
|
||
]
|
||
|
||
export const NODE_TYPES: Record<string, NodeTypeDef> = {
|
||
testpattern: {
|
||
type: 'testpattern',
|
||
label: 'Test Pattern',
|
||
ports: [
|
||
{ id: 'video-out', kind: 'video', direction: 'out' },
|
||
{ id: 'audio-out', kind: 'audio', direction: 'out' },
|
||
],
|
||
params: [
|
||
...FORMAT_PARAMS,
|
||
{ key: 'pattern', 'label': 'Pattern', type: 'select', options: PATTERN_OPTIONS, default: 'bars' },
|
||
{ key: 'channels', label: 'Channels', type: 'number', default: 0, min: 0, max: 16 }
|
||
],
|
||
},
|
||
ndiin: {
|
||
type: 'ndiin',
|
||
label: 'NDI In',
|
||
ports: [
|
||
{ id: 'video-out', kind: 'video', direction: 'out' },
|
||
{ id: 'audio-out', kind: 'audio', direction: 'out' },
|
||
],
|
||
params: [
|
||
{ key: 'source_num', label: 'NDI Source #', type: 'number', default: 0, min: 0, max: 15 },
|
||
...FORMAT_PARAMS,
|
||
],
|
||
},
|
||
decklinkin: {
|
||
type: 'decklinkin',
|
||
label: 'DeckLink In',
|
||
ports: [
|
||
{ id: 'video-out', kind: 'video', direction: 'out' },
|
||
{ id: 'audio-out', kind: 'audio', direction: 'out' },
|
||
],
|
||
params: [
|
||
{ key: 'device_index', label: 'Port', type: 'select', options: DEVICE_OPTIONS, default: 0 },
|
||
...FORMAT_PARAMS,
|
||
],
|
||
},
|
||
ndiout: {
|
||
type: 'ndiout',
|
||
label: 'NDI Out',
|
||
ports: [
|
||
{ id: 'video-in', kind: 'video', direction: 'in' },
|
||
{ id: 'audio-in', kind: 'audio', direction: 'in' },
|
||
],
|
||
params: [],
|
||
},
|
||
decklinkout: {
|
||
type: 'decklinkout',
|
||
label: 'DeckLink Out',
|
||
ports: [
|
||
{ id: 'video-in', kind: 'video', direction: 'in' },
|
||
{ id: 'audio-in', kind: 'audio', direction: 'in' },
|
||
],
|
||
params: [
|
||
{ key: 'device_index', label: 'Port', type: 'select', options: DEVICE_OPTIONS, default: 0 },
|
||
],
|
||
},
|
||
fakesink: {
|
||
type: 'fakesink',
|
||
label: 'Fake Sink',
|
||
ports: [
|
||
{ id: 'video-in', kind: 'video', direction: 'in' },
|
||
],
|
||
params: [],
|
||
},
|
||
videoin: {
|
||
type: 'videoin',
|
||
label: 'Multimedia file in',
|
||
ports: [
|
||
{ id: 'video-out', kind: 'video', direction: 'out' },
|
||
{ id: 'audio-out', kind: 'audio', direction: 'out' },
|
||
],
|
||
params: [
|
||
{ key: 'file', label: 'File', type: 'input', default: '0.ts' }
|
||
],
|
||
},
|
||
mix: {
|
||
type: 'mix',
|
||
label: 'Mix',
|
||
ports: [
|
||
{ id: 'video-in-1', kind: 'video', direction: 'in' },
|
||
{ id: 'video-in-2', kind: 'video', direction: 'in' },
|
||
{ id: 'audio-in-1', kind: 'audio', direction: 'in' },
|
||
{ id: 'audio-in-2', kind: 'audio', direction: 'in' },
|
||
{ id: 'video-out', kind: 'video', direction: 'out' },
|
||
{ id: 'audio-out', kind: 'audio', direction: 'out' },
|
||
],
|
||
params: [
|
||
{ key: 'mode', label: 'Mode', type: 'select', options: MIX_MODE_OPTIONS, default: 'fade' },
|
||
{ key: 'transition', label: 'Transition', type: 'select', options: TRANSITION_OPTIONS, default: 'cut' },
|
||
{ key: 'duration', label: 'Duration', type: 'number', default: 500, min: 0, max: 10000 },
|
||
],
|
||
},
|
||
}
|
||
|
||
// Default params for a new node of the given type
|
||
export function defaultParams(nodeType: string): Record<string, string | number> {
|
||
const def = NODE_TYPES[nodeType]
|
||
if (!def) return {}
|
||
return Object.fromEntries(def.params.map(p => [p.key, p.default]))
|
||
}
|