CLI
The Closed Caption Converter CLI brings the full power of the conversion engine to your command line. It runs entirely on your local machine as a single self-contained binary with no external dependencies — no runtime installations, no package managers, no library conflicts. Deploy it once and it works. When you need to upgrade, you replace a single file.
The CLI is available for macOS, Windows, and Linux, and is designed for environments where sending files to a cloud API is not possible or desirable: air-gapped networks, serverless deployments, on-premise infrastructure, or any facility that requires caption processing to happen within the security perimeter.
Installation
Download the CLI binary for your platform from the Closed Caption Converter website or from the distribution link supplied with your account.
The CLI is distributed as a single executable file:
| Platform | Binary Name |
|---|---|
| macOS (Apple Silicon) | ccconverter |
| macOS (Intel) | ccconverter |
| Windows | ccconverter.exe |
| Linux | ccconverter |
On macOS and Linux, make the binary executable after downloading:
chmod +x ccconverter
You may optionally move it to a directory on your PATH (for example /usr/local/bin/) to run it from anywhere:
mv ccconverter /usr/local/bin/ccconverter
On Windows, place the .exe in a directory on your PATH or reference it by full path in your scripts.
Some antivirus and endpoint protection tools perform aggressive real-time scanning on newly downloaded executables. If the CLI is blocked, moved, or quarantined immediately after download, whitelist the executable in your security software before troubleshooting further.
Activation
The CLI requires a valid license file to run. Place the license file in the same directory as the binary. Contact sales and support to obtain a license key.
Running Your First Conversion
The CLI accepts a Job Description JSON file as its primary input via the --config flag. This is the same JSON format used by the API, making it easy to develop and test job configurations in the web application and then run them locally.
Source, target, and most conversion options can be specified either as command-line flags or as properties in the config JSON. The examples below use flags for clarity.
ccconverter \
--source input.srt \
--target output.stl \
--config job.json
Where job.json contains a standard Job Description:
{
"job_type": "convert",
"source_profile": "SubRip Video Subtitle Script",
"target_profile": "EBU STL",
"default_frameRate": 25,
"encoding_options": [
{ "name": "Language Code", "selected": "English" },
{ "name": "Country of Origin", "selected": "United Kingdom" }
]
}
When the source and target paths are embedded in the config JSON, no extra flags are needed:
ccconverter --config job.json
{
"job_type": "convert",
"source": "/captions/input.srt",
"target": "/captions/output.stl",
"source_profile": "SubRip Video Subtitle Script",
"target_profile": "EBU STL"
}
CLI Flags
All flags can also be set as properties in the config JSON file. Run ccconverter --help at any time to see the full list of flags along with supported frame rates and format profiles.
| Flag | Short | Description |
|---|---|---|
--source <path> | -S | Source file path |
--target <path> | -T | Target output file path |
--config <path> | -C | Job configuration JSON file path |
--job_type <type> | -JT | Job type: convert, qc, align, or retime. Defaults to convert |
--source_profile <profile> | -SP | Source format profile name |
--target_profile <profile> | -TP | Target format profile name |
--source_frameRate <rate> | -SFR | Source frame rate. Defaults to auto |
--target_frameRate <rate> | -TFR | Target frame rate. Defaults to source frame rate |
--source_dropFrame <bool> | -SDF | Source drop frame (true/false) |
--target_dropFrame <bool> | -TDF | Target drop frame (true/false) |
--offset <TC|Frames> | -O | Timecode offset value (timecode or frame count) |
--offset_type <type> | -OT | Offset mode: add, subtract, or auto |
--auto_format <bool> | -AF | Enable auto format |
--max_lines <number> | -ML | Maximum lines per caption event (auto format) |
--max_characters <number> | -MC | Maximum characters per line (auto format) |
--min_duration <number> | -MD | Minimum event duration in seconds (auto format) |
--allow_orphan_words <bool> | -AOW | Allow single-word lines in auto format |
--auto_format_selective <bool> | -AFS | Only reformat events that already exceed the configured limits |
--partial [start-tc,duration] | -P | Trim output starting at a timecode, with optional duration |
--tcMultiplier <number> | -TCM | Stretch or shrink all timecodes by a decimal multiplier (e.g. 1.001, 0.999) |
--convert_to_pop_on <bool> | -CPO | Convert Roll-Up and Paint-On captions to Pop-On |
--fix_overlap <bool> | -FO | Automatically fix overlapping caption events |
--source_encoding <enc> | -SE | Source file character encoding |
--target_encoding <enc> | -TE | Target file character encoding |
--xml_format <bool> | -X | Auto-format XML outputs (TTML, DFXP, FCPXML, etc.) |
--bom <bool> | -BOM | Write a BOM to the target file |
--eol <string> | -EOL | End-of-line style: windows, unix, or macintosh |
--list <profile> | -LS | Print all available options for a given format profile |
--extract_from_source <bool> | -ES | Extract captions from a media wrapper |
--extract_from_source_profile <profile> | -ESP | Extraction source profile (e.g. mp4) |
--timecode_format <format> | -TCF | Source timecode format for retime jobs: smpte, frames, ms, seconds, tcMs, tcTicks |
--timecode_reformat <format> | -TCRF | Output timecode format for retime jobs |
The --jobDescription / -JD flag is deprecated. Use --config / -C instead.
Supported file encodings: ascii, base64, hex, ucs2, ucs-2, utf16le, utf-16le, utf8, utf-8, binary, latin1, 1252.
Job Types
The job_type field (or --job_type flag) controls what the CLI does with the source file. It defaults to convert.
convert
Standard caption format conversion. Reads the source file, applies any configured filters, and writes the converted output to the target path.
qc
Automated quality control. Runs technical and/or content rules against the source file and writes a JSON report to the target path. Requires a qc object in the config JSON with technical and/or content rules enabled.
align
Aligns caption timing to a word-level transcript. Requires transcript (path to the transcript file) and transcript_profile in the config JSON.
{
"job_type": "align",
"source": "/captions/input.srt",
"target": "/captions/output.srt",
"source_profile": "SubRip Video Subtitle Script",
"target_profile": "SubRip Video Subtitle Script",
"transcript": "/transcripts/episode.json",
"transcript_profile": "deepgram"
}
retime
Adjusts timecodes without converting the caption format. Use --timecode_format to specify the input timecode representation and --timecode_reformat for the output format.
Job Configuration Reference
All fields can appear in the config JSON passed via --config. Command-line flags override the corresponding JSON fields where both are provided.
Core Fields
| Field | Default | Description |
|---|---|---|
job_type | "convert" | Job type: convert, qc, align, or retime |
source | — | Source file path |
sources | — | Array of source file paths for multi-file processing |
target | — | Output file path |
source_profile | auto-detected | Source format profile name |
target_profile | auto-detected | Target format profile name |
default_frameRate | 29.97 | Frame rate used when auto-detection is unavailable |
default_dropFrame | true | Drop frame setting used when auto-detection is unavailable |
source_frameRate | "auto" | Override the detected source frame rate |
target_frameRate | matches source | Override the target frame rate |
source_encoding | format default | Source file character encoding |
target_encoding | format default | Target file character encoding |
incode | "auto" | Programme start timecode |
offset | "00:00:00:00" | Timecode offset value |
offset_type | "add" | Offset mode: add, subtract, or auto |
tcMultiplier | 1 | Decimal timecode stretch/shrink multiplier |
timecode_format | "smpte" | Source timecode format for retime jobs |
timecode_reformat | "match" | Output timecode format for retime jobs |
encoding_options | — | Array of output encoding option objects |
decoding_options | — | Array of input decoding option objects |
preset_id | — | Cloud preset ID (requires network access) |
Transformation Fields
| Field | Default | Description |
|---|---|---|
convert_to_pop_on | — | Convert Roll-Up and Paint-On captions to Pop-On |
merge_by_time | — | Merge overlapping events by time |
fix_overlap | — | Automatically fix overlapping events |
split_speakers_by_color | false | Split events into separate tracks by speaker colour |
remove_color | false | Strip colour from all caption events |
remove_formatting | false | Strip bold, italic, and underline formatting |
reorderRtl | — | Reorder RTL text for left-to-right rendering |
partial | "00:00:00:00" | Trim output from a start timecode; append ,duration to limit length |
searches | [] | Array of search-and-replace rule objects |
position | [] | Array of position rule objects for repositioning events |
segments | [] | Array of segment objects for conforming multiple sources |
bom | — | Write a BOM to the target file |
eol | — | End-of-line character style: windows, unix, or macintosh |
xml_format | — | Auto-format XML file outputs |
extract_from_source | — | Extract captions from a media wrapper |
extract_from_source_profile | "mp4" | Extraction source profile |
Auto Format Options
| Field | Default | Description |
|---|---|---|
auto_format_options.enable | false | Enable auto format |
auto_format_options.max_lines | 2 | Maximum lines per caption event |
auto_format_options.max_characters | 32 | Maximum characters per line |
auto_format_options.minimum_duration | 0.5 | Minimum event duration in seconds |
auto_format_options.allow_orphan_words | true | Allow single-word lines |
auto_format_options.selective | true | Only reformat events that already exceed the limits |
Auto Correct Timing Options
| Field | Default | Description |
|---|---|---|
auto_correct_timing_options.enable | false | Enable auto correct timing |
auto_correct_timing_options.max_cps | 25 | Maximum characters per second |
auto_correct_timing_options.min_duration | 1 | Minimum event duration in seconds |
auto_correct_timing_options.max_duration | 12 | Maximum event duration in seconds |
auto_correct_timing_options.min_frame_gap | 2 | Minimum gap between events in frames |
Event Gap Options
| Field | Default | Description |
|---|---|---|
event_gap_options.enable | — | Enable event gap insertion |
event_gap_options.frames | 2 | Number of frames to insert between adjacent events |
event_gap_options.min_gap | 0 | Minimum existing gap (frames) before adjustment is applied |
event_gap_options.max_gap | 6 | Maximum gap (frames); events further apart are not adjusted |
event_gap_options.shot_change_aware | false | Respect shot change boundaries when inserting gaps |
event_gap_options.shot_changes | [] | Array of shot change timecodes |
event_gap_options.shot_change_format | "seconds" | Shot change timecode format: seconds, smpte, milliseconds, tcMs |
Remove Forced Subtitles Options
| Field | Default | Description |
|---|---|---|
remove_forced_subs.enable | false | Strip forced/textless subtitle events |
remove_forced_subs.max_repeats | 5 | Maximum occurrences before an event is considered forced |
remove_forced_subs.min_duration | 2 | Minimum event duration in seconds for a forced event |
Window Options
Used for safe-area and positioning calculations, particularly relevant for 608 and 708 caption output.
| Field | Default | Description |
|---|---|---|
srcWindow.height | 15 | Source safe-area height in rows |
srcWindow.width | 32 | Source safe-area width in characters |
srcWindow.xPadding | 10 | Horizontal padding |
srcWindow.yPadding | 10 | Vertical padding |
trgWindow.* | same as srcWindow | Target window dimensions (same four fields) |
Align Job Fields
| Field | Default | Description |
|---|---|---|
transcript | — | Path to the transcript file |
transcript_profile | "deepgram" | Transcript format profile |
Post-Processing
| Field | Description |
|---|---|
postScript | Shell command executed after a successful conversion. Supports $target (output file path), $frameRate (source frame rate), and $custom_name substitutions |
Listing Format Options
To inspect the available encoding or decoding options for a specific format profile, use the --list flag:
ccconverter --list "EBU STL"
This prints the option names and their valid values as JSON, which is useful when constructing encoding_options and decoding_options arrays in your config file.
Using Presets
You can reference a stored Job Preset instead of a full Job Description. Specify the preset ID in the config JSON and ensure the CLI has network access to resolve it:
{
"preset_id": "your-preset-id-here"
}
For fully offline workflows, provide the complete Job Description JSON on disk instead. The CLI operates entirely offline when a full configuration is supplied.
If you are operating in a secure environment that should not make outbound network requests, avoid preset_id and keep the full configuration on disk instead.
Batch Processing
To process multiple source files with the same job configuration, supply a sources array in your config JSON:
{
"job_type": "convert",
"sources": [
"/captions/episode_01.srt",
"/captions/episode_02.srt",
"/captions/episode_03.srt"
],
"target": "/converted/output.stl",
"source_profile": "SubRip Video Subtitle Script",
"target_profile": "EBU STL"
}
Each source file is processed independently using the same configuration:
ccconverter --config batch_job.json
Common Use Cases
On-Premise Broadcast Automation
Many broadcast facilities run automation systems (such as Ross Overdrive, Imagine Versio, or custom scripting) that need to process caption files as part of a playout workflow. The CLI integrates into these automation chains as a command-line step, requiring no network connectivity to the Closed Caption Converter API.
AWS Lambda and Serverless Functions
Because the CLI is a single binary with zero dependencies, it is well suited for deployment inside containerised or serverless functions. Drop the binary into your Lambda deployment package or Docker image, reference it from your function handler, and invoke it with a job configuration assembled at runtime.
Air-Gapped Environments
Government agencies, secure post facilities, and content distributors that process confidential or unreleased material often require that files never leave a controlled network. The CLI processes all files locally with no data transmission — ideal for these environments.
Scripted Format Conversion Pipelines
Any scripting environment that can invoke a subprocess can wrap the CLI. Python, bash, PowerShell, Node.js, and Ruby scripts can all call the CLI, check the exit code, and process the output file as part of a larger automated workflow.
Exit Codes
In interactive use, a successful conversion may produce little or no console output beyond returning exit code 0.
| Code | Meaning |
|---|---|
0 | Job completed successfully |
1 | Job failed due to a processing error. Error details are written to stderr |
Getting Help
Run ccconverter --help to see all available flags along with the full list of supported frame rates and format profiles.
For questions about CLI deployment, licensing, or integration support, contact the Closed Caption Converter team at closedcaptionconverter.com/contact.html.