Skip to main content

Pythonic SCTE35

Project description

x9k3 is an HLS segmenter with SCTE-35 support powered by threefive.

threefive is a SCTE-35 parser lib in python3.



Requirements

  • threefive requires pypy3 or python 3.6+
  • optional dependencies:
    • pyaes If you want AES decryption for HLS segments.

Install

python3 -mpip  install  threefive

# and / or

pypy3 -m pip install threefive
  • To install the optional dependencies.
python3 -mpip  install threefive[all]

# and / or

pypy3 -mpip  install  threefive[all]

Versions and Releases

Release versions are odd. Unstable testing versions are even.

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


Easy Examples

Base64
>>> from threefive import Cue
>>> stuff = '/DAvAAAAAAAA///wBQb+dGKQoAAZAhdDVUVJSAAAjn+fCAgAAAAALKChijUCAKnMZ1g='
>>> cue=Cue(stuff)
>>> cue.decode()
True
Bytes
>>> import threefive 

>>> stuff = b'\xfc0\x11\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00O%3\x96'
>>> cue=Cue(stuff)
>>> cue.decode()
True
>>> cue.show()
Hex
import threefive 

cue = threefive.Cue("0XFC301100000000000000FFFFFF0000004F253396")
cue.decode()
cue.show()

Mpegts Multicast

import threefive 

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


Cue Class

  • src cue.py
  • The threefive.Cue class decodes a SCTE35 binary, base64, or hex encoded string.
    >>>> 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 Cues from MPEGTS, threefive tries to include,
    • pid of the packet
    • program of the pid
    • pts of the packet
    • pcr of the packet

class Cue(threefive.base.SCTE35Base)
 |  Cue(data=None, packet_data=None)
 
 |  __init__(self, data=None, packet_data=None)
 |      data may be packet bites or encoded string
 |      packet_data is a instance passed from a Stream instance

Cue.decode()

 |  decode(self)
 |      Cue.decode() parses for SCTE35 data

Cue.get()

 |  get(self)
 |      Cue.get returns the SCTE-35 Cue
 |      data as a dict of dicts.

Cue.get() Example

>>> from threefive import Cue
>>> cue = Cue('0XFC301100000000000000FFFFFF0000004F253396')
>>> cue.decode()
True
>>> cue
{'bites': b'\xfc0\x11\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00O%3\x96', 
'info_section': {'table_id': '0xfc', 'section_syntax_indicator': False, 'private': False, 'sap_type': '0x3', 
'sap_details': 'No Sap Type', 'section_length': 17, 'protocol_version': 0, 'encrypted_packet': False, 
'encryption_algorithm': 0, 'pts_adjustment_ticks': 0, 'pts_adjustment': 0.0, 'cw_index': '0x0', 'tier': '0xfff',
'splice_command_length': 4095, 'splice_command_type': 0, 'descriptor_loop_length': 0, 'crc': '0x4f253396'},
'command': {'command_length': None, 'command_type': 0, 'name': 'Splice Null'},
'descriptors': [], 'packet_data': None}

### Cue.get() omits cue.bites and empty values

