Skip to main content

threefive is SCTE35 for the civilized

Project description

:rocket: threefive


threefive is a SCTE35 Decoder Encoder Parser library in Python3.

  • threefive references the 2020 SCTE35 Specification.

  • threefive decodes SCTE35 from MPEG-TS video files and streams.

  • threefive decodes SCTE35 from Base64, Hex, and Binary encoded strings.

  • threefive Encodes SCTE35 Cues.

  • threefive is Fast. threefive VS tsduck .

  • threefive Cyclomatic Complexity

  • threefive Performance Tuning the threefive.Stream class


Happy threefive users

Install threefive


Fast Start


Easy threefive


Advanced threefive


Examples


Cool Stuff


Install

  • dependencies

    • Python 3.6+ or pypy3 (pypy3 runs threefive three times faster than python3)
    • bitn
    • crcmod
    • urllib3
  • install from git

$ git clone https://github.com/futzu/SCTE35-threefive.git

$ cd SCTE-threefive
# you need root to install for the system
$ make install

# for pypy3 
$ make pypy3
  • install from pip
$ pip3 install threefive

# for pypy3
$ pypy3 -mpip install threefive

#If you don't have pip installed, try this.
$ pypy3 -mensurepip install pip 

🡡 top

Easy threefive

The decode Function

  • src decode.py

  • threefive.decode is an all purpose function to decode SCTE 35 messages from a file or string.

  • MpegTS

import threefive
threefive.decode('/path/to/mpegwithscte35.ts') 
  • New in v.2.2.69 threefive.decode can parse MpegTS over http and https
import threefive
threefive.decode('https://futzu.com/xaa.ts') 
  • Base64
mesg='/DA4AAAAAAAA///wBQb+AAAAAAAiAiBDVUVJAAAAA3//AAApPWwDDEFCQ0QwMTIzNDU2SBAAAGgCL9A='
threefive.decode(mesg)
  • Hex
hexed='0xFC302F000000000000FFFFF014054800008F7FEFFE7369C02EFE0052CCF500000000000A0008435545490000013562DBA30A'
threefive.decode(hexed)
  • Read a string directly from a file encoded in Base64, Binary or Base64
$ cat cue.dat
    /DCSAAAAAAAAAP/wBQb/RgeVUgB8AhdDVUVJbs6+VX+/CAgAAAAABy0IxzELGQIXQ1VFSW7MmIh/vwgIAAABGDayFhE3AQECHENVRUluzw0If/8AABvLoAgIAAAAAActVhIwDBkCKkNVRUluzw02f78MG1JUTE4xSAEAAAAAMTM3NjkyMDI1NDQ5NUgxAAEAAGnbuXg=
from threefive import decode

decode('cue.dat')

🡡 top

Happy threefive users

Advanced threefive


Cue Class

  • src cue.py
  • The threefive.Cue class decodes a SCTE35 binary, base64, or hex encoded string.
  • threefive.Cue provides several methods to access the parsed data.
from threefive import Cue

b64 = "/DBIAAAAAAAA///wBQb+ek2ItgAyAhdDVUVJSAAAGH+fCAgAAAAALMvDRBEAAAIXQ1VFSUgAABl/nwgIAAAAACyk26AQAACZcuND"

cue = Cue(b64)
cue.decode()


  • All instance vars can be accessed via dot notation.
>>>> from threefive import Cue
>>>> cue = Cue(b64)
>>>> cue.decode()
True
>>>> cue.command
{'command_length': 5, 'command_type': 6, 'name': 'Time Signal', 'time_specified_flag': True, 'pts_time': 22798.906911}
>>>> cue.command.pts_time
22798.906911
>>>> 
  • call one or more of these methods after decode.
Cue Method Description
cue.get() returns cue as a dict
cue.get_info_section() returns cue.info_section as a dict
cue.get_command() returns cue.command as a dict
cue.get_descriptors() returns cue.descriptors as a list of dicts.
cue.get_json() returns cue as a JSON string
cue.show() prints cue as JSON

  • Full Example
>>>> from threefive import Cue

>>>> b64 = "/DBIAAAAAAAA///wBQb+ek2ItgAyAhdDVUVJSAAAGH+fCAgAAAAALMvDRBEAAAIXQ1VFSUgAABl/nwgIAAAAACyk26AQAACZcuND"

>>>> cue.decode()
True
>>>> cue.show()
{
    "info_section": {
        "table_id": "0xfc",
        "section_syntax_indicator": false,
        "private": false,
        "sap_type": "0x3",
        "sap_details": "No Sap Type",
        "section_length": 72,
        "protocol_version": 0,
        "encrypted_packet": false,
        "encryption_algorithm": 0,
        "pts_adjustment": 0.0,
        "cw_index": "0xff",
        "tier": "0xfff",
        "splice_command_length": 5,
        "splice_command_type": 6,
        "descriptor_loop_length": 50
    },
    "command": {
        "command_length": 5,
        "command_type": 6,
        "name": "Time Signal",
        "time_specified_flag": true,
        "pts_time": 22798.906911
    },
    "descriptors": [
        {
            "tag": 2,
            "descriptor_length": 23,
            "identifier": "CUEI",
            "name": "Segmentation Descriptor",
            "segmentation_event_id": "0x48000018",
            "segmentation_event_cancel_indicator": false,
            "components": [],
            "program_segmentation_flag": true,
            "segmentation_duration_flag": false,
            "delivery_not_restricted_flag": false,
            "web_delivery_allowed_flag": true,
            "no_regional_blackout_flag": true,
            "archive_allowed_flag": true,
            "device_restrictions": "No Restrictions",
            "segmentation_message": "Program End",
            "segmentation_upid_type": 8,
            "segmentation_upid_length": 8,
            "segmentation_upid": "0x2ccbc344",
            "segmentation_type_id": 17,
            "segment_num": 0,
            "segments_expected": 0
        },
        {
            "tag": 2,
            "descriptor_length": 23,
            "identifier": "CUEI",
            "name": "Segmentation Descriptor",
            "segmentation_event_id": "0x48000019",
            "segmentation_event_cancel_indicator": false,
            "components": [],
            "program_segmentation_flag": true,
            "segmentation_duration_flag": false,
            "delivery_not_restricted_flag": false,
            "web_delivery_allowed_flag": true,
            "no_regional_blackout_flag": true,
            "archive_allowed_flag": true,
            "device_restrictions": "No Restrictions",
            "segmentation_message": "Program Start",
            "segmentation_upid_type": 8,
            "segmentation_upid_length": 8,
            "segmentation_upid": "0x2ca4dba0",
            "segmentation_type_id": 16,
            "segment_num": 0,
            "segments_expected": 0
        }
    ],
    "crc": "0x9972e343"
}

