{"id":26506256,"url":"https://github.com/superkabuki/skdc","last_synced_at":"2025-10-15T09:49:55.860Z","repository":{"id":283564836,"uuid":"945909738","full_name":"superkabuki/skdc","owner":"superkabuki","description":"Super Karate Death Car is the World's Fastest SCTE-35 Parser library.Written in Go.","archived":false,"fork":false,"pushed_at":"2025-08-23T18:07:43.000Z","size":58,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-24T06:32:37.009Z","etag":null,"topics":["adbreak","adrianofdoom","adtech","boobs","golang","scte-35","scte-35parser","scte-marker","scte35","superkabuki"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/superkabuki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-10T10:13:58.000Z","updated_at":"2025-08-23T18:07:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"be49c4d5-a995-421a-b508-9ed0ae4c55ed","html_url":"https://github.com/superkabuki/skdc","commit_stats":null,"previous_names":["superkabuki/skdc"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/superkabuki/skdc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superkabuki%2Fskdc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superkabuki%2Fskdc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superkabuki%2Fskdc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superkabuki%2Fskdc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/superkabuki","download_url":"https://codeload.github.com/superkabuki/skdc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/superkabuki%2Fskdc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279068864,"owners_count":26096574,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-15T02:00:07.814Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adbreak","adrianofdoom","adtech","boobs","golang","scte-35","scte-35parser","scte-marker","scte35","superkabuki"],"created_at":"2025-03-20T22:26:33.602Z","updated_at":"2025-10-15T09:49:55.830Z","avatar_url":"https://github.com/superkabuki.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n [Install](#install-skdc)  | [Go Docs](https://pkg.go.dev/github.com/superkabuki/skdc)  | [Examples](https://pkg.go.dev/github.com/superkabuki/skdc) | \n\n# `S`uper `K`arate `D`eath `C`ar is a SCTE-35 Parser lib written in Go.\n# Encoder/Decoder for SCTE-35\n\u003cbr\u003e\n\n\n- [x] Parses SCTE-35 Cues from MPEGTS or Bytes or Base64 or Hex or Int or Octal or even Base 36.\n- [x] Parses SCTE-35 Cues spread over multiple MPEGTS packets  \n- [x] Supports multi-packet PAT and PMT tables  \n- [x] Supports multiple MPEGTS Programs and multiple SCTE-35 streams \n- [x] Encodes Time Signals and Splice Inserts with Descriptors and Upids. \n \n___\n\n##  Super Karate Death Car is fast.\n![image](https://github.com/user-attachments/assets/edc29afe-d198-44e2-a230-567acbcddbdf)\n\n\n\n\n### Want to parse an MPEGTS video and print the SCTE-35?  🛰️\n\n### Do it in ten lines.\n```go\npackage main                        \n\nimport (                              \n        \"os\"                            \n        \"github.com/superkabuki/skdc\"       \n)                                    \n\nfunc main(){                         \n        arg := os.Args[1]             \n        stream := skdc.NewStream()    \n        stream.Decode(arg)           \n}                                    \n```\n---\n\n# Documentation\n\n\n* [Install](#install-skdc)  \n\n\n* [Examples](https://pkg.go.dev/github.com/superkabuki/skdc)\n\t* skdc.Stream \n\t\t* [Parse SCTE-35 from MPEGTS](#quick-demo)\n   \t\t* [Custom Cue Handling for MPEGTS Streams](#custom-cue-handling-for-mpegts-streams)\n   \t\t* [Multicast](#custom-cue-handling-for-mpegts-streams-over-multicast) _(New!)_\n\n   \t* skdc.Cue\n\t\t* [Parse Base64 encoded SCTE-35](#parse-base64-encoded-scte-35) \n\t\t* [Use Dot Notation to access SCTE-35 Cue values](#use-dot-notation-to-access-scte-35-cue-values)\n\t\t* [Shadow a Cue Struct Method ( override ) ](#shadow-a-cue-struct-method)\n\t\t* [Shadow a Cue Method and call the Shadowed Method ( like super in python )](#call-a-shadowed-method)\n  \t\t* [Load a SCTE-35 Cue from JSON and Encode it](#load-json-and-encode)\n\n\n\n### `Install skdc` \n\n```go\ngo install github.com/superkabuki/skdc@latest\n\n```\n\n\n\n### `Quick Demo` \n\n* skdcdemo.go\n\n```go\npackage main\n\nimport (\n        \"os\"\n        \"fmt\"\n        \"github.com/superkabuki/skdc\"\n)\n\nfunc main(){\n\n        arg := os.Args[1]\n\n        stream := skdc.NewStream()\n        cues := stream.Decode(arg)\n        for _,cue := range cues {\n        fmt.Printf(\"Command is a %v\\n\", cue.Command.Name)\n        }\n\n}\n\n\n\n```\n\n#### `build skdcdemo`\n```go\ngo build skdcdemo.go\n```\n#### `parse mpegts video for scte35` \n```go\n./skdcdemo a_video_with_scte35.ts\n```\n\t\t\t\n### SCTE-35 Cues\n```go\ntype Cue struct {\n\tInfoSection *InfoSection  \n\tCommand     *Command          \n\tDll         uint16       `json:\"DescriptorLoopLength\"`\n\tDescriptors []Descriptor `json:\",omitempty\"`\n\tCrc32       string\n\tPacketData  *packetData `json:\",omitempty\"`\n}\n```\n* Output is JSON and looks like this.\n```awk\n{\n    \"InfoSection\": {\n        \"Name\": \"Splice Info Section\",\n        \"TableID\": \"0xfc\",\n        \"SectionSyntaxIndicator\": false,\n        \"Private\": false,\n        \"SapType\": 3,\n        \"SapDetails\": \"No Sap Type\",\n        \"SectionLength\": 44,\n        \"ProtocolVersion\": 0,\n        \"EncryptedPacket\": false,\n        \"EncryptionAlgorithm\": 0,\n        \"PtsAdjustment\": 2.3,\n        \"CwIndex\": \"0x0\",\n        \"Tier\": \"0xfff\",\n        \"CommandLength\": 10,\n        \"CommandType\": 5\n    },\n\n    \"Command\": {\n        \"Name\": \"Splice Insert\",\n        \"CommandType\": 5,\n        \"SpliceEventID\": 1,\n        \"SpliceEventCancelIndicator\": false,\n        \"OutOfNetworkIndicator\": false,\n        \"ProgramSpliceFlag\": true,\n        \"DurationFlag\": false,\n        \"BreakDuration\": 0,\n        \"BreakAutoReturn\": false,\n        \"SpliceImmediateFlag\": true,\n        \"EventIDComplianceFlag\": true,\n        \"UniqueProgramID\": 39321,\n        \"AvailNum\": 1,\n        \"AvailExpected\": 1\n    },\n    \"DescriptorLoopLength\": 17,\n\n    \"Descriptors\": [\n        {\n            \"Tag\": 2,\n            \"Length\": 15,\n            \"Name\": \"Segmentation Descriptor\",\n            \"Identifier\": \"CUEI\",\n            \"SegmentationEventID\": \"0x0\",\n            \"SegmentationEventCancelIndicator\": false,\n            \"SegmentationEventIDComplianceIndicator\": true,\n            \"ProgramSegmentationFlag\": true,\n            \"SegmentationDurationFlag\": false,\n            \"DeliveryNotRestrictedFlag\": false,\n            \"WebDeliveryAllowedFlag\": false,\n            \"NoRegionalBlackoutFlag\": false,\n            \"ArchiveAllowedFlag\": false,\n            \"DeviceRestrictions\": \"Restrict Group 0\",\n            \"SegmentationDuration\": 0,\n            \"SegmentationMessage\": \"Provider Placement Opportunity End\",\n            \"SegmentationUpidType\": 1,\n            \"SegmentationUpidLength\": 0,\n            \"SegmentationUpid\": null,\n            \"SegmentationTypeID\": 53,\n            \"SegmentNum\": 0,\n            \"SegmentsExpected\": 0,\n            \"SubSegmentNum\": 0,\n            \"SubSegmentsExpected\": 0\n        }\n    ],\n    \"Crc32\": \" 0x2d974195\",\n    \"PacketData\": {\n        \"Pid\": 258,\n        \"Program\": 1,\n        \"Pts\": 72951.196988\n    }\n}\n```\n\n### `Parse base64 encoded SCTE-35`\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n)\n\nfunc main(){\n\n\tcue := skdc.NewCue()\n\tdata := \"/DA7AAAAAAAAAP/wFAUAAAABf+/+AItfZn4AKTLgAAEAAAAWAhRDVUVJAAAAAX//AAApMuABACIBAIoXZrM=\"\n        cue.Decode(data) \n        fmt.Println(\"Cue as Json\")\n        cue.Show()\n}\n```\n\n### `Shadow a Cue struct method`\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n)\n\ntype Cue2 struct {\n    skdc.Cue               \t\t// Embed skdc.Cue\n}\nfunc (cue2 *Cue2) Show() {        \t// Override Show\n\tfmt.Printf(\"%+v\",cue2.Command)\n}\n\nfunc main(){\n\tvar cue2 Cue2\n\tdata := \"/DA7AAAAAAAAAP/wFAUAAAABf+/+AItfZn4AKTLgAAEAAAAWAhRDVUVJAAAAAX//AAApMuABACIBAIoXZrM=\"\n        cue2.Decode(data) \n        cue2.Show()\n}\n\n```\n\n### `Call a shadowed method`\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n)\n\ntype Cue2 struct {\n    skdc.Cue               \t\t// Embed skdc.Cue\n}\nfunc (cue2 *Cue2) Show() {        \t// Override Show\n\tfmt.Println(\"Cue2.Show()\")\n\tfmt.Printf(\"%+v\",cue2.Command) \n\tfmt.Println(\"\\n\\nskdc.Cue.Show() from cue2.Show()\")\n\tcue2.Cue.Show()\t\t\t// Call the Show method from embedded skdc.Cue\n}\n\nfunc main(){\n\tvar cue2 Cue2\n\tdata := \"/DA7AAAAAAAAAP/wFAUAAAABf+/+AItfZn4AKTLgAAEAAAAWAhRDVUVJAAAAAX//AAApMuABACIBAIoXZrM=\"\n        cue2.Decode(data) \n        cue2.Show()\n\t\n}\n\n\n```\n### `Use Dot notation to access SCTE-35 Cue values`\n* SuperKarate DeathCar doesn't use interfaces for SCTE-35 data\n* SCTE-35 Data can be accessed directly via dot notation \n\n```go\n\n/**\nShow  the packet PTS time and Splice Command Name of SCTE-35 Cues\nin a MPEGTS stream.\n**/\npackage main\n\nimport (\n\t\"os\"\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n)\n\nfunc main() {\n\targ := os.Args[1]\n\tstream := skdc.NewStream()\n\tcues :=\tstream.Decode(arg)\n\tfor _,c := range cues {\n\t\tfmt.Printf(\"PTS: %v, Splice Command: %v\\n\",c.PacketData.Pts, c.Command.Name )\n\t}\n}\n\n```\n\n### `Load JSON and Encode`\n* skdc can accept SCTE-35 data as JSON and encode it to Base64, Bytes, or Hex string.\n* The function __skdc.Json2Cue()__ accepts SCTE-35 JSON as input and returns a *skdc.Cue\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n)\n\nfunc main() {\n\n\tjs := `{\n    \"InfoSection\": {\n        \"Name\": \"Splice Info Section\",\n        \"TableID\": \"0xfc\",\n        \"SectionSyntaxIndicator\": false,\n        \"Private\": false,\n        \"Reserved\": \"0x3\",\n        \"SectionLength\": 42,\n        \"ProtocolVersion\": 0,\n        \"EncryptedPacket\": false,\n        \"EncryptionAlgorithm\": 0,\n        \"PtsAdjustment\": 0,\n        \"CwIndex\": \"0xff\",\n        \"Tier\": \"0xfff\",\n        \"CommandLength\": 15,\n        \"CommandType\": 5\n    },\n    \"Command\": {\n        \"Name\": \"Splice Insert\",\n        \"CommandType\": 5,\n        \"SpliceEventID\": 5690,\n        \"OutOfNetworkIndicator\": true,\n        \"ProgramSpliceFlag\": true,\n        \"TimeSpecifiedFlag\": true,\n        \"PTS\": 23683.480033\n    },\n    \"DescriptorLoopLength\": 10,\n    \"Descriptors\": [\n        {\n            \"Length\": 8,\n            \"Identifier\": \"CUEI\",\n            \"Name\": \"Avail Descriptor\"\n        }\n    ],\n    \"Crc32\": \"0xd7165c79\"\n}\n`\ncue :=  skdc.Json2Cue(js)    // \ncue.AdjustPts(28.0)   \t // Apply pts adjustment\nfmt.Println(\"\\nBytes:\\n\\t\", cue.Encode())\t// Bytes\nfmt.Println(\"\\nBase64:\\n\\t\",cue.Encode2B64())  \t// Base64\nfmt.Println(\"\\nHex:\\n\\t\",cue.Encode2Hex()) \t// Hex\n\n}\n\n\n```\n* Output\n```smalltalk\nBytes:\n\t[252 48 42 0 0 0 38 115 192 255 255 240 15 5 0 0 22 58 127 207 254 127 12 79 115\n\t0 0 0 0 0 10 0 8 67 85 69 73 0 0 0 0 236 139 53 78]\n\nBase64:\n\t /DAqAAAAJnPA///wDwUAABY6f8/+fwxPcwAAAAAACgAIQ1VFSQAAAADsizVO\n\nHex:\n\t 0xfc302a0000002673c0fffff00f050000163a7fcffe7f0c4f7300000000000a00084355454900000000ec8b354e\n\n```\n## skdc.Stream\n### `Custom Cue Handling for MPEGTS Streams`\n##### Four Steps\n1) Create Stream Instance\n2) Read Bytes from the video stream (__in multiples of 188__)\n3) Call Stream.DecodeBytes(Bytes) \n4) Process [] *Cue returned by Stream.DecodeBytes\n\n```go\npackage main\n\nimport (\n        \"fmt\"\n        \"github.com/superkabuki/skdc\"\n        \"os\"\n)\n\nfunc main() {\n\n  arg := os.Args[1]\n  stream := skdc.NewStream()  //   (1)\n  bufSize := 32768 * 188   // Always read in multiples of 188\n  file, err := os.Open(arg)\n  if err != nil {\n    fmt.Printf(\"Unable to read %v\\n\", arg)\n  }\n  buffer := make([]byte, bufSize)\n  for {\n  \t_, err := file.Read(buffer)   //  (2)\n\tif err != nil {\n\t\tbreak\n\t}\n\tcues := stream.DecodeBytes(buffer)  // (3)\n\n\tfor _, c := range cues {  //   (4)\n\t\tfmt.Printf(\" %v, %v\\n\", c.PacketData.Pts, c.Encode2B64())\n\t}\n  }\n}\n\n```\n* Output\n```php\n60638.745877, /DAWAAAAAAAAAP/wBQb/RUqw1AAAd6OnQA==\n 60638.745877, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60640.714511, /DAWAAAAAAAAAP/wBQb/RU1wqAAAoqaOaA==\n 60640.714511, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60642.015811, /DAWAAAAAAAAAP/wBQb/RU9F4AAA9Te5ag==\n 60642.015811, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60642.749877, /DAWAAAAAAAAAP/wBQb/RVAwfAAAWOLrFQ==\n 60642.749877, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60644.718511, /DAWAAAAAAAAAP/wBQb/RVLwUAAAj7/Pgw==\n 60644.718511, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60646.720511, /DAWAAAAAAAAAP/wBQb/RVWwJAAA8pm/jg==\n 60646.720511, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60648.121911, /DAWAAAAAAAAAP/wBQb/RVec0gAAt0QzqA==\n 60648.121911, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60634.208011, /DAWAAAAAAAAAP/wBQb/RUR1fAAAik8gfQ==\n 60634.208011, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60634.675144, /DAWAAAAAAAAAP/wBQb/RUUxLAAABQVyEA==\n 60634.675144, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n 60636.710511, /DAWAAAAAAAAAP/wBQb/RUfxAAAA0lhWhg==\n 60636.710511, /DAgAAAAAAAAAP/wDwUAAAABf//+AFJlwAABAAAAAMOOklg=\n```\n\n### `Custom Cue Handling for MPEGTS Streams Over Multicast`\n##### Need a multicast sender? Try [gums](https://github.com/superkabuki/gums)\n\n\u003cdiv\u003e for multicast we use the same four steps,\u003cbr\u003e the only difference is we read the bytes from the network instead of a local file. \u003c/div\u003e\n\n1) Create Stream Instance\n2) Read Bytes from the video stream (__in multiples of 188__)\n3) Call Stream.DecodeBytes(Bytes) \n4) Process [] *Cue returned by Stream.DecodeBytes\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/superkabuki/skdc\"\n\t\"os\"\n        \"net\"\n)\n\n\nfunc main() {\n  arg := os.Args[1]\n  stream := skdc.NewStream()  //  (1)\n  stream.Quiet = true\n  dgram:=1316  // \u003c-- multicast dgram size is 1316 (188*7) for mpegts\n  bufSize := 100 * dgram\n  addr, _ := net.ResolveUDPAddr(\"udp\", arg)\n  l, _ := net.ListenMulticastUDP(\"udp\", nil, addr)  // Multicast Connection \n  l.SetReadBuffer(bufSize)\n  for {\n\tbuffer := make([]byte, bufSize)  // (2)\n\tl.ReadFromUDP(buffer)\n\tcues := stream.DecodeBytes(buffer)   //  (3)\n\tfor _, c := range cues {      //  (4)\n\t\tfmt.Printf(\" %v, %v\\n\", c.PacketData.Pts, c.Encode2B64())\n\t}\n  }\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperkabuki%2Fskdc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsuperkabuki%2Fskdc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsuperkabuki%2Fskdc/lists"}