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.
-
Supports All 2020 SCTE-35 Commands and Descriptors and Upids.
-
Parses SCTE-35 from MPEGTS Streams with Direct Multicast Support .
-
HLS?Custom Upid Handling?Frame Accurate Preroll timings?... Yes. https://github.com/futzu/x9k3_ -
A threefive SCTE-35 Cue.What's included.
-
ffmpegandSCTE35andStream Type 0x6 bin dataand threefive
Encodingtoo withExamplesIssuesandBugsandFeature RequestsNo forms man, just open an issue and tell me what you need.
-
Diagram of a threefive SCTE-35 Cue
-
IssuesandBugsandFeatureRequests No forms man, just open an issue.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d7336c9fa14f45b3a7756468c2e32a6b14d258ee80a393e525eb002b5ad7cbef
|
|
| MD5 |
26c8c3912a7095fb2daf0d1ae373edaa
|
|
| BLAKE2b-256 |
8e3bb3d79018e5c26f9722ad72712cea2b233e3bfbde58d0f8f13dd981e979e9
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b9992c20ec7c6f4e3353c4785fc4dca16b156b42102d99b55d2e75ecd0a30bb8
|
|
| MD5 |
2387fc76873c5b472b4f8be48fa99d62
|
|
| BLAKE2b-256 |
dcabdb08d02bd2a2fc1de7f2bdf92ef6d121541b59dac0ce5eee17a728594317
|