Technical

Automating Your Closed Caption Workflows Part 2

Closed Caption Segmentation & Conform 

By: Tim Taylor

Last Updated: September 16, 2025

This is the second article in our three-part series on automating closed caption workflows. In Part 1, we covered creating clean JSON profiles. Now we'll tackle one of the most powerful features of Closed Caption Converter: conforming segment timings to match your target delivery specifications.

TLDR:

  • Manifest data is essential for accurate segment timing—avoid manual timing entry when possible
  • Linear segment definition makes configuration straightforward (no complex calculations)
  • Two segment types handle all scenarios: "file" for content, "black" for breaks
  • CLI and API use identical segment arrays—easy to switch between local and cloud processing
  • Automation-friendly workflow scales from single conversions to enterprise batch processing

Understanding Segment Timing Conforming

When working with professional video content, your source captions rarely align perfectly with your final delivery timeline. Consider these common scenarios:

  • Source: Broadcast SCC file with 1-hour timecode base, matching original program timing
  • Target: Web delivery requiring WebVTT starting at 00:00:00, with specific segment break durations

Segment timing conforming allows you to extract caption data from specific time ranges in your source file and reorganize them to match your target video asset's timeline. This is essential for:

  • Multi-segment programs (shows with commercial breaks, multi-part content)
  • Timeline restructuring (removing or adjusting break durations)
  • Format delivery requirements (client specifications for segment break timing)

Real-World Example: Broadcast to Web Conversion

Let's walk through a practical scenario that demonstrates the power and precision of segment timing control.

Source Asset Specifications
  • Format: SCC (Scenarist Closed Caption format)
  • Timecode Base: 01:00:00;00 (1-hour offset, common in broadcast)
  • Frame Rate: 29.97fps Drop Frame (DF)
  • Structure: 3 content segments with 2 commercial breaks
  • Timeline: Conforms to original broadcast video/audio asset
Target Delivery Requirements
  • Format: WebVTT (web standard)
  • Timecode Base: 00:00:00;00 (starting at zero)
  • Structure: Same 3 content segments
  • Segment Breaks: Exactly 5 frames duration (per client specification)

Note: The original duration of segment breaks is irrelevant—we extract caption data from content segments and insert new break timings to match the target video asset.

Working with Manifest Data

The key to accurate segment timing is having reliable source data. This typically comes from:

  • Manifest files (JSON/XML with precise timing data)
  • EDL files (Edit Decision Lists from video editing systems)
  • Media metadata (extracted from video analysis tools)
Sample Manifest Data

Here's what typical manifest data looks like for our three segments:


{
  "interval": {
    "inclusive": true,
    "dropFrame": true,
    "startFrames": 107892.0,
    "startTimecode": "01:00:00;00",
    "startSeconds": 3599.9964,
    "endTimecode": "01:12:07;27", 
    "durationFrames": 21816.0,
    "durationTimecode": "00:12:07;28",
    "durationSeconds": 727.9272,
    "durationTime": "00:12:07.927"
  }
},
{
  "interval": {
    "inclusive": true,
    "dropFrame": true,
    "startFrames": 129858.0,
    "startTimecode": "01:12:12;28",
    "startSeconds": 4332.9286,
    "endTimecode": "01:20:05;21",
    "durationFrames": 14170.0,
    "durationTimecode": "00:07:52;24",
    "durationSeconds": 472.805667,
    "durationTime": "00:07:52.806"
  }
},
{
  "interval": {
    "inclusive": true,
    "dropFrame": true,
    "startFrames": 144179.0,
    "startTimecode": "01:20:10;23",
    "startSeconds": 4810.772633,
    "endTimecode": "01:28:08;02",
    "durationFrames": 14304.0,
    "durationTimecode": "00:07:57;08",
    "durationSeconds": 477.2768,
    "durationTime": "00:07:57.277"
  }
}

Key Data Points for Caption Processing

From each segment's manifest data, we need:

  • startTimecode: Where to begin extracting captions
  • endTimecode: Where to stop extracting captions
  • durationTimecode: Length of content (optional but helpful for validation)
Understanding Segment Types

Closed Caption Converter defines segments using two distinct types:

1. "file" Segments (Active Content)
  • Contains actual caption/subtitle data
  • Extracted from specific timecode ranges in source file
  • Represents video content with dialogue, sound effects, etc.
2. Commercial "black" Segments (Breaks)
  • Inserts silent/mute periods between content segments
  • Represents commercial breaks, scene transitions, etc.
  • Duration controlled by delivery specifications

Building the Segment Configuration

The beauty of this approach is its simplicity—no complex calculations required. We extract timing data directly from the manifest and structure it for CCC.

Step 1: Create File Segments

For each content segment, we create a "file" entry:


"segments": [
  {
    "duration": "00:12:07;28",
    "endTime": "01:12:07;27", 
    "source": "file",
    "startTime": "01:00:00;00"
  },
  // ... additional segments
]

Step 2: Insert Black Segments

Between each content segment, we add "black" entries with our target duration (5 frames):


{
  "duration": "00:00:00;05",
  "endTime": "00:00:00;05",
  "source": "black", 
  "startTime": "00:00:00;01"
}

Step 3: Complete Segment Array

Here's our full segment configuration following the linear timeline:


