Pythonic SCTE35
Project description
threefive is the highest rate SCTE-35 Tool. Ever.
Latest Version is 2.3.81
- Big thanks to NicoAdrian for repeatedly telling me the issue until I finally fixed it. Great name by the way. ~Adrian
Installation and Getting Started
Requirements
- threefive requires
- pypy3 or python 3.6+ (pypy3 runs threefive 2-3 times faster than python 3.10)
- new_reader
- pyaes
Versions and Releases
>>> import threefive
>>> threefive.version
'2.3.79'
>>>
- Release versions are odd.
- Unstable testing versions are even.
Parse SCTE-35 on the command line.
threefive 0xFC302F000000000000FFFFF014054800008F7FEFFE7369C02EFE0052CCF500000000000A0008435545490000013562DBA30A
cat video.ts | threefive
or like this
threefive https://so.slo.me/longb.ts
parse multicast like this
threefive udp://@235.35.3.5:3535
Parse SCTE-35 with three to five lines of code.
Mpegts Multicast in three lines of code.
import threefive
strm = threefive.Stream('udp://@239.35.0.35:1234')
strm.decode()
(need an easy multicast server? gumd )
Mpegts over Https in three lines of code.
import threefive
strm = threefive.Stream('https://iodisco.com/ch1/ready.ts')
strm.decode()
</details>
<details><summary>Base64 in five lines of code.</summary>
```python3
>>> from threefive import Cue
>>> stuff = '/DAvAAAAAAAA///wBQb+dGKQoAAZAhdDVUVJSAAAjn+fCAgAAAAALKChijUCAKnMZ1g='
>>> cue=Cue(stuff)
>>> cue.decode()
True
>>> cue.show()
Bytes in five lines of code.
>>> 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 in 4 lines of code.
import threefive
cue = threefive.Cue("0XFC301100000000000000FFFFFF0000004F253396")
cue.decode()
cue.show()
Easy SCTE-35 encoding with threefive.
-
Need SCTE-35 Packet Injection? SuperKabuki, powered by threefive.
-
Helper functions for SCTE35 Cue encoding
Python 3.8.13 (7.3.9+dfsg-5, Oct 30 2022, 09:55:31)
[PyPy 7.3.9 with GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>> import threefive.encode
>>>> help(threefive.encode)
Help on module threefive.encode in threefive:
NAME
threefive.encode - encode.py
DESCRIPTION
threefive.encode has helper functions for Cue encoding.
FUNCTIONS
mk_splice_insert(event_id, pts=None, duration=None, out=False)
mk_cue returns a Cue with a Splice Insert.
The args set the SpliceInsert vars.
splice_event_id = event_id
if pts is None (default):
splice_immediate_flag True
time_specified_flag False
if pts:
splice_immediate_flag False
time_specified_flag True
pts_time pts
If duration is None (default)
duration_flag False
if duration IS set:
out_of_network_indicator True
duration_flag True
break_auto_return True
break_duration duration
pts_time pts
if out is True:
out_of_network_indicator True
if out is False (default):
out_of_network_indicator False
mk_splice_null()
mk_splice_null returns a Cue
with a Splice Null
mk_time_signal(pts=None)
mk_time_signal returns a Cue
with a Time Signal
if pts is None:
time_specified_flag False
if pts IS set:
time_specified_flag True
pts_time pts
Cue Class
- src cue.py
- The threefive.Cue class decodes a SCTE35 binary, base64, or hex encoded string.
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
- 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'
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()
| 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.
-
threefive tries to include pid, program, anf pts of the SCTE-35 packet.
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
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()
| 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',encoding="utf-8") 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.proxy(func = show_cue)
-
Writes all packets to sys.stdout.
-
Writes scte35 data to sys.stderr.
-
| decode(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.proxy Example
import threefive
sp = threefive.Stream('https://futzu.com/xaa.ts')
sp.decode_proxy()
- Pipe to mplayer
$ python3 proxy.py | mplayer -
Stream.show()
| show(self)
| List programs and streams and info for MPEGTS
Stream.show() Example
>>>> from threefive import Stream
>>>> Stream('https://slo.me/plp0.ts').show()
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
Custom charsets for UPIDS aka upids.charset
Specify a charset for Upid data by setting threefive.upids.charset
issue #55
- default charset is ascii
- python charsets info Here
- setting charset to None will return raw bytes.
Example Usage:
>>> from threefive import Cue,upids
>>> i="/DBKAAAAAAAAAP/wBQb+YtC8/AA0AiZDVUVJAAAD6X/CAAD3W3ACEmJibG5kcHBobkQCAsGDpQIAAAAAAAEKQ1VFSRSAIyowMljRk9c="
>>> upids.charset
'ascii'
>>> cue=Cue(i)
>>> cue.decode()
ascii
True
>>> cue.descriptors[0].segmentation_upid
'bblndpphnD\x02\x02���\x02\x00\x00'
>>> upids.charset="utf16"
>>> cue.decode()
utf16
True
>>> cue.descriptors[0].segmentation_upid
'扢湬灤桰䑮Ȃ菁ʥ\x00'
Powered by threefive
-
x9k3: SCTE-35 HLS Segmenter and Cue Inserter.
-
m3ufu: SCTE-35 m3u8 Parser.
-
six2scte35: ffmpeg changes SCTE-35 stream type to 0x06 bin data, six2scte35 changes it back.
-
SuperKabuki: SCTE-35 Packet Injection.
other threefive stuff
-
Diagram of a threefive SCTE-35 Cue.
-
ffmpeg and threefive and SCTE35 and Stream Type 0x6 bin data.
-
Issues and Bugs and Feature Requests No forms man, just open an issue and tell me what you need.
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
Hashes for threefive-2.3.81-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a9d0b154218e2adaebffc40ea680adbbfdd78bf1e7b917f8a32d011c35cf559a |
|
MD5 | 384b5c056bd2a23f391329cba3e6112a |
|
BLAKE2b-256 | b4003b99fcf8ff15fab9a826cc8af571fc547320a0021b8d0b7135f39a23a8e1 |