Skip to main content

threefive is The #1 SCTE-35 tool on the Planet. Death to those who oppose me.

Project description

Install |SCTE-35 Cli | SCTE-35 HLS | Cue Class | Stream Class | Online SCTE-35 Parser | Encode SCTE-35 | SCTE-35 Examples | SCTE-35 XML and More XML | SuperKabuki SCTE-35 MPEGTS Packet Injection | SCTE-35 As a Service image

v3.0.57 is the latest

  • threefive installs.
    • today: 350
    • last seven days: 2,288
    • last thirty days: 10,491
    • last five years: 1,029,995

threefive

  • Decodes SCTE-35 in TEN formats: MPEGTS, Base64, Bytes, Dicts, Hex,HLS, Integers,JSON,XML and XML+Binary.
  • Encodes SCTE-35 in EIGHT formats: MPEGTS, Base64, Bytes, Hex, Int, JSON,XML, and Xml+binary.
  • Supports All HLS SCTE-35 Tags.
  • Does Automatic AES decryption for MPEGTS and HLS.
  • Has Built-in Multicast Sender and Receiver.
  • Injects SCTE-35 Packets into MPEGTS video.

The SuperKabuki SCTE-35 MPEGTS Packet Injection Engine

Sassy, the new SCTE-35 as a service, Decode SCTE-35 in your browser

Super Cool SCTE-35 Examples

New XML stuff in threefive


Documentation

Install

Quick Start

  • Here's how to decode these SCTE-35 formats with threefive.
  • This covers both the Cli tool and library.
MPEGTS * MPEGTS streams can be Files, Http(s), Multicast, UDP Unicast, or stdin.
  • cli
threefive https://example.com/video.ts
  • wildcards work too.
threefive /mpegts/*.ts
  • lib
from threefive import Stream
stream = Stream('https://example.com/video.ts')
stream.decode()

Base64
  • cli
threefive '/DAsAAAAAyiYAP/wCgUAAAABf1+ZmQEBABECD0NVRUkAAAAAf4ABADUAAC2XQZU='
  • lib
from threefive import Cue
data = '/DAsAAAAAyiYAP/wCgUAAAABf1+ZmQEBABECD0NVRUkAAAAAf4ABADUAAC2XQZU='
cue=Cue(data)
cue.show()

Bytes
  • cli

    • Bytes don't work on the cli
  • lib

from threefive import Cue
data =  b'\xfc0\x16\x00\x00\x00\x00\x00\x00\x00\xff\xf0\x05\x06\xfe\x00\xc0D\xa0\x00\x00\x00\xb5k\x88'
cue=Cue(data)
cue.show()

Hex
  • Can be a hex literal or hex string or bytes.

  • cli

threefive  0xfc301600000000000000fff00506fed605225b0000b0b65f3b
  • lib
from threefive import Cue
data =  0xfc301600000000000000fff00506fed605225b0000b0b65f3b
cue=Cue(data)
cue.show()

Int
  • Can be a literal integer or string or bytes.

  • cli

threefive  1583008701074197245727019716796221243043855984942057168199483b
  • lib
from threefive import Cue
data =  1583008701074197245727019716796221243043855984942057168199483
cue=Cue(data)
cue.show()

JSON
  • cli
    • put JSON SCTE-35 in a file and redirect it into threefive
threefive  < json.json
  • lib
 from threefive import Cue
 data = '''{
    "info_section": {
        "table_id": "0xfc",
        "section_syntax_indicator": false,
        "private": false,
        "sap_type": "0x03",
        "sap_details": "No Sap Type",
        "section_length": 22,
        "protocol_version": 0,
        "encrypted_packet": false,
        "encryption_algorithm": 0,
        "pts_adjustment": 0.0,
        "cw_index": "0x00",
        "tier": "0x0fff",
        "splice_command_length": 5,
        "splice_command_type": 6,
        "descriptor_loop_length": 0,
        "crc": "0xb56b88"
    },
    "command": {
        "command_length": 5,
        "command_type": 6,
        "name": "Time Signal",
        "time_specified_flag": true,
        "pts_time": 140.005333
    },
    "descriptors": []
}
'''
cue=Cue(data)
cue.show()

Xml
  • cli
    • put xml SCTE-35 in a file and redirect it into threefive
     threefive < xmlbin.xml
    
  • lib
from threefive import Cue
data =  '''
<scte35:SpliceInfoSection xmlns:scte35="https://scte.org/schemas/35" 
        ptsAdjustment="0" protocolVersion="0" sapType="3" tier="4095">
   <scte35:TimeSignal>
      <scte35:SpliceTime ptsTime="12600480"/>
   </scte35:TimeSignal>
</scte35:SpliceInfoSection>
'''
cue=Cue(data)

cue.show()

Xml+binary
  • cli
    • write xml+binary to a file and redirect it to threefive
threefive < xmlbin.xml
  • lib
from threefive import Cue
data = '''<scte35:Signal xmlns:scte35="https://scte.org/schemas/35">
    <scte35:Binary>/DAWAAAAAAAAAP/wBQb+AMBEoAAAALVriA==</scte35:Binary>
</scte35:Signal>
'''
cue=Cue(data)
cue.show()

Examples

XML

  • XML New! updated 05/01/2025

Cli

  • SCTE-35 Cli Super Tool Encodes, Decodes, and Recodes. This is pretty cool, it does SCTE-35 seven different ways.
    • The cli tool comes with builtin documentation just type threefive help

HLS

MPEGTS Packet Injection

SCTE-35 As a Service

  • Decode SCTE-35 without installing anything. If you can make an https request, you can use Sassy to decode SCTE-35. .

Classes

  • The python built in help is always the most up to date docs for the library.
a@fu:~/build7/threefive$ pypy3

>>>> from threefive import Stream
>>>> help(Stream)

| more


Install

  • python3 via pip
python3 -mpip install threefive
  • pypy3
pypy3 -mpip install threefive
  • from the git repo
git clone https://github.com/superkabuki/scte35.git
cd threefive
make install

Using the library

  • Let me show you how easy threefive is to use.
  • well start off reading SCTE-35 xml from a file
a@fu:~/threefive$ pypy3
Python 3.9.16 (7.3.11+dfsg-2+deb12u3, Dec 30 2024, 22:36:23)
[PyPy 7.3.11 with GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>> from threefive import reader
>>>> from threefive import Cue
>>>> data =reader('/home/a/xml.xml').read()
* load it into a threefive.Cue instance
```py3
>>>> cue = Cue(data)
  • Show the data as JSON
>>>> cue.show()
{
    "info_section": {
        "table_id": "0xfc",
        "section_syntax_indicator": false,
        "private": false,
        "sap_type": "0x03",
        "sap_details": "No Sap Type",
        "section_length": 92,
        "protocol_version": 0,
        "encrypted_packet": false,
        "encryption_algorithm": 0,
        "pts_adjustment": 0.0,
        "cw_index": "0x00",
        "tier": "0x0fff",
        "splice_command_length": 15,
        "splice_command_type": 5,
        "descriptor_loop_length": 60,
        "crc": "0x7632935"
    },
    "command": {
        "command_length": 15,
        "command_type": 5,
        "name": "Splice Insert",
        "break_auto_return": false,
        "break_duration": 180.0,
        "splice_event_id": 1073743095,
        "splice_event_cancel_indicator": false,
        "out_of_network_indicator": true,
        "program_splice_flag": false,
        "duration_flag": true,
        "splice_immediate_flag": false,
        "event_id_compliance_flag": true,
        "unique_program_id": 1,
        "avail_num": 12,
        "avails_expected": 5
    },
    "descriptors": [
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 12,
            "descriptor_length": 8
        },
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 13,
            "descriptor_length": 8
        },
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 14,
            "descriptor_length": 8
        },
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 15,
            "descriptor_length": 8
        },
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 16,
            "descriptor_length": 8
        },
        {
            "tag": 0,
            "identifier": "CUEI",
            "name": "Avail Descriptor",
            "provider_avail_id": 17,
            "descriptor_length": 8
        }
    ]
}
  • convert the data back to xml
>>>> print(cue.xml())
<scte35:SpliceInfoSection xmlns:scte35="https://scte.org/schemas/35"  ptsAdjustment="0" protocolVersion="0" sapType="3" tier="4095">
   <scte35:SpliceInsert spliceEventId="1073743095" spliceEventCancelIndicator="false" spliceImmediateFlag="false" eventIdComplianceFlag="true" availNum="12" availsExpected="5" outOfNetworkIndicator="true" uniqueProgramId="1">
      <scte35:BreakDuration autoReturn="false" duration="16200000"/>
   </scte35:SpliceInsert>
   <scte35:AvailDescriptor providerAvailId="12"/>
   <scte35:AvailDescriptor providerAvailId="13"/>
   <scte35:AvailDescriptor providerAvailId="14"/>
   <scte35:AvailDescriptor providerAvailId="15"/>
   <scte35:AvailDescriptor providerAvailId="16"/>
   <scte35:AvailDescriptor providerAvailId="17"/>
</scte35:SpliceInfoSection>
  • convert to xml+binary
>>>> print(cue.xmlbin())
<scte35:Signal xmlns:scte35="https://scte.org/schemas/35">
    <scte35:Binary>/DBcAAAAAAAAAP/wDwVAAAT3f69+APcxQAABDAUAPAAIQ1VFSQAAAAwACENVRUkAAAANAAhDVUVJAAAADgAIQ1VFSQAAAA8ACENVRUkAAAAQAAhDVUVJAAAAEQdjKTU=</scte35:Binary>
</scte35:Signal>
  • convert to base64
>>>> print(cue.base64())
/DBcAAAAAAAAAP/wDwVAAAT3f69+APcxQAABDAUAPAAIQ1VFSQAAAAwACENVRUkAAAANAAhDVUVJAAAADgAIQ1VFSQAAAA8ACENVRUkAAAAQAAhDVUVJAAAAEQdjKTU=
  • convert to hex
>>>> print(cue.hex())
0xfc305c00000000000000fff00f05400004f77faf7e00f7314000010c05003c0008435545490000000c0008435545490000000d0008435545490000000e0008435545490000000f000843554549000000100008435545490000001107632935
  • show just the splice command
>>>> cue.command.show()
{
    "command_length": 15,
    "command_type": 5,
    "name": "Splice Insert",
    "break_auto_return": false,
    "break_duration": 180.0,
    "splice_event_id": 1073743095,
    "splice_event_cancel_indicator": false,
    "out_of_network_indicator": true,
    "program_splice_flag": false,
    "duration_flag": true,
    "splice_immediate_flag": false,
    "event_id_compliance_flag": true,
    "unique_program_id": 1,
    "avail_num": 12,
    "avails_expected": 5
}
  • edit the break duration
>>>> cue.command.break_duration=30
>>>> cue.command.show()
{
    "command_length": 15,
    "command_type": 5,
    "name": "Splice Insert",
    "break_auto_return": false,
    "break_duration": 30,
    "splice_event_id": 1073743095,
    "splice_event_cancel_indicator": false,
    "out_of_network_indicator": true,
    "program_splice_flag": false,
    "duration_flag": true,
    "splice_immediate_flag": false,
    "event_id_compliance_flag": true,
    "unique_program_id": 1,
    "avail_num": 12,
    "avails_expected": 5
}
  • re-encode to base64 with the new duration
>>>> cue.base64()
'/DBcAAAAAAAAAP/wDwVAAAT3f69+ACky4AABDAUAPAAIQ1VFSQAAAAwACENVRUkAAAANAAhDVUVJAAAADgAIQ1VFSQAAAA8ACENVRUkAAAAQAAhDVUVJAAAAEe1FB6g='
  • re-encode to xml with the new duration
>>>> print(cue.xml())
<scte35:SpliceInfoSection xmlns:scte35="https://scte.org/schemas/35"  ptsAdjustment="0" protocolVersion="0" sapType="3" tier="4095">
   <scte35:SpliceInsert spliceEventId="1073743095" spliceEventCancelIndicator="false" spliceImmediateFlag="false" eventIdComplianceFlag="true" availNum="12" availsExpected="5" outOfNetworkIndicator="true" uniqueProgramId="1">
      <scte35:BreakDuration autoReturn="false" duration="2700000"/>
   </scte35:SpliceInsert>
   <scte35:AvailDescriptor providerAvailId="12"/>
   <scte35:AvailDescriptor providerAvailId="13"/>
   <scte35:AvailDescriptor providerAvailId="14"/>
   <scte35:AvailDescriptor providerAvailId="15"/>
   <scte35:AvailDescriptor providerAvailId="16"/>
   <scte35:AvailDescriptor providerAvailId="17"/>
</scte35:SpliceInfoSection>
  • show just the descriptors
>>>> _ = [d.show() for d in cue.descriptors]
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 12,
    "descriptor_length": 8
}
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 13,
    "descriptor_length": 8
}
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 14,
    "descriptor_length": 8
}
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 15,
    "descriptor_length": 8
}
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 16,
    "descriptor_length": 8
}
{
    "tag": 0,
    "identifier": "CUEI",
    "name": "Avail Descriptor",
    "provider_avail_id": 17,
    "descriptor_length": 8
}
  • pop off the last descriptor and re-encode to xml
>>>> cue.descriptors.pop()
{'tag': 0, 'identifier': 'CUEI', 'name': 'Avail Descriptor', 'private_data': None, 'provider_avail_id': 17, 'descriptor_length': 8}
>>>> print(cue.xml())
<scte35:SpliceInfoSection xmlns:scte35="https://scte.org/schemas/35"  ptsAdjustment="0" protocolVersion="0" sapType="3" tier="4095">
   <scte35:SpliceInsert spliceEventId="1073743095" spliceEventCancelIndicator="false" spliceImmediateFlag="false" eventIdComplianceFlag="true" availNum="12" availsExpected="5" outOfNetworkIndicator="true" uniqueProgramId="1">
      <scte35:BreakDuration autoReturn="false" duration="2700000"/>
   </scte35:SpliceInsert>
   <scte35:AvailDescriptor providerAvailId="12"/>
   <scte35:AvailDescriptor providerAvailId="13"/>
   <scte35:AvailDescriptor providerAvailId="14"/>
   <scte35:AvailDescriptor providerAvailId="15"/>
   <scte35:AvailDescriptor providerAvailId="16"/>
</scte35:SpliceInfoSection>

The Cli tool

The cli tool installs automatically with pip or the Makefile.

Inputs

  • Most inputs are auto-detected.
  • stdin is auto selected and auto detected.
  • SCTE-35 data is printed to stderr
  • stdout is used when piping video
  • mpegts can be specified by file name or URI.
threefive udp://@235.2.5.35:3535
  • If a file comtains a SCTE-35 cue as a string( base64,hex,int,json,or xml+bin), redirect the file contents.
  threefive < json.json  
  • quoted strings(( base64,hex,int,json or xml+bin), can be passed directly on the command line as well.
threefive '/DAWAAAAAAAAAP/wBQb+ztd7owAAdIbbmw=='
Input Type Cli Example
Base64 threefive '/DAsAAAAAyiYAP/wCgUAAAABf1+ZmQEBABECD0NVRUkAAAAAf4ABADUAAC2XQZU='
Hex threefive 0xfc301600000000000000fff00506fed605225b0000b0b65f3b
HLS threefive hls https://example.com/master.m3u8
JSON threefive < json.json
Xmlbin js threefive < xmlbin.xml

Streams

Protocol Cli Example
File threefive video.ts
Http(s) threefive https://example.com/video.ts
Stdin threefive < video.ts
UDP Multicast threefive udp://@235.35.3.5:9999
UDP Unicast threefive udp://10.0.0.7:5555
HLS__ threefive hls https://example.com/master.m3u8

Outputs

  • output type is determined by the key words base64, bytes, hex, int, json, and xmlbin.
  • json is the default.
  • Any input (except HLS,) can be returned as any output
    • examples Base64 to Hex etc...)
Output Type Cli Example
Base 64 threefive 0xfc301600000000000000fff00506fed605225b0000b0b65f3b base64
Bytes threefive 0xfc301600000000000000fff00506fed605225b0000b0b65f3b bytes
Hex threefive '/DAsAAAAAyiYAP/wCgUAAAABf1+ZmQEBABECD0NVRUkAAAAAf4ABADUAAC2XQZU=' hex
Integer threefive '/DAsAAAAAyiYAP/wCgUAAAABf1+ZmQEBABECD0NVRUkAAAAAf4ABADUAAC2XQZU=' int
JSON threefive 0xfc301600000000000000fff00506fed605225b0000b0b65f3b json
Xml+bin threefive 0xfc301600000000000000fff00506fed605225b0000b0b65f3b xmlbin

hls

  • parse hls manifests and segments for SCTE-35
threefive hls https://example.com/master.m3u8

Iframes

  • Show iframes PTS in an MPEGTS video
threefive iframes https://example.com/video.ts

packets

  • Print raw SCTE-35 packets from multicast mpegts video
threefive packets udp://@235.35.3.5:3535

proxy

  • Parse a https stream and write raw video to stdout
threefive proxy video.ts

pts

  • Print PTS from mpegts video
threefive pts video.ts

sidecar

  • Parse a stream, write pts,write SCTE-35 Cues to sidecar.txt
threefive sidecar video.ts

sixfix

  • Fix SCTE-35 data mangled by ffmpeg
threefive sixfix video.ts

show

  • Probe mpegts video ( kind of like ffprobe )
 threefive show video.ts

version

  • Show version
 threefive version

help

  • Help
 threefive help

Stream Multicast with the threefive cli, it's easy.

  • The threefive cli has long been a Multicast Receiver( client )
  • The cli now comes with a builtin Multicast Sender( server).
  • Start the Receiver first
  • It's optimized for MPEGTS (1316 byte Datagrams) but you can send any video or file.
  • The defaults will work in most situations, you don't even have to set the address.
  • threefive cli also supports UDP Unicast Streaming.

image

a@fu:~$ threefive mcast help
usage: threefive mcast [-h] [-i INPUT] [-a ADDR] [-b BIND_ADDR] [-t TTL]

optional arguments:
  -h, --help            show this help message and exit
  -i INPUT, --input INPUT
                        like "/home/a/vid.ts" or "udp://@235.35.3.5:3535" or
                        "https://futzu.com/xaa.ts"
                        [default:sys.stdin.buffer]
  -a ADDR, --addr ADDR  Destination IP:Port [default:235.35.3.5:3535]
  -b BIND_ADDR, --bind_addr BIND_ADDR
                        Local IP to bind [default:0.0.0.0]
  -t TTL, --ttl TTL     Multicast TTL (1 - 255) [default:32]
a@fu:~$ 

iodisco.com/scte35

Month Savings
January $100
Base64 SCTE-35
  • The Cli tool can decode Base64 SCTE-35 on the command line.
	a@fu:~$ threefive '/DAgAAAAAAAAAP/wDwUAAAABf//+AA27oAABAAAAANwB3tE='
  • Using the library Base64 SCTE-35 is decoded by the Cue class.
	
	from threefive import Cue
	
	data='/DAgAAAAAAAAAP/wDwUAAAABf//+AA27oAABAAAAANwB3tE='   
	
	cue=Cue(data)
	
	cue.show()
	
Hex SCTE-35
  • The Cli tool
	a@fu:~$ threefive 0xfc302000000000000000fff00f05000000017ffffe000dbba0000100000000dc01ded1
  • Convert from Hex to bas64,bytes,json,Int, xml or xmlbin
	a@fu:~$ threefive 0xfc302000000000000000fff00f05000000017ffffe000dbba0000100000000dc01ded1 base64
	a@fu:~$ threefive 0xfc302000000000000000fff00f05000000017ffffe000dbba0000100000000dc01ded1 xml
  • Convert to Hex
a@fu:~$ threefive '/DAgAAAAAAAAAP/wDwUAAAABf//+AA27oAABAAAAANwB3tE=' hex
  • lib
	
from threefive import Cue
	
data='0xfc302000000000000000fff00f05000000017ffffe000dbba0000100000000dc01ded1''   
	
cue=Cue(data)
	
cue.show()
	
  • Convert from Hex to bas64,bytes,json,Int, xml or xmlbin
from threefive import Cue	
data='0xfc302000000000000000fff00f05000000017ffffe000dbba0000100000000dc01ded1''   
cue=Cue(data)

cue.base64() 	# base64

cue.bytes()  	# or bytes

cue.show()  	# or json

cue.int()  		# or int

cue.xml()  		# or xml

cue.xmlbin() 	# or xmlbin

Install |SCTE-35 Cli | SCTE-35 HLS | Cue Class | Stream Class | Online SCTE-35 Parser | Encode SCTE-35 | SCTE-35 Examples | SCTE-35 XML and More XML | threefive runs Four Times Faster on pypy3 | SuperKabuki SCTE-35 MPEGTS Packet Injection

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

Uploaded Source

Built Distribution

threefive-3.0.57-py3-none-any.whl (78.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: threefive-3.0.57.tar.gz
  • Upload date:
  • Size: 76.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.2

File hashes

Hashes for threefive-3.0.57.tar.gz
Algorithm Hash digest
SHA256 dc977a9630b641236c538fcd5459f4065651a9b1b7630164f68bccea07a87061
MD5 1e34473957604e43f4ad2e2b6c938602
BLAKE2b-256 09ae96569e2b92196bee2fae9bedc08e4aa484806f03922c97dd6a3d4944870e

See more details on using hashes here.

File details

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

File metadata

  • Download URL: threefive-3.0.57-py3-none-any.whl
  • Upload date:
  • Size: 78.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.11.2

File hashes

Hashes for threefive-3.0.57-py3-none-any.whl
Algorithm Hash digest
SHA256 48e334b690bbec4742292338014dbd988b60f383a240fd95914dcb9f7f42b09a
MD5 5217b8262d8e6c903eeffd703b02e1e9
BLAKE2b-256 53f22060748d3df47aa4feb69480d24480145295311a9d2c7ce7adc8a62e4f14

See more details on using hashes here.

Supported by

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