{"id":18305978,"url":"https://github.com/rafaelcaricio/scte35","last_synced_at":"2025-08-21T05:31:55.328Z","repository":{"id":66274669,"uuid":"484866415","full_name":"rafaelcaricio/scte35","owner":"rafaelcaricio","description":"Parse and encoding of data using the SCTE-35 standard.","archived":false,"fork":false,"pushed_at":"2025-06-11T20:55:02.000Z","size":365,"stargazers_count":4,"open_issues_count":5,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-17T19:42:37.827Z","etag":null,"topics":["advertisement","monetization","scte-35","scte-marker","streaming-video","video-processing"],"latest_commit_sha":null,"homepage":"https://docs.rs/scte35/latest/scte35/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rafaelcaricio.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}},"created_at":"2022-04-23T22:05:51.000Z","updated_at":"2025-06-11T20:55:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"20acaab1-bb5c-45e4-b2ea-95b084d98590","html_url":"https://github.com/rafaelcaricio/scte35","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rafaelcaricio/scte35","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelcaricio%2Fscte35","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelcaricio%2Fscte35/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelcaricio%2Fscte35/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelcaricio%2Fscte35/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rafaelcaricio","download_url":"https://codeload.github.com/rafaelcaricio/scte35/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafaelcaricio%2Fscte35/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271430753,"owners_count":24758364,"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-08-21T02:00:08.990Z","response_time":74,"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":["advertisement","monetization","scte-35","scte-marker","streaming-video","video-processing"],"created_at":"2024-11-05T15:36:15.453Z","updated_at":"2025-08-21T05:31:55.310Z","avatar_url":"https://github.com/rafaelcaricio.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SCTE-35 Library\n\nA Rust library for creating and parsing SCTE-35 (Society of Cable Telecommunications Engineers) messages with built-in CRC validation. SCTE-35 is a standard for inserting cue messages into video streams, commonly used for ad insertion points in broadcast television.\n\n## Features\n\n- **Builder Pattern API** - Type-safe builder pattern for creating SCTE-35 messages from scratch with validation\n- **Serde support** - Serialize/deserialize SCTE-35 messages to/from JSON and other formats (enabled by default)\n- **CRC validation** - Built-in CRC-32 validation using MPEG-2 algorithm (enabled by default)\n- **Human-readable UPID parsing** - Full support for 18 standard UPID types with intelligent formatting\n- **Human-readable segmentation types** - Complete set of 48 standard segmentation types with descriptive names\n- **Segmentation descriptor parsing** - Complete parsing of segmentation descriptors including UPID data\n- **Minimal dependencies** - Only the `crc` crate for validation (optional) and `serde` for serialization (optional)\n- **Full SCTE-35 parsing** - Supports all major SCTE-35 command types\n- **Bit-level precision** - Accurate parsing of bit-packed SCTE-35 messages\n- **Optional CLI tool** - Command-line interface for parsing base64-encoded messages with text and JSON output formats\n- **Type-safe** - Strongly typed representations of all SCTE-35 structures\n- **Data integrity** - Detects corrupted or tampered SCTE-35 messages\n\n## Installation\n\n### With All Features (Default)\n\nAdd this to your `Cargo.toml`:\n\n```toml\n[dependencies]\nscte35 = \"0.2.0\"\n```\n\nThis includes both CRC validation and serde support.\n\n### Without Serde Support\n\nIf you don't need JSON serialization:\n\n```toml\n[dependencies]\nscte35 = { version = \"0.2.0\", default-features = false, features = [\"crc-validation\"] }\n```\n\n### Minimal (No CRC or Serde)\n\nFor a minimal library without CRC validation or serde:\n\n```toml\n[dependencies]\nscte35 = { version = \"0.2.0\", default-features = false }\n```\n\n### With CLI Tool (Automatically includes CRC validation)\n\nTo include the command-line tool, enable the `cli` feature:\n\n```toml\n[dependencies]\nscte35 = { version = \"0.2.0\", features = [\"cli\"] }\n```\n\nOr install the CLI tool directly:\n\n```bash\ncargo install scte35 --features cli\n```\n\n**Note**: The CLI feature automatically enables CRC validation to provide complete message diagnostics.\n\n## Usage\n\n### Library Usage\n\n```rust\nuse scte35::{SpliceCommand, SpliceDescriptor};\nuse std::time::Duration;\n\n// Your SCTE-35 message as bytes (example message)\nlet scte35_bytes = vec![\n    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, \n    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4\n];\n\nmatch scte35::parse(\u0026scte35_bytes) {\nOk(section) =\u003e {\n    println!(\"Table ID: {}\", section.table_id);\n    println!(\"Command Type: {}\", section.splice_command_type);\n    \n    match section.splice_command {\n        SpliceCommand::SpliceInsert(insert) =\u003e {\n            println!(\"Splice Event ID: 0x{:08x}\", insert.splice_event_id);\n            \n            // Convert break duration to std::time::Duration\n            if let Some(break_duration) = \u0026insert.break_duration {\n                let duration: Duration = break_duration.into();\n                println!(\"Break Duration: {:?}\", duration);\n                println!(\"Break Duration: {:.3} seconds\", duration.as_secs_f64());\n            }\n            \n            // Convert splice time to Duration\n            if let Some(duration) = insert.splice_time.as_ref()\n                .and_then(|st| st.to_duration()) {\n                println!(\"Splice Time: {:?}\", duration);\n            }\n        }\n        SpliceCommand::TimeSignal(signal) =\u003e {\n            if let Some(duration) = signal.splice_time.to_duration() {\n                println!(\"Time Signal: {:?}\", duration);\n            }\n        }\n        _ =\u003e println!(\"Other command type\"),\n    }\n    \n    // Parse segmentation descriptors with UPID information\n    for descriptor in \u0026section.splice_descriptors {\n        if let SpliceDescriptor::Segmentation(seg_desc) = descriptor {\n            println!(\"Segmentation Event ID: 0x{:08x}\", seg_desc.segmentation_event_id);\n            println!(\"UPID Type: {}\", seg_desc.upid_type_description());\n            println!(\"Segmentation Type: {}\", seg_desc.segmentation_type_description());\n            \n            if let Some(upid_str) = seg_desc.upid_as_string() {\n                println!(\"UPID: {}\", upid_str);\n            }\n        }\n    }\n}\nErr(e) =\u003e eprintln!(\"Error parsing SCTE-35: {}\", e),\n}\n```\n\n### CRC Validation\n\nBy default, the library validates CRC-32 checksums in SCTE-35 messages to ensure data integrity:\n\n```rust\nuse scte35::parse_splice_info_section;\n\n// Example SCTE-35 message bytes\nlet scte35_bytes = vec![\n    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, \n    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4\n];\n\n// Parse with automatic CRC validation (default behavior)\nmatch parse_splice_info_section(\u0026scte35_bytes) {\nOk(section) =\u003e {\n    println!(\"Valid SCTE-35 message parsed successfully\");\n    #[cfg(feature = \"crc-validation\")]\n    {\n        use scte35::CrcValidatable;\n        println!(\"CRC-32: 0x{:08X}\", section.get_crc());\n    }\n}\nErr(e) =\u003e {\n    if e.to_string().contains(\"CRC validation failed\") {\n        eprintln!(\"Message corrupted or tampered: {}\", e);\n    } else {\n        eprintln!(\"Parse error: {}\", e);\n    }\n}\n}\n\n#[cfg(feature = \"crc-validation\")]\n{\n    use scte35::{validate_scte35_crc, CrcValidatable};\n    \n    // Validate CRC independently\n    match validate_scte35_crc(\u0026scte35_bytes) {\n        Ok(true) =\u003e println!(\"CRC validation passed\"),\n        Ok(false) =\u003e println!(\"CRC validation failed or not available\"),\n        Err(e) =\u003e eprintln!(\"Validation error: {}\", e),\n    }\n\n    // Validate using the parsed section\n    if let Ok(section) = parse_splice_info_section(\u0026scte35_bytes) {\n        match section.validate_crc(\u0026scte35_bytes) {\n            Ok(true) =\u003e println!(\"Message integrity verified\"),\n            Ok(false) =\u003e println!(\"Message integrity check failed\"),\n            Err(e) =\u003e eprintln!(\"Validation error: {}\", e),\n        }\n    }\n}\n```\n\n### Duration Conversion\n\nSCTE-35 time values are represented as 90kHz clock ticks. This library provides convenient conversion to Rust's `std::time::Duration`:\n\n```rust\nuse scte35::BreakDuration;\nuse std::time::Duration;\n\n// Create a break duration of 30 seconds (30 * 90000 ticks)\nlet break_duration = BreakDuration {\n    auto_return: 1,\n    reserved: 0,\n    duration: 2_700_000,\n};\n\n// Convert using Into trait  \nlet duration: Duration = (\u0026break_duration).into();\nassert_eq!(duration.as_secs(), 30);\n\n// Or use the method directly\nlet duration2 = break_duration.to_duration();\nassert_eq!(duration2.as_secs(), 30);\n```\n\n### Serde Support (JSON Serialization)\n\nThe library includes built-in serde support for serializing/deserializing SCTE-35 messages:\n\n```rust\nuse scte35::parse_splice_info_section;\n\n// Parse SCTE-35 message\nlet scte35_bytes = vec![\n    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, \n    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4\n];\n\nif let Ok(section) = parse_splice_info_section(\u0026scte35_bytes) {\n    #[cfg(feature = \"serde\")]\n    {\n        use serde_json;\n        \n        // Serialize to JSON\n        let json = serde_json::to_string_pretty(\u0026section).unwrap();\n        println!(\"{}\", json);\n        \n        // Deserialize from JSON\n        let deserialized: scte35::SpliceInfoSection = \n            serde_json::from_str(\u0026json).unwrap();\n        assert_eq!(section, deserialized);\n    }\n}\n```\n\nThe serde implementation includes:\n\n- **Binary data as base64**: All raw bytes (private commands, UPID data, alignment bits) are encoded as base64 strings\n- **Human-readable enums**: Segmentation types and UPID types include both numeric values and descriptions\n- **Time duration info**: PTS times and durations include both raw ticks and human-readable formats\n- **Computed fields**: Segmentation descriptors include parsed UPID strings when available\n\nExample JSON output:\n```json\n{\n  \"table_id\": 252,\n  \"section_syntax_indicator\": 0,\n  \"private_indicator\": 0,\n  \"section_length\": 22,\n  \"protocol_version\": 0,\n  \"encrypted_packet\": 0,\n  \"encryption_algorithm\": 0,\n  \"pts_adjustment\": 0,\n  \"cw_index\": 255,\n  \"tier\": 4095,\n  \"splice_command_length\": 5,\n  \"splice_command_type\": 6,\n  \"splice_command\": {\n    \"type\": \"TimeSignal\",\n    \"splice_time\": {\n      \"time_specified_flag\": 1,\n      \"pts_time\": 900000,\n      \"duration_info\": {\n        \"ticks\": 900000,\n        \"seconds\": 10.0,\n        \"human_readable\": \"10.0s\"\n      }\n    }\n  },\n  \"descriptor_loop_length\": 0,\n  \"splice_descriptors\": [],\n  \"alignment_stuffing_bits\": \"\",\n  \"e_crc_32\": null,\n  \"crc_32\": 0\n}\n```\n\n### Segmentation Types\n\nThe library provides human-readable segmentation types that correspond to the numeric IDs in SCTE-35 messages:\n\n```rust\nuse scte35::{SegmentationType, parse_splice_info_section, SpliceDescriptor};\n\n// Work with segmentation types directly\nlet seg_type = SegmentationType::ProviderAdvertisementStart;\nprintln!(\"Type: {} (ID: 0x{:02X})\", seg_type, seg_type.id());\n\n// Convert from numeric ID (useful when parsing)\nlet seg_type = SegmentationType::from_id(0x30);\nassert_eq!(seg_type, SegmentationType::ProviderAdvertisementStart);\nassert_eq!(seg_type.to_string(), \"Provider Advertisement Start\");\n\n// Example: Parse a message and check segmentation descriptors\nlet scte35_bytes = vec![\n    0xFC, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x05, 0x06, 0xFE, \n    0x42, 0x3A, 0x35, 0xBD, 0x00, 0x00, 0xBB, 0x0C, 0x73, 0xF4\n];\n\nif let Ok(section) = parse_splice_info_section(\u0026scte35_bytes) {\n    // Segmentation descriptors automatically populate both fields\n    // The numeric ID and human-readable type are always consistent\n    for descriptor in \u0026section.splice_descriptors {\n        if let SpliceDescriptor::Segmentation(seg_desc) = descriptor {\n            println!(\"Segmentation Type ID: 0x{:02X}\", seg_desc.segmentation_type_id);\n            println!(\"Segmentation Type: {:?}\", seg_desc.segmentation_type);\n            println!(\"Description: {}\", seg_desc.segmentation_type_description());\n        }\n    }\n}\n```\n\n#### Supported Segmentation Types\n\nThe library supports all standard SCTE-35 segmentation types including:\n\n**Program Boundaries:**\n- Program Start/End\n- Program Early Termination\n- Program Breakaway/Resumption\n- Program Runover (Planned/Unplanned)\n- Program Overlap Start\n- Program Blackout Override\n- Program Join\n\n**Content Segments:**\n- Chapter Start/End\n- Break Start/End\n- Content Identification\n\n**Advertisement Opportunities:**\n- Provider/Distributor Advertisement Start/End\n- Provider/Distributor Placement Opportunity Start/End\n- Provider/Distributor Overlay Placement Opportunity Start/End\n- Provider/Distributor Promo Start/End\n- Provider/Distributor Ad Block Start/End\n\n**Special Events:**\n- Unscheduled Event Start/End\n- Alternate Content Opportunity Start/End\n- Network Start/End\n\n### Builder Pattern API (Creating SCTE-35 Messages)\n\nThe library includes a comprehensive builder pattern API for creating SCTE-35 messages from scratch with type safety and validation:\n\n```rust\n# use scte35::builders::*;\n# use scte35::types::SegmentationType;\n# use std::time::Duration;\n# fn main() -\u003e BuilderResult\u003c()\u003e {\n// Example 1: Creating a 30-second ad break starting at 20 seconds\nlet splice_insert = SpliceInsertBuilder::new(12345)\n    .at_pts(Duration::from_secs(20))?\n    .duration(Duration::from_secs(30))\n    .unique_program_id(0x1234)\n    .avail(1, 4)  // First of 4 avails\n    .build()?;\n\nlet section = SpliceInfoSectionBuilder::new()\n    .pts_adjustment(0)\n    .splice_insert(splice_insert)\n    .build()?;\n\nprintln!(\"Created SCTE-35 message with {} byte payload\", section.section_length);\n# Ok(())\n# }\n```\n\n#### Creating Time Signals with Segmentation Descriptors\n\n```rust\n# use scte35::builders::*;\n# use scte35::types::SegmentationType;\n# use std::time::Duration;\n# fn example() -\u003e BuilderResult\u003c()\u003e {\n// Example 2: Program start boundary with UPID\nlet segmentation = SegmentationDescriptorBuilder::new(\n        5678, \n        SegmentationType::ProgramStart\n    )\n    .upid(Upid::AdId(\"ABC123456789\".to_string()))?\n    .duration(Duration::from_secs(1800))?  // 30-minute program\n    .build()?;\n\nlet section = SpliceInfoSectionBuilder::new()\n    .time_signal(TimeSignalBuilder::new().immediate().build()?)\n    .add_segmentation_descriptor(segmentation)\n    .build()?;\n# Ok(())\n# }\n```\n\n#### Component-Level Splice Operations\n\n```rust\n# use scte35::builders::*;\n# use std::time::Duration;\n# fn example() -\u003e BuilderResult\u003c()\u003e {\n// Example 3: Component-level splice for specific audio/video streams\nlet splice_insert = SpliceInsertBuilder::new(3333)\n    .component_splice(vec![\n        (0x01, Some(Duration::from_secs(10))),  // Video component\n        (0x02, Some(Duration::from_secs(10))),  // Audio component 1\n        (0x03, Some(Duration::from_secs(10))),  // Audio component 2\n    ])?\n    .duration(Duration::from_secs(15))\n    .build()?;\n# Ok(())\n# }\n```\n\n#### Advanced Segmentation with Delivery Restrictions\n\n```rust\n# use scte35::builders::*;\n# use scte35::types::SegmentationType;\n# fn example() -\u003e BuilderResult\u003c()\u003e {\n// Example 4: Complex segmentation with delivery restrictions\nlet restrictions = DeliveryRestrictions {\n    web_delivery_allowed: false,\n    no_regional_blackout: false,\n    archive_allowed: true,\n    device_restrictions: DeviceRestrictions::RestrictGroup1,\n};\n\nlet uuid_bytes = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,\n                 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0];\n\nlet segmentation = SegmentationDescriptorBuilder::new(\n        7777,\n        SegmentationType::DistributorAdvertisementStart\n    )\n    .delivery_restrictions(restrictions)\n    .upid(Upid::Uuid(uuid_bytes))?\n    .segment(2, 6)  // 2nd of 6 segments\n    .build()?;\n# Ok(())\n# }\n```\n\n#### Comprehensive UPID Support\n\nThe builder API supports all SCTE-35 UPID types with validation:\n\n```rust\n# use scte35::builders::*;\n# fn example() -\u003e BuilderResult\u003c()\u003e {\n# let mut builder = SegmentationDescriptorBuilder::new(1, scte35::types::SegmentationType::ProgramStart);\n// Ad ID (12 ASCII characters)\nbuilder = builder.upid(Upid::AdId(\"ABC123456789\".to_string()))?;\n\n// UUID (16 bytes)\nlet uuid_bytes = [0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,\n                 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0];\nbuilder = builder.upid(Upid::Uuid(uuid_bytes))?;\n\n// URI (variable length)\nbuilder = builder.upid(Upid::Uri(\"https://example.com/content/123\".to_string()))?;\n\n// ISAN (12 bytes)\nlet isan_bytes = [0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23];\nbuilder = builder.upid(Upid::Isan(isan_bytes))?;\n\n// And many more: UMID, EIDR, TID, AiringID, etc.\n# Ok(())\n# }\n```\n\n#### Error Handling and Validation\n\nThe builder API provides comprehensive validation with clear error messages:\n\n```rust\n# use scte35::builders::*;\n# use scte35::types::SegmentationType;\n# use std::time::Duration;\n# fn example() -\u003e BuilderResult\u003c()\u003e {\n// Invalid UPID length\nlet result = SegmentationDescriptorBuilder::new(1234, SegmentationType::ProgramStart)\n    .upid(Upid::AdId(\"TOO_SHORT\".to_string()));\n\nmatch result {\n    Err(BuilderError::InvalidUpidLength { expected, actual }) =\u003e {\n        println!(\"UPID validation failed: expected {} chars, got {}\", expected, actual);\n    }\n    _ =\u003e {}\n}\n\n// Duration too large for 33-bit PTS\nlet result = SpliceInsertBuilder::new(1234)\n    .at_pts(Duration::from_secs(u64::MAX / 90_000 + 1))?\n    .build();\n\nmatch result {\n    Err(BuilderError::DurationTooLarge { field, duration }) =\u003e {\n        println!(\"Duration {} is too large for field {}\", duration.as_secs(), field);\n    }\n    _ =\u003e {}\n}\n# Ok(())\n# }\n```\n\n#### Builder Features\n\n- **Type Safety**: Compile-time prevention of invalid message states\n- **Validation**: Runtime validation with descriptive error messages  \n- **Ergonomic API**: Fluent interface with sensible defaults\n- **Spec Compliance**: Automatic handling of reserved fields and constraints\n- **Complete Coverage**: Builders for all major SCTE-35 structures\n\nSee the [builder_demo example](examples/builder_demo.rs) for more comprehensive usage examples.\n\n### CLI Usage\n\nWhen built with the `cli` feature, you can parse base64-encoded SCTE-35 messages with multiple output formats:\n\n```bash\n# Text output (default)\ncargo run --features cli -- \"/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=\"\n\n# JSON output\ncargo run --features cli -- -o json \"/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=\"\n\n# Or with long flag\ncargo run --features cli -- --output json \"/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=\"\n\n# Get help\ncargo run --features cli -- --help\n```\n\nExample output with splice insert command and break duration:\n```text\nSuccessfully parsed SpliceInfoSection:\n  Table ID: 252\n  Section Length: 47\n  Protocol Version: 0\n  Splice Command Type: 5\n  Splice Command Length: 20\n  Splice Command: SpliceInsert\n    Splice Event ID: 0x4800008f\n    Splice Event Cancel: 0\n    Out of Network: 1\n    Program Splice Flag: 1\n    Duration Flag: 1\n    Splice Immediate Flag: 0\n    Splice Time PTS: 0x07369c02e\n    Splice Time: 21514.559089 seconds\n    Break Duration:\n      Auto Return: 1\n      Duration: 0x00052ccf5 (60.293567 seconds)\n    Unique Program ID: 0\n    Avail Num: 0\n    Avails Expected: 0\n  Descriptor Loop Length: 10\n  Number of Descriptors: 1\n    Unknown Descriptor:\n      Tag: 0x00\n      Length: 8\n      Content: \"CUEI  5\"\n  CRC-32: 0x62DBA30A ✓ (Valid)\n```\n\n#### CLI Output Formats\n\nThe CLI supports two output formats:\n\n- **Text format** (default): Human-readable format with detailed field descriptions\n- **JSON format**: Structured JSON output for programmatic use\n\nJSON output includes the complete parsed structure with CRC validation results:\n\n```bash\ncargo run --features cli -- -o json \"/DAvAAAAAAAA///wFAVIAACPf+/+c2nALv4AUsz1AAAAAAAKAAhDVUVJAAABNWLbowo=\"\n```\n\n```json\n{\n  \"status\": \"success\",\n  \"data\": {\n    \"table_id\": 252,\n    \"section_length\": 47,\n    \"protocol_version\": 0,\n    \"splice_command_type\": 5,\n    \"splice_command_length\": 20,\n    \"splice_command\": {\n      \"type\": \"SpliceInsert\",\n      \"splice_event_id\": 1207959695,\n      \"splice_event_cancel_indicator\": 0,\n      \"out_of_network_indicator\": 1,\n      \"program_splice_flag\": 1,\n      \"duration_flag\": 1,\n      \"splice_immediate_flag\": 0,\n      \"splice_time\": {\n        \"time_specified_flag\": 1,\n        \"pts_time\": 1936310318,\n        \"duration_info\": {\n          \"ticks\": 1936310318,\n          \"seconds\": 21514.559088888887,\n          \"human_readable\": \"5h 58m 34.6s\"\n        }\n      },\n      \"break_duration\": {\n        \"auto_return\": 1,\n        \"duration\": 5426421,\n        \"duration_info\": {\n          \"ticks\": 5426421,\n          \"seconds\": 60.29356666666666,\n          \"human_readable\": \"1m 0.3s\"\n        }\n      },\n      \"unique_program_id\": 0,\n      \"avail_num\": 0,\n      \"avails_expected\": 0\n    },\n    \"descriptor_loop_length\": 10,\n    \"splice_descriptors\": [\n      {\n        \"descriptor_type\": \"Unknown\",\n        \"tag\": 0,\n        \"length\": 8,\n        \"data\": \"Q1VFSQAAATU=\"\n      }\n    ],\n    \"crc_32\": 1658561290\n  },\n  \"crc_validation\": {\n    \"valid\": true,\n    \"error\": null\n  }\n}\n```\n\n## Supported SCTE-35 Commands\n\n- **SpliceNull** - Null command\n- **SpliceSchedule** - Scheduled splice events\n- **SpliceInsert** - Immediate or scheduled ad insertion points\n- **TimeSignal** - Time synchronization signals\n- **BandwidthReservation** - Bandwidth allocation commands\n- **PrivateCommand** - Private/custom commands\n\n## CRC Validation\n\nBy default, the library validates CRC-32 checksums in SCTE-35 messages to ensure data integrity. This feature can be disabled if needed:\n\n### With CRC Validation (Default)\n```toml\n[dependencies]\nscte35 = \"0.2.0\"\n```\n\n### Without CRC Validation (Library only)\n```toml\n[dependencies]\nscte35 = { version = \"0.2.0\", default-features = false }\n```\n\n### With CLI Tool (Automatically includes CRC validation)\n```toml\n[dependencies]\nscte35 = { version = \"0.2.0\", features = [\"cli\"] }\n```\n\n**Note**: The CLI feature automatically enables CRC validation to provide complete message diagnostics.\n\n### Benefits of CRC Validation\n\n1. **Data Integrity**: Ensures SCTE-35 messages haven't been corrupted during transmission\n2. **Security**: Helps detect tampered messages\n3. **Debugging**: Identifies parsing issues vs. data corruption\n4. **Standards Compliance**: Follows SCTE-35 specification requirements\n5. **Flexibility**: Optional feature allows users to choose performance vs. validation trade-offs\n\n## API Documentation\n\nFull API documentation is available at [docs.rs](https://docs.rs/scte35) or can be generated locally:\n\n```bash\ncargo doc --no-deps --open\n```\n\n### Main Functions\n\n#### `parse(buffer: \u0026[u8]) -\u003e Result\u003cSpliceInfoSection, io::Error\u003e`\n\nConvenient alias for parsing SCTE-35 messages. This is the recommended function for most use cases, providing a clean and ergonomic API.\n\n```rust\n# use scte35;\n# fn main() -\u003e Result\u003c(), Box\u003cdyn std::error::Error\u003e\u003e {\n# #[cfg(feature = \"cli\")]\n# {\n#     use data_encoding::BASE64;\n#     let base64_message = \"/DAWAAAAAAAAAP/wBQb+Qjo1vQAAuwxz9A==\";\n#     let buffer = BASE64.decode(base64_message.as_bytes())?;\n#     let section = scte35::parse(\u0026buffer)?;\n# }\n#\n# // For doctests without the cli feature, use a direct byte array\n# let buffer = vec![\n#     0xfc, 0x30, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf0,\n#     0x05, 0x06, 0xfe, 0x42, 0x3a, 0x35, 0xbd, 0x00, 0x00, 0xbb, 0x0c, 0x73,\n#     0xf4\n# ];\nlet section = scte35::parse(\u0026buffer)?;\n# Ok(())\n# }\n```\n\n#### `parse_splice_info_section(buffer: \u0026[u8]) -\u003e Result\u003cSpliceInfoSection, io::Error\u003e`\n\nParses a complete SCTE-35 splice information section from a byte buffer. Automatically validates CRC-32 when the `crc-validation` feature is enabled. The original function behind `parse`.\n\n#### `validate_scte35_crc(buffer: \u0026[u8]) -\u003e Result\u003cbool, io::Error\u003e`\n\nValidates the CRC-32 checksum of an SCTE-35 message independently. Returns `Ok(true)` if valid, `Ok(false)` if invalid or CRC validation is disabled.\n\n### Data Structures\n\n#### `SpliceInfoSection`\nThe top-level structure containing all SCTE-35 message fields:\n- `table_id`: Table identifier (should be 0xFC for SCTE-35)\n- `section_length`: Length of the section\n- `protocol_version`: SCTE-35 protocol version\n- `splice_command_type`: Type of splice command\n- `splice_command`: The actual command data (enum)\n- `descriptor_loop_length`: Length of descriptors\n- `splice_descriptors`: List of splice descriptors\n- `crc_32`: CRC32 checksum\n\n#### `SpliceCommand`\nAn enum representing different SCTE-35 command types:\n- `SpliceNull`\n- `SpliceSchedule(SpliceSchedule)`\n- `SpliceInsert(SpliceInsert)`\n- `TimeSignal(TimeSignal)`\n- `BandwidthReservation(BandwidthReservation)`\n- `PrivateCommand(PrivateCommand)`\n- `Unknown`\n\n## Building from Source\n\n### Build Library Only\n```bash\ngit clone https://github.com/yourusername/scte35\ncd scte35\ncargo build --release\n```\n\n### Build with CLI Tool\n```bash\ncargo build --release --features cli\n```\n\n### Run Tests\n```bash\ncargo test\n```\n\n## License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## References\n\n- [SCTE-35 2023r1 Specification](https://www.scte.org/standards/)\n- [Digital Program Insertion Cueing Message](https://en.wikipedia.org/wiki/SCTE-35)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelcaricio%2Fscte35","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafaelcaricio%2Fscte35","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafaelcaricio%2Fscte35/lists"}