>>> cue.get()
{'info_section': {'table_id': '0xfc', 'section_syntax_indicator': False,'private': False, 'sap_type': '0x3', 
'sap_details': 'No Sap Type', 'section_length': 17, 'protocol_version': 0, 'encrypted_packet': False,
'encryption_algorithm': 0, 'pts_adjustment_ticks': 0, 'pts_adjustment': 0.0, 'cw_index': '0x0', 'tier': '0xfff',
'splice_command_length': 4095, 'splice_command_type': 0, 'descriptor_loop_length': 0, 'crc': '0x4f253396'},
'command': {'command_type': 0, 'name': 'Splice Null'},
'descriptors': []}
#### Cue.get_descriptors()
```js
 |  get_descriptors(self)
 |      Cue.get_descriptors returns a list of
 |      SCTE 35 splice descriptors as dicts.

Cue.get_json()

 |  get_json(self)
 |      Cue.get_json returns the Cue instance
 |      data in json.

Cue.show()

 |  show(self)
 |      Cue.show prints the Cue as JSON

Cue.to_stderr()

 |  to_stderr(self)
 |      Cue.to_stderr prints the Cue

Stream Class

  • src stream.py
  • The threefive.Stream class parses SCTE35 from Mpegts.
  • Supports:
    • File and Http(s) and Udp and Multicast protocols.
    • Multiple Programs.
    • Multi-Packet PAT, PMT, and SCTE35 tables.
class Stream(builtins.object)
 |  Stream(tsdata, show_null=True)
 |  
 |  Stream class for parsing MPEG-TS data.
|  __init__(self, tsdata, show_null=True)
|      
|      tsdata is a file or http, https, 
|       udp or multicast url.
|       
|      set show_null=False to exclude Splice Nulls
|      
|      Use like...
|      
|      from threefive import Stream
|      strm = Stream("vid.ts",show_null=False)
|      strm.decode()

Stream.decode(func=show_cue)

|  decode(self, func=show_cue)
|      Stream.decode reads self.tsdata to find SCTE35 packets.
|      func can be set to a custom function that accepts
|      a threefive.Cue instance as it's only argument.

Stream.decode Example

import sys
from threefive import Stream
>>>> Stream('plp0.ts').decode()
  • Pass in custom function

  • func should match the interface func(cue)

Stream.decode with custom function Example

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.
|  decode_next(self)
|      Stream.decode_next returns the next
|      SCTE35 cue as a threefive.Cue instance.

Stream.decode_next Example

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
|  decode_program(self, the_program, func=show_cue)
|      Stream.decode_program limits SCTE35 parsing
|      to a specific MPEGTS program.

Stream.decode_program Example

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.

|  decode_proxy(self, func=show_cue_stderr)
|      Stream.decode_proxy writes all ts packets are written to stdout
|      for piping into another program like mplayer.
|      SCTE-35 cues are printed to stderr.

Stream.decode_proxy Example

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

Stream.show()

  • List programs and streams and info for MPEGTS
|  show(self)
|      displays streams that will be
|      parsed for SCTE-35.

Stream.show() Example

>>>> 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_fu(func = show_cue)

|  decode_fu(self, func=show_cue)
|      Stream.decode_fu decodes
|      2016 packets at a time.

Stream.dump(fname)

|  dump(self, fname)
|      Stream.dump dumps all the packets to a file (fname).

Stream.strip_scte35(func=show_cue_stderr)

|  strip_scte35(self, func=show_cue_stderr)
|      Stream.strip_scte35 works just like Stream.decode_proxy,
|      MPEGTS packets, ( Except the SCTE-35 packets) ,
|      are written to stdout after being parsed.
|      SCTE-35 cues are printed to stderr.

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.27.tar.gz (30.0 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.27-py3-none-any.whl (30.4 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: threefive-2.3.27.tar.gz
  • Upload date:
  • Size: 30.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.27.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.9 CPython/3.10.4

File hashes

Hashes for threefive-2.3.27.tar.gz
Algorithm Hash digest
SHA256 d7336c9fa14f45b3a7756468c2e32a6b14d258ee80a393e525eb002b5ad7cbef
MD5 26c8c3912a7095fb2daf0d1ae373edaa
BLAKE2b-256 8e3bb3d79018e5c26f9722ad72712cea2b233e3bfbde58d0f8f13dd981e979e9

See more details on using hashes here.

File details

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

File metadata

  • Download URL: threefive-2.3.27-py3-none-any.whl
  • Upload date:
  • Size: 30.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.8.0 colorama/0.4.4 importlib-metadata/4.6.4 keyring/23.5.0 pkginfo/1.8.2 readme-renderer/34.0 requests-toolbelt/0.9.1 requests/2.27.1 rfc3986/1.5.0 tqdm/4.57.0 urllib3/1.26.9 CPython/3.10.4

File hashes

Hashes for threefive-2.3.27-py3-none-any.whl
Algorithm Hash digest
SHA256 b9992c20ec7c6f4e3353c4785fc4dca16b156b42102d99b55d2e75ecd0a30bb8
MD5 2387fc76873c5b472b4f8be48fa99d62
BLAKE2b-256 dcabdb08d02bd2a2fc1de7f2bdf92ef6d121541b59dac0ce5eee17a728594317

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