Skip to main content

The World Wide Leader in SCTE35

Project description

threefive is SCTE-35 Parsing

Q. How many lines of code doe it take to parse SCTE35 from Mpegts?

A. Two.

from threefive import decode

decode("https://futzu.com/xaa.ts")


Requirements

  • threefive requires pypy3 or python 3.6+
    • (pypy3 runs threefive 4x Faster than python3 but uses a lot more memory)
  • threefive 2.3.02+ requires crcmod for encoding and pyaes for decrypting.

Install

pip3 install threefive

# for pypy3
pypy3 -m pip install threefive

Versions and Releases

Release versions are odd. Unstable testing versions are even.

threefive.version() returns the version as a string.

threefive.version_number() returns an int for easy version comparisons.


Easy threefive

the tsduck user's manual is longer than threefive's source code.

threefive.decode is a SCTE-35 decoder function with input type auto-detection. Base64, Binary, Hex Strings,Hex literals, Integers, Mpegts files and Mpegts HTTP/HTTPS Streams

SCTE-35 data can be parsed with just one function call.

SCTE-35 data is printed in JSON format.

Examples:

Base64
import threefive 

stuff = '/DAvAAAAAAAA///wBQb+dGKQoAAZAhdDVUVJSAAAjn+fCAgAAAAALKChijUCAKnMZ1g='
threefive.decode(stuff)
Bytes
import threefive 

payload = b'\xfc0\x11\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00O%3\x96'
threefive.decode(payload)
Hex String
import threefive 

stuff = '0XFC301100000000000000FFFFFF0000004F253396'
threefive.decode(stuff)
Hex Literal
import threefive 

threefive.decode(0XFC301100000000000000FFFFFF0000004F253396)
Integer
big_int = 1439737590925997869941740173214217318917816529814
threefive.decode(big_int)
Mpegts File
import threefive 

threefive.decode('/path/to/mpegts')
Mpegts HTTP/HTTPS Streams
import threefive 

threefive.decode('https://futzu.com/xaa.ts')

Mpegts UDP streams

import threefive 

threefive.decode('udp://10.0.0.1:555')

Mpegts Multicast

import threefive 

threefive.decode('udp://@239.35.0.35:1234')

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.
    >>>> import threefive
    >>>> Base64 = "/DAvAAAAAAAA///wBQb+dGKQoAAZAhdDVUVJSAAAjn+fCAgAAAAALKChijUCAKnMZ1g="
    >>>> cue = threefive.Cue(Base64)

cue.decode() returns True on success,or False if decoding failed

    >>>> cue.decode()
    True

After Calling cue.decode() the instance variables can be accessed via dot notation.

    >>>> cue.command
    {'calculated_length': 5, 'name': 'Time Signal', 'time_specified_flag': True, 'pts_time': 21695.740089}

    >>>> cue.command.pts_time
    21695.740089

    >>>> cue.info_section.table_id

    '0xfc'

When parsing SCTE35 Cues from MPEGTS streams, threefive attempts to include as many of the following as possible.'

  • pid of the packet
  • program of the pid
  • pts of the packet
  • pcr of the packet

  • call one or more of these methods after decode.
Cue Method Description
cue.get() returns cue as a dict
cue.get_json() returns cue as a JSON string
cue.show() prints cue as JSON

Stream Class

 threefive.Stream(tsdata, show_null = False)
  • src stream.py
  • The threefive.Stream class parses SCTE35 from Mpegts.
  • Supports:
    • File and Http(s) and Udp and Multicast protocols.
    • Multiple Programs.
    • Multiple SCTE35 Streams.
    • Multi-Packet PAT, PMT, and SCTE35 tables.
    • Constant Data Parsing.
      • threefive.Stream is designed to run continuously
Method Description
Stream.show() Prints Streams that will be checked for SCTE35
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 that will be checked for SCTE35 data.
>>>> from threefive import Stream
>>>> Stream('https://slo.me/plp0.ts').show()
Program: 1040
    Service:    fumatic
    Provider:   fu-labs
    Pcr Pid:    1041[0x411]
    Streams:
                Pid: 1041[0x411]        Type: 0x1b AVC Video
                Pid: 1042[0x412]        Type: 0x3 MP2 Audio
                Pid: 1044[0x414]        Type: 0x6 PES Packets/Private Data
                Pid: 1045[0x415]        Type: 0x86 SCTE35 Data

Program: 1050
    Service:    fancy ˹ 
    Provider:   fu-corp
    Pcr Pid:    1051[0x41b]
    Streams:
                Pid: 1051[0x41b]        Type: 0x1b AVC Video
                Pid: 1052[0x41c]        Type: 0x3 MP2 Audio
                Pid: 1054[0x41e]        Type: 0x6 PES Packets/Private Data
                Pid: 1055[0x41f]        Type: 0x86 SCTE35 Data

Stream.decode(func=show_cue)

import sys
from threefive import Stream
>>>> Stream('plp0.ts').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():
   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
threefive.Stream('35.ts').decode_program(1)

Stream.decode_proxy(func = show_cue)

  • Writes all packets to sys.stdout.

  • Writes scte35 data to sys.stderr.

import threefive
sp = threefive.Stream('https://futzu.com/xaa.ts')
sp.proxy_decode()
  • Pipe to mplayer
$ python3 proxy.py | mplayer -

Issues and Bugs and Feature Requests


Speak up. I want to hear what you have to say.

If threefive doesn't work as expected,

or if you find a bug ,

or if you have feature request,

please open an issue.


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.3.19.tar.gz (28.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

threefive-2.3.19-py3-none-any.whl (29.2 kB view details)

Uploaded Python 3

File details

Details for the file threefive-2.3.19.tar.gz.

File metadata

  • Download URL: threefive-2.3.19.tar.gz
  • Upload date:
  • Size: 28.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.10

File hashes

Hashes for threefive-2.3.19.tar.gz
Algorithm Hash digest
SHA256 6cece91f6371f3be4a294d0ab311f8a294b28778809b8db84ffccc9c1dac75e8
MD5 d6e4a3c200f68cfae4e3ac646c18f8b0
BLAKE2b-256 1b9549def09d42ff99e3d30d24e27048b33768368d5b7e90c97ae138992ed014

See more details on using hashes here.

File details

Details for the file threefive-2.3.19-py3-none-any.whl.

File metadata

  • Download URL: threefive-2.3.19-py3-none-any.whl
  • Upload date:
  • Size: 29.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/4.0.1 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.60.0 CPython/3.9.10

File hashes

Hashes for threefive-2.3.19-py3-none-any.whl
Algorithm Hash digest
SHA256 32415d0f5b0c3834890eade289a02dd3df8ad87b2ef725cceee6c04cac4b992a
MD5 02a40742e3e43c5afb50bacd05b4694a
BLAKE2b-256 7fddf6a30778a3bf9dce5bae1b6ed03e0dd9308bc57aeb663715847b01a319c6

See more details on using hashes here.

Supported by

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