Skip to content

keithah/threefive.js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

threefive.js

JavaScript/TypeScript port of Python threefive — a SCTE-35 decoder for broadcast ad markers.

Decode-only. Synchronous. ESM. No dependencies.

import { Cue } from 'threefive-scte35';

const cue = new Cue('/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=');

cue.command.name          // 'Splice Insert'
cue.command.ptsTime       // 21514.559089  (seconds)
cue.command.breakDuration // 60.293567     (seconds)
cue.descriptors[0].name   // 'Avail Descriptor'

Install

npm install threefive-scte35

Or reference a local clone:

"threefive-scte35": "^0.1.1"

Usage

From base64

import { Cue } from 'threefive-scte35';

const cue = new Cue('/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=');

From hex

const cue = new Cue('0xFC302F000000000000FFFFF014054800008F7FEFFE7369C02EFE0052CCF5...');

From bytes

const cue = new Cue(new Uint8Array([0xfc, 0x30, ...]));

Inspect results

// Info section
cue.infoSection.tableId           // '0xfc'
cue.infoSection.spliceCommandType // 5
cue.infoSection.ptsAdjustment     // 0
cue.infoSection.crc               // '0x62dba30a'

// Splice command
cue.command.name          // 'Splice Insert'
cue.command.commandType   // 5
cue.command.ptsTime       // seconds (null if not specified)
cue.command.breakDuration // seconds (null if not a timed break)

// Descriptors
cue.descriptors           // SpliceDescriptor[]

Serialize to plain object

const obj = cue.get();
// {
//   info_section: { table_id: '0xfc', splice_command_type: 5, ... },
//   command: { name: 'Splice Insert', pts_time: 21514.559089, break_duration: 60.293567, ... },
//   descriptors: [{ name: 'Avail Descriptor', provider_avail_id: 309 }]
// }

API

new Cue(data?)

Argument Type
data string | Uint8Array | undefined

String inputs: hex (0xfc30... or fc30...) or base64. Uint8Array is passed directly. Passing nothing creates an empty instance.

The constructor calls decode() automatically.


cue.infoSectionSpliceInfoSection

Property Type Notes
tableId string | null Always '0xfc'
sectionLength number | null
protocolVersion number | null
encryptedPacket boolean | null
ptsAdjustment number Seconds (90kHz converted)
spliceCommandType number | null
spliceCommandLength number | null
descriptorLoopLength number
crc string | null Stored, not verified

cue.command — splice command instances

Class commandType Key fields
SpliceNull 0
SpliceInsert 5 spliceEventId, ptsTime, breakDuration, breakAutoReturn, outOfNetworkIndicator, uniqueProgramId, availNum, availsExpected
TimeSignal 6 ptsTime, timeSpecifiedFlag
BandwidthReservation 7
PrivateCommand 255 identifier, privateBytes

ptsTime and breakDuration are in seconds (already divided by 90000). null when not present.


cue.descriptorsSpliceDescriptor[]

Class tag Key fields
AvailDescriptor 0 providerAvailId
DtmfDescriptor 1 preroll, dtmfCount, dtmfChars
SegmentationDescriptor 2 segmentationEventId, segmentationTypeId, segmentationMessage, segmentationDuration, segmentationUpid, segmentNum, segmentsExpected
TimeDescriptor 3 taiSeconds, taiNs, utcOffset
PrivateDescriptor any other privateData

SegmentationDescriptor segmentation types (table 22)

Common values:

segmentationTypeId segmentationMessage
0x10 Program Start
0x11 Program End
0x20 Chapter Start
0x21 Chapter End
0x22 Break Start
0x23 Break End
0x30 Provider Advertisement Start
0x31 Provider Advertisement End
0x34 Provider Placement Opportunity Start
0x35 Provider Placement Opportunity End
0x36 Distributor Placement Opportunity Start
0x37 Distributor Placement Opportunity End

Full table in src/segmentation.ts.

UPID types

segmentationUpid is a UpidResult:

{
  upidType: 8,
  upidTypeName: 'AiringID',
  upidLength: 8,
  upidValue: '0x2ca0a18a'
}

Supported: No UPID, AdID, UMID, ISAN, TID, AiringID, ADI, EIDR, ATSC, MPU, MID, ADS Info, URI, UUID, SCR.


Named exports

import {
  Cue,
  SpliceInfoSection,
  SpliceNull, SpliceInsert, TimeSignal, BandwidthReservation, PrivateCommand,
  AvailDescriptor, DtmfDescriptor, SegmentationDescriptor, TimeDescriptor,
  PrivateDescriptor, spliceDescriptor,
  Bitn,
  table20, table22, SUB_SEG_TYPES,
  decodeUpid,
} from 'threefive-scte35';

Design notes

  • Decode-only. No encoding, no XML, no CRC generation.
  • Synchronous. new Cue(data) returns immediately — no async init.
  • BigInt bit reader. Bitn stores the input as one BigInt and slices bits without alignment constraints, matching Python's arbitrary-precision integer approach.
  • Seconds throughout. ptsTime and breakDuration are divided by 90000 at parse time. No raw ticks exposed.
  • ESM only. Targets ES2020 with "type": "module".

Relationship to Python threefive

This is a port of the decode path from superkabuki/threefive_is_scte35. Field names and class structure follow the Python library closely so output is comparable. The test suite cross-checks all parsed values against Python cue.show() output.

Not ported: encoding, XML output, CRC computation, HLS/DASH playlist parsing, network fetching.


License

MIT

About

JavaScript/TypeScript port of the Python threefive SCTE-35 decoder

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors