#!/usr/bin/env node 'use strict'; /** * ltc-reader — decode SMPTE LTC from an audio feed and push it to ProdDash. * * ProPresenter's APIs expose no timecode (see modules/propresenter-timers), * so this tool reads LTC where it actually lives: the audio signal. Pipe * PCM (signed 16-bit little-endian) into stdin from any capture front-end; * the decoded state is POSTed to the Timers module's /ltc ingest route — * ~4×/s while running, 1×/s as a keepalive otherwise, and immediately on * every state change. * * macOS (ffmpeg; list input devices with * `ffmpeg -f avfoundation -list_devices true -i ""`): * ffmpeg -loglevel error -f avfoundation -i ":0" -ac 1 -ar 48000 \ * -f s16le - | node tools/ltc-reader.js --url http://127.0.0.1:24500 * sox (default input device): * sox -q -d -t raw -b 16 -e signed -c 1 -r 48000 - | node tools/ltc-reader.js * Windows (ffmpeg/dshow): * ffmpeg -loglevel error -f dshow -i audio="" -ac 1 \ * -ar 48000 -f s16le - | node tools/ltc-reader.js * * LTC on one input of a multichannel interface (a console bus, a Dante/ * MADI card, input 5 of a Scarlett 18i20…): do NOT downmix with -ac 1 — * summing LTC with program audio corrupts the bit transitions. Capture the * channels as they are and tell the reader which one carries LTC (1-based): * ffmpeg -loglevel error -f avfoundation -i ":0" -ar 48000 -f s16le - \ * | node tools/ltc-reader.js --channels 18 --ch 5 * (--channels must match what the capture actually emits; ffmpeg keeps * the device's native count unless -ac says otherwise, and prints it on * stderr at startup. sox: match its -c flag.) * * Flags: * --url ProdDash base URL (default http://127.0.0.1:24500) * --module target module id (default propresenter-timers) * --token matches the module's "LTC reader token" admin setting * --sr stdin sample rate (default 48000) * --channels interleaved channels in the stdin stream (default 1) * --ch which channel carries LTC, 1-based (default 1) * --source