"segments": [
  {
    "duration": "00:12:07;28",
    "endTime": "01:12:07;27",
    "source": "file",
    "startTime": "01:00:00;00"
  },
  {
    "duration": "00:00:00;05", 
    "endTime": "00:00:00;05",
    "source": "black",
    "startTime": "00:00:00;01"
  },
  {
    "duration": "00:07:52;24",
    "endTime": "01:20:05;21", 
    "source": "file",
    "startTime": "01:12:12;28"
  },
  {
    "duration": "00:00:00;05",
    "endTime": "00:00:00;05", 
    "source": "black",
    "startTime": "00:00:00;01"
  },
  {
    "duration": "00:07:57;08",
    "endTime": "01:28:08;02",
    "source": "file", 
    "startTime": "01:20:10;23"
  }
]

Complete JSON Configuration

Integrating our segment timing into the full CCC profile:

CLI Version (cli_test.json)

{
  "source_frameRate": 29.97,
  "target_frameRate": 29.97,
  "incode": "auto",
  "automatic_offset": true,
  "segments": [
    {
      "duration": "00:12:07;28",
      "durationSeconds": 727.9272,
      "endTime": "01:12:07;27",
      "source": "file",
      "startTime": "01:00:00;00"
    },
    {
      "duration": "00:00:00;05",
      "endTime": "00:00:00;05",
      "order": 2,
      "source": "black",
      "startTime": "00:00:00;01"
    },
    {
      "duration": "00:07:52;24", 
      "durationSeconds": 472.805667,
      "endTime": "01:20:05;21",
      "source": "file",
      "startTime": "01:12:12;28"
    },
    {
      "duration": "00:00:00;05",
      "endTime": "00:00:00;05",
      "order": 4,
      "source": "black", 
      "startTime": "00:00:00;01"
    },
    {
      "duration": "00:07:57;08",
      "durationSeconds": 477.2768,
      "endTime": "01:28:08;02",
      "source": "file",
      "startTime": "01:20:10;23"
    }
  ],
  "encoding_options": [
    {"name": "Encode Position", "selected": true},
    {"name": "Encode Formatting", "selected": true}, 
    {"name": "Encode Font Styles", "selected": false}
  ],
  "source_profile": "scenerist",
  "target_profile": "webVtt",
  "source": "TimSource.scc",
  "target": "TimTarget.vtt"
}

API Version

For API submission, simply remove the source and target filename references:


{
  "source_frameRate": 29.97,
  "target_frameRate": 29.97,
  "incode": "auto",
  "automatic_offset": true,
  "segments": [
    // ... same segments array as above
  ],
  "encoding_options": [
    {"name": "Encode Position", "selected": true},
    {"name": "Encode Formatting", "selected": true},
    {"name": "Encode Font Styles", "selected": false}
  ],
  "source_profile": "scenerist", 
  "target_profile": "webVtt"
}

Scaling for Complex Content

Handling More Segments

Need to process longer content with more segments? The pattern scales easily:

  1. Extract timing data from your manifest/EDL for each content segment
  2. Add file entries for each content segment using manifest timings
  3. Insert black entries between content segments with your target duration
  4. Maintain linear order from first to last segment
Automation Opportunities

This workflow is ideal for automation:


# Pseudo-code for automated segment processing
def create_segments_from_manifest(manifest_data, break_duration="00:00:00;05"):
    segments = []
    
    for i, segment in enumerate(manifest_data):
        # Add content segment
        segments.append({
            "duration": segment["durationTimecode"],
            "endTime": segment["endTimecode"], 
            "source": "file",
            "startTime": segment["startTimecode"]
        })
        
        # Add break segment (except after last segment)
        if i < len(manifest_data) - 1:
            segments.append({
                "duration": break_duration,
                "endTime": break_duration,
                "source": "black",
                "startTime": "00:00:00;01"
            })
    
    return segments

Best Practices and Troubleshooting

Data Validation
  • Verify timecode format matches your source file (DF vs. NDF)
  • Check frame rates between source, manifest, and target specifications
  • Validate segment continuity to avoid timing gaps or overlaps
Testing Strategy
  1. Start with CLI for rapid iteration and debugging
  2. Test single segments first before processing complete timeline
  3. Verify output timing against target video asset
  4. Validate caption content appears at correct timestamps
Common Issues and Solutions

Problem: Captions appear at wrong timestamps in output
Solution: Verify automatic_offset and incode settings match your requirements

Problem: Missing captions in certain segments
Solution: Check that segment start/end times precisely match caption data availability

Problem: Incorrect break durations in final output
Solution: Verify black segment durations match delivery specifications

GUI Alternative Comparison

While you can achieve the same results using the CCC web interface, the manual approach requires:

  • Multiple form entries for each segment
  • Prone to human error in timing entry
  • Generates verbose, hard-to-maintain JSON
  • Difficult to version control or automate

The programmatic approach we've outlined offers:

  • Precision: Direct copy-paste from manifest data
  • Maintainability: Clean, readable configurations
  • Scalability: Easy automation for batch processing

What's Next

In our final article of this series, we'll dive deep into advanced Postman techniques for CCC API integration, covering batch processing strategies, error handling, and building robust production workflows.

With segment timing mastery under your belt, you're ready to tackle complex, multi-segment caption conversion projects with frame-accurate precision. The combination of clean JSON profiles and precise segment timing gives you the foundation for professional-grade caption workflow automation.


Resources

Blog Article

Automating Your Closed Caption Workflows | Part 1

Read Now
Blog Article

Automating Your Closed Caption Workflows | Part 3

Read Now
Solution

Closed Caption Converter API

Learn More
Free Trial

Free 7 Day Trial of Closed Caption Creator

Sign Up Now