Skip to content

VHS Processing ​

vhs-service contains two worker modules for an analogue-video workflow:

  1. vhs-decode turns an RF capture into time-base-corrected data and sidecars.
  2. tbc-decode turns those artifacts into a viewable video file.

Exactly one module runs in each process, selected by the command's positional service token.

Stage 1: RF capture to TBC ​

The vhs_decode job requires:

FieldMeaning
input_sourceRF capture URI, such as .ldf, .lds, .flac, .s16, or .u8.
output_sourceDestination for the decoded .tbc file.
sidecar_output_sourceDestination for the .tbc.json metadata sidecar.
chroma_output_sourceOptional _chroma.tbc destination for Y/C-separated formats.

The following vhs_decode parameters decode an NTSC VHS RF capture and write the TBC artifacts locally:

json
{
  "input_source": "rsync://capture@host/rf/tape.ldf",
  "output_source": "file:///work/tape.tbc",
  "sidecar_output_source": "file:///work/tape.tbc.json",
  "tape_format": "vhs",
  "video_system": "ntsc",
  "tape_speed": "SP"
}

Supported tape formats are vhs, svhs, umatic, umatic_hi, betamax, betamax_hifi, video8, hi8, and edit_betacam. Video systems are pal, pal-m, ntsc, ntsc-j, and mesecam; tape speeds are SP, LP, EP, ELP, and VP.

Optional controls cover sample frequency, threads, frame/sample ranges, level detection, sharpness, chroma filtering, dropout detection, clamping, and an advanced params file. The service-published JSON Schema is the authoritative field list.

Stage 2: TBC to video ​

The tbc_decode job requires:

FieldMeaning
input_source.tbc luma or combined capture.
sidecar_sourceMatching .tbc.json metadata.
output_sourceDestination video URI.

chroma_source is optional for composite captures and needed for Y/C-separated captures.

The following tbc_decode parameters convert the staged artifacts to an FFV1 video file:

json
{
  "input_source": "file:///work/tape.tbc",
  "sidecar_source": "file:///work/tape.tbc.json",
  "chroma_source": "file:///work/tape_chroma.tbc",
  "output_source": "s3://archive/tape.mkv",
  "profile": "ffv1",
  "pixel_format": "yuv422",
  "bit_depth": "10bit",
  "field_order": "tff"
}

Output controls include video system, chroma decoder, profile/container, pixel format, bit depth, field order, anamorphic mode, luma-only mode, two-step export, metadata export, audio tracks, hardware acceleration, and an advanced configuration file.

Key enums include:

  • chroma decoder: MONO, PAL2D, TRANSFORM2D, TRANSFORM3D, NTSC2D;
  • pixel format: gray, yuv420, yuv422, yuv444;
  • bit depth: 8bit, 10bit, 16bit;
  • field order: auto, tff, bff, prog.

Starting modules ​

Use serve, worker, or hybrid with one service token:

bash
vhs-service hybrid vhs-decode
vhs-service hybrid tbc-decode

The development tasks use separate containers:

bash
mise run dev:vhs-decode-service
mise run dev:tbc-service

Configuration lives under services.vhs-decode and services.tbc-decode in vhs-service/config.yaml. Each section has its own service ID, database, Kafka topic, consumer group, River limits, health interval, and gRPC address.

Resource planning ​

The default configuration runs one River worker per process with a 60-minute timeout. RF and TBC artifacts are large, so place worker staging storage on a volume with enough free space for inputs, sidecars, temporary output, and final output.

Released under the MIT License.