Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/comcast/scte35-go
Golang implementation of ANSI/SCTE-35
https://github.com/comcast/scte35-go
decoder encoder go golang mpeg-ts scte-35 signaling video
Last synced: 29 days ago
JSON representation
Golang implementation of ANSI/SCTE-35
- Host: GitHub
- URL: https://github.com/comcast/scte35-go
- Owner: Comcast
- License: apache-2.0
- Created: 2021-06-28T19:54:56.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-07-24T17:39:51.000Z (6 months ago)
- Last Synced: 2024-12-09T03:12:06.985Z (about 1 month ago)
- Topics: decoder, encoder, go, golang, mpeg-ts, scte-35, signaling, video
- Language: Go
- Homepage:
- Size: 3.34 MB
- Stars: 36
- Watchers: 10
- Forks: 15
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# scte35-go: ANSI/SCTE 35 Decoder/Encoder
`scte35-go` is a Go library to supports creating, decorating, and analyzing
binary Digital Program Insertion Cueing Messages.This library is fully compliant and compatible with all versions of the
[ANSI/SCTE 35](https://www.scte.org/standards-development/library/standards-catalog/scte-35-2019/)
specification up to and including [ANSI/SCTE 35 2022b](./docs/SCTE_35_2022b.pdf).This project uses [Semantic Versioning](https://semver.org) and is published as
a [Go Module](https://blog.golang.org/using-go-modules).[![Build Status](https://github.com/Comcast/scte35-go/actions/workflows/check.yml/badge.svg)](https://github.com/Comcast/scte35-go/actions/workflows/check.yml)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/Comcast/scte35-go)](https://pkg.go.dev/github.com/Comcast/scte35-go)## Getting Started
Get the module:
```shell
$ go get github.com/Comcast/scte35-go
go get: added github.com/Comcast/scte35-go v1.2.1
```## Code Examples
Additional examples can be found in [examples](./examples).
#### Decode Signal
Binary signals can be quickly and easily decoded from base-64 or hexadecimal
strings.The results can be output as a:
* String - emulating the table structure used in the [SCTE 35 specification](./docs/SCTE_35_2022b.pdf).
* XML - compliant with the [SCTE 35 XML Schema](./docs/scte_35_20220816.xsd)
* JSON - for integrating with JSON based tools such as [jq](https://stedolan.github.io/jq/)[decode.go](../examples/decode.go)
```go
package mainimport (
"encoding/json"
"encoding/xml"
"fmt"
"os""github.com/Comcast/scte35-go/pkg/scte35"
)func main() {
sis, _ := scte35.DecodeBase64("/DA8AAAAAAAAAP///wb+06ACpQAmAiRDVUVJAACcHX//AACky4AMEERJU0NZTVdGMDQ1MjAwMEgxAQEMm4c0")// details
_, _ = fmt.Fprintf(os.Stdout, "\nDetails: \n%s\n", sis)// xml
b, _ := xml.MarshalIndent(sis, "", "\t")
_, _ = fmt.Fprintf(os.Stdout, "\nXML: \n%s\n", b)// json
b, _ = json.MarshalIndent(sis, "", "\t")
_, _ = fmt.Fprintf(os.Stdout, "\nJSON: \n%s\n", b)
}
``````shell
$ go run ./examples/decode.goDetails:
splice_info_section() {
table_id: 0xfc
section_syntax_indicator: false
private_indicator: false
sap_type: Not Specified
section_length: 60 bytes
}
protocol_version: 0
encrypted_packet: false
encryption_algorithm: No encryption
pts_adjustment: 0 ticks (0s)
cw_index: 0
tier: 4095
splice_command_length: 5 bytes
splice_command_type: 0x06
time_signal() {
time_specified_flag: true
pts_time: 3550479013 ticks (10h57m29.766811111s)
}
descriptor_loop_length: 38 bytes
avail_descriptor() {
splice_descriptor_tag: 0x02
descriptor_length: 36 bytes
identifier: CUEI
segmentation_event_id: 39965
segmentation_event_cancel_indicator: false
program_segmentation_flag: true
segmentation_duration_flag: true
delivery_not_restricted_flag: true
segmentation_duration: 10800000 ticks (2m0s)
segmentation_upid_length: 16 bytes
segmentation_upid {
segmentation_upid_type: MPU() (0x0c)
format_identifer: DISC
segmentation_upid: 0x44495343594d57463034353230303048
}
segmentation_type_id: Provider Advertisement End (0x31)
segment_num: 1
segments_expected: 1
}XML:
WU1XRjA0NTIwMDBI
JSON:
{
"protocolVersion": 0,
"ptsAdjustment": 0,
"sapType": 3,
"spliceCommand": {
"type": 6,
"spliceTime": {
"ptsTime": 3550479013
}
},
"spliceDescriptors": [
{
"type": 2,
"deliveryRestrictions": null,
"segmentationUpids": [
{
"segmentationUpidType": 12,
"formatIdentifier": 1145656131,
"format": "base-64",
"value": "WU1XRjA0NTIwMDBI"
}
],
"components": null,
"segmentationEventId": 39965,
"segmentationEventCancelIndicator": false,
"segmentationDuration": 10800000,
"segmentationTypeId": 49,
"segmentNum": 1,
"segmentsExpected": 1,
"subSegmentNum": null,
"subSegmentsExpected": null
}
],
"tier": 4095
}
```#### Encode Signal
Encoding signals is equally simple. You can start from scratch and build a
`scte35.SpliceInfoSection` or decode an existing signal and modify it to suit
your needs.[encode.go](./examples/encode.go)
```go
package mainimport (
"fmt"
"os""github.com/Comcast/scte35-go/pkg/scte35"
)func main() {
// start with a signal
sis := scte35.SpliceInfoSection{
SpliceCommand: scte35.NewTimeSignal(0x072bd0050),
SpliceDescriptors: []scte35.SpliceDescriptor{
&scte35.SegmentationDescriptor{
DeliveryRestrictions: &scte35.DeliveryRestrictions{
NoRegionalBlackoutFlag: true,
ArchiveAllowedFlag: true,
DeviceRestrictions: scte35.DeviceRestrictionsNone,
},
SegmentationEventID: uint32(0x4800008e),
SegmentationTypeID: scte35.SegmentationTypeProviderPOStart,
SegmentationUPIDs: []scte35.SegmentationUPID{
scte35.NewSegmentationUPID(scte35.SegmentationUPIDTypeTI, []byte("78511452")),
},
SegmentNum: 2,
},
},
EncryptedPacket: scte35.EncryptedPacket{CWIndex: 255},
Tier: 4095,
SAPType: 3,
}// encode it
_, _ = fmt.Fprintf(os.Stdout, "Original:\n")
_, _ = fmt.Fprintf(os.Stdout, "base-64: %s\n", sis.Base64())
_, _ = fmt.Fprintf(os.Stdout, "hex : %s\n", sis.Hex())// add a segmentation descriptor
sis.SpliceDescriptors = append(
sis.SpliceDescriptors,
&scte35.DTMFDescriptor{
DTMFChars: "ABC*",
},
)// encode it again
_, _ = fmt.Fprintf(os.Stdout, "\nModified:\n")
_, _ = fmt.Fprintf(os.Stdout, "base-64: %s\n", sis.Base64())
_, _ = fmt.Fprintf(os.Stdout, "hex : %s\n", sis.Hex())
}```
```shell
$ go run ./examples/encode.go
Original:
base-64: /DAvAAAAAAAA///wBQb+cr0AUAAZAhdDVUVJSAAAjn+PCAg3ODUxMTQ1MjQCADhqB9E=
hex : fc302f000000000000fffff00506fe72bd005000190217435545494800008e7f8f08083738353131343532340200386a07d1Modified:
base-64: /DA7AAAAAAAA///wBQb+cr0AUAAlAhdDVUVJSAAAjn+PCAg3ODUxMTQ1MjQCAAEKQ1VFSQCfQUJDKqtwQlQ=
hex : fc303b000000000000fffff00506fe72bd005000250217435545494800008e7f8f08083738353131343532340200010a43554549009f4142432aab704254
```#### Decoding Non-Compliant Signals
The SCTE 35 decoder will always return a non-nil `SpliceInfoSection`, even when
an error occurs. This is done to help better identify the specific cause of the
decoding failure.[bad-signal](./examples/bad_signal.go)
```go
package mainimport (
"fmt"
"os""code.comcast.com/jbaile223/scte35/pkg/scte35"
)func main() {
sis, err := scte35.DecodeBase64("FkC1lwP3uTQD0VvxHwVBEH89G6B7VjzaZ9eNuyUF9q8pYAIXsRM9ZpDCczBeDbytQhXkssQstGJVGcvjZ3tiIMULiA4BpRHlzLGFa0q6aVMtzk8ZRUeLcxtKibgVOKBBnkCbOQyhSflFiDkrAAIp+Fk+VRsByTSkPN3RvyK+lWcjHElhwa9hNFcAy4dm3DdeRXnrD3I2mISNc7DkgS0ReotPyp94FV77xMHT4D7SYL48XU20UM4bgg==")
if err != nil {
fmt.Fprintf(os.Stdout, "Error: %s\n", err)
}
// splice info section contains best-effort decoding
fmt.Fprintf(os.Stdout, "Signal: %s", sis)
}
```As we can see from the output below, the signal has a corrupted `component_count`,
causing the decoder to return a `scte.ErrBufferOverflow`:```shell
$ go run ./examples/bad_signal.go
Error: splice_insert: buffer overflow
Signal: splice_info_section() {
table_id: 0xfc
section_syntax_indicator: false
private_indicator: false
sap_type: Type 1
section_length: 343 bytes
}
protocol_version: 151
encrypted_packet: false
encryption_algorithm: No encryption
pts_adjustment: 8451077123 ticks (26h5m0.856922222s)
cw_index: 209
tier: 1471
splice_command_length: 326 bytes
splice_command_type: 0x05
splice_insert() {
splice_event_id: 1091600189
splice_event_cancel_indicator: false
out_of_network_indicator: true
program_splice_flag: false
duration_flag: true
splice_immediate_flag: false
component_count: 123
component[0] {
component_tag: 86
time_specified_flag: false
}... additional components removed
component[122] {
component_tag: 0
time_specified_flag: false
}
auto_return: false
duration: 0 ticks (0s)
unique_program_id: 0
avail_num: 0
avails_expected: 0
}
```#### CRC_32 Validation
The SCTE 35 decoder performs automatic `CRC_32` validation. The returned error
can be explicitly ignored if desired.```go
sis, err := scte35.DecodeBase64("/DA4AAAAAAAAAP/wFAUABDEAf+//mWEhzP4Azf5gAQAAAAATAhFDVUVJAAAAAX+/AQIwNAEAAKeYO3Q=")
if err != nil && !errors.Is(err, scte35.ErrCRC32Invalid) {
return err
}
```#### Logging
Additional diagnostics can be enabled by redirecting the output of
`scte35.Logger````go
scte35.Logger.SetOutput(os.Stderr)
```## Command Line Interface
This package also provides a simple command line interface that supports
encoding and decoding signals from the command line.```shell
$ ./scte35-go --help
SCTE-35 CLIUsage:
scte35-go [command]Available Commands:
decode Decode a splice_info_section from binary
encode Encode a splice_info_section to binary
help Help about any commandFlags:
-h, --help help for scte35-go
```## License
`scte35-go` is licensed under [Apache License 2.0](/LICENSE.md).
## Code of Conduct
We take our [code of conduct](CODE_OF_CONDUCT.md) very seriously. Please abide
by it.## Contributing
Please read our [contributing guide](CONTRIBUTING.md) for details on how to
contribute to our project.