🡡 top


Stream Class

 threefive.Stream(tsdata, show_null = False)
  • src stream.py

  • The threefive.Stream class parses SCTE35 messages from a file or stream.

  • Supports

    • Multiple Programs.
    • Multiple SCTE35 Streams.
    • Multi-Packet PAT,PMT, and SCTE35 data.
  • tsdata is an open file handle.

  • show_null if set to True, enables showing SCTE 35 null commands.

Method Description
Stream.show() Prints all recognized Programs and streams by pid and type.
Stream.decode(func=show_cue) Prints SCTE-35 cues for SCTE-35 packets. Accepts an optional function, func, as arg.
Stream.decode_next() Returns the next SCTE35 cue as a threefive.Cue instance.
Stream.decode_program(the_program=None, func=show_cue) Same as Stream.decode except only packets where program == the_program
Stream.decode_proxy(func=show_cue) Same as Stream.decode except raw packets are written to stdout for piping to another program.

Stream.show()

  • List programs and streams for a video.
>>>> from threefive import Stream, version
>>>> version()
'2.2.69'
>>>> with open('video.ts','rb') as tsdata:
....     strm = Stream(tsdata)
....     strm.show()
....     


Program 1030

        PMT pid: 1030
        PCR pid: 1031
        Descriptor: tag: 5 length: 4 data: b'CUEI'
        1031: [0x1b] Video
        1032: [0x3] ISO/IEC 11172 Audio
        1034: [0x6] SO/IEC 13818-1 PES packets- private data
        1035: [0x86] SCTE 35

Program 1100

        PMT pid: 1100
        PCR pid: 1101
        Descriptor: tag: 5 length: 4 data: b'CUEI'
        1101: [0x1b] Video
        1102: [0x3] ISO/IEC 11172 Audio
        1104: [0x6] SO/IEC 13818-1 PES packets- private data
        1105: [0x86] SCTE 35

Program 1080

        PMT pid: 1080
        PCR pid: 1081
        1081: [0x1b] Video
        1082: [0x3] ISO/IEC 11172 Audio
        1084: [0x6] SO/IEC 13818-1 PES packets- private data

Program 1010

        PMT pid: 1010
        PCR pid: 1011
        Descriptor: tag: 5 length: 4 data: b'CUEI'
        1011: [0x1b] Video
        1012: [0x3] ISO/IEC 11172 Audio
        1014: [0x6] SO/IEC 13818-1 PES packets- private data
        1015: [0x86] SCTE 35

Program 1050

        PMT pid: 1050
        PCR pid: 1051
        Descriptor: tag: 5 length: 4 data: b'CUEI'
        1051: [0x1b] Video
        1052: [0x3] ISO/IEC 11172 Audio
        1054: [0x6] SO/IEC 13818-1 PES packets- private data
        1055: [0x86] SCTE 35

Stream.decode(func=show_cue)

import sys
from threefive import Stream

if __name__ =='__main__':
   with open(sys.argv[1],'rb') as tsdata:
       sp = Stream(tsdata)
       sp.decode()
  • Pass in custom function

  • func should match the interface func(cue)

import sys
import threefive

def display(cue):
   print(f'\033[92m{cue.packet_data}\033[00m')
   print(f'{cue.command.name}')

def do():
   with open(sys.argv[1],'rb') as tsdata:
    sp = threefive.Stream(tsdata)
    sp.decode(func = display)       

if __name__ == '__main__':
    do()

Stream.decode_next()

  • Stream.decode_next returns the next SCTE35 cue as a threefive.Cue instance.
import sys
import threefive

def do():
    arg = sys.argv[1]
    with open(arg,'rb') as tsdata:
        st = threefive.Stream(tsdata)
        while True:
            cue = st.decode_next()
            if not cue:
                return False
            if cue:
                cue.show()

if __name__ == "__main__":
    do()

Stream.decode_program(the_program, func = show_cue)

  • Use Stream.decode_program() instead of Stream.decode() to decode SCTE-35 from packets where program == the_program
import threefive

with open('../35.ts','rb') as tsdata:
    threefive.Stream(tsdata).decode_program(1)

Stream.decode_proxy(func = show_cue)

  • Writes all packets to sys.stdout.

  • Writes scte35 data to sys.stderr.

import threefive

with open('vid.ts','rb') as tsdata:
    sp = threefive.Stream(tsdata)
    sp.proxy_decode()
  • Pipe to mplayer
$ python3 proxy.py | mplayer -

Happy threefive users

🡡 top

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

threefive-2.2.79.tar.gz (25.3 kB view hashes)

Uploaded Source

Built Distribution

threefive-2.2.79-py3-none-any.whl (23.6 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page