threefive is SCTE35 for the civilized
Project description
:rocket: threefive
threefive is a SCTE35 Decoder,Editor, Encoder, and Parser library in Python3.
-
References the 2020 SCTE35 Specification.
-
Decode SCTE35 from MPEG-TS video files and streams, Base64, Hex, and Binary encoded strings.
-
threefive now Encodes SCTE35 Cues.
-
threefive Cyclomatic Complexity
-
Performance Tuning threefive.Stream
Install threefive
Fast Start
Easy threefive
- Parsing SCTE 35 Cues from Mpeg-TS Streams
- Parsing SCTE 35 Cues from Mpeg-TS Streams over HTTPS
- Parsing SCTE 35 Cue strings encoded in Base64, or Hex
- Parsing SCTE 35 Cues directly from a file encoded in Base64, Binary, or Hex
Advanced threefive
Examples
Cool Stuff
Install
-
dependencies
-
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
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')
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()
-
A decoded Cue instance contains:
-
cue.info_section
-
cue.command
-
cue.descriptors
-
a list of 0 or more of these descriptors :
-
-
crc
-
'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
-
-
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"
}
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 -
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.2.77-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 94b8a8e1c3f3c0f62a607c7cc0321d3bda0e21c787101f85e66f0754f4f4a9ff |
|
MD5 | 344095acef91ca48c51ac5b75ce8e6cc |
|
BLAKE2b-256 | 814759d2bba733e6376611e66d5fd0de3514d691c462ef22fd307458861c9995 |