This is the complete developer documentation for the Closed Caption Converter API. # Closed Caption Converter API > Closed Caption Converter is a REST API for converting, conforming, QCing, translating, transcribing and delivering closed caption and subtitle files in over 30 formats. ## Key facts - Base URL: `https://api.closedcaptionconverter.com` - Auth: every `/jobs` request needs both headers `x-api-key: ` and `username: `. Keep the key server-side. - Submit a job: `POST /jobs` as `multipart/form-data` with `source` (file upload or public HTTPS URL) and `config` (Job Description as a JSON string), or as `application/json` where the body is the Job Description with a `source` URL. - The response is JSON `{ id, target, status, statusMsg, qcReport, progress }`. The output file is downloaded from the signed URL in `target`; it is not embedded in the response. - If `status` is `queued` or `in progress` (transcription, alignment, very large jobs), poll `GET /jobs/{id}` until `status` is `passed` or `failed`. - Profile names must match exactly. Get the valid lists from `GET /help/profiles/source` and `GET /help/profiles/target` (no auth). `GET /help/schemas/job` returns a Job Description with all defaults. - Errors are plain-text bodies with HTTP 400, 401, 404, 429 or 500. --- # API Getting Started The Closed Caption Converter API is a REST API that provides programmatic access to the full conversion engine, including format conversion, automatic conform workflows, transcription, machine translation, and delivery. Every feature available in the web application is accessible via the API, plus additional capabilities enabled by [Access Providers](https://www.closedcaptionconverter.com/docs/access-providers-guide). ## Base URL All API requests are made to: ``` https://api.closedcaptionconverter.com ``` If your team has been provisioned with a client-specific staging or production endpoint, use the URL supplied for that environment instead of the public default above. ## Authentication Every request to the `/jobs` endpoints must include two headers: ``` x-api-key: YOUR_API_KEY username: you@example.com ``` | Header | Description | |---|---| | `x-api-key` | Your API key. | | `username` | The email address of the Closed Caption Converter account that owns the key. | Requests missing either header are rejected with `401`. Postman collections exported from the app include both headers. To generate an API key, sign in to the web application, open **Account & Billing** in the left sidebar, select the **API Keys** tab, and click **Generate Key**. Each account has one active key at a time; generating a new key replaces the previous one. API keys are not available during the free trial. Keep your API key secure. Do not include it in client-side code or commit it to version control. If a key is compromised, generate a new key from **Account & Billing → API Keys** immediately. For interactive testing without writing code, use the [API Playground](https://www.closedcaptionconverter.com/docs/api-playground) workspace. ## Endpoints | Method | Path | Auth | Description | |---|---|---|---| | `POST` | `/jobs` | Yes | Submit a job (convert, QC, translate, transcribe, align, deliver). | | `GET` | `/jobs/{id}` | Yes | Get a job's status and download links. Use this to poll asynchronous jobs. | | `DELETE` | `/jobs/{id}` | Yes | Delete a job and its stored source and output files. | | `GET` | `/help/profiles/source` | No | JSON array of every supported source (read) profile name. | | `GET` | `/help/profiles/target` | No | JSON array of every supported target (write) profile name. | | `GET` | `/help/profiles/all` | No | Mapping of profile IDs to display names. | | `GET` | `/help/profiles/extensions` | No | Source and target profiles grouped by file extension. | | `GET` | `/help/profiles/default-extensions` | No | Default file extension for each profile. | | `GET` | `/help/profiles/encodings` | No | Default character encoding for each profile. | | `GET` | `/help/schemas/job` | No | A complete Job Description object with every field set to its default value. | Profile names in a Job Description must match a supported profile exactly. If you are unsure of a name, request `/help/profiles/source` or `/help/profiles/target` rather than guessing. ## Your First Request The primary endpoint for submitting caption processing jobs is `POST /jobs`. The request body is a `multipart/form-data` payload with the following fields: | Field | Type | Description | |---|---|---| | `source` | File or URL string | The source caption file, either uploaded as binary data or provided as a public HTTPS URL. Uploads are limited to 20 MB. | | `sources` | URL strings | Multiple source URLs, for multi-source jobs such as merge or Segmentation & Conform. Repeat the field once per URL. | | `config` | JSON string | The Job Description object that instructs the API what to do with the source file. Required unless `preset_id` is supplied. | | `preset_id` | string | Optional. The ID of a saved [Job Preset](https://www.closedcaptionconverter.com/docs/api/presets). Fields in `config` override the preset's values. | You do not need to include every possible conversion parameter in `config`. Omitted values use the engine defaults or the selected profile defaults. The following example converts a SubRip (SRT) file to WebVTT using curl: ```bash curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -F "source=@/path/to/input.srt" \ -F 'config={ "job_type": "convert", "source_profile": "SubRip Video Subtitle Script", "target_profile": "WebVTT", "default_frameRate": 29.97 }' ``` ## The Job Response Every successful `POST /jobs` returns `200` with a JSON object. The output file is not embedded in the response; download it from the signed URL in `target`: ```json { "jobId": "1b0e6f1a-6a7e-4c1e-9d0b-3f5f7c2a9e11", "id": "1b0e6f1a-6a7e-4c1e-9d0b-3f5f7c2a9e11", "target": "https://storage.googleapis.com/...signed-url.../1b0e6f1a-6a7e-4c1e-9d0b-3f5f7c2a9e11.vtt", "qcReport": false, "qc_status": null, "qc_errors": null, "status": "passed", "statusMsg": "Job completed successfully", "warning": "", "progress": 100 } ``` | Field | Description | |---|---| | `id` / `jobId` | The job ID. Both fields contain the same value. | | `target` | A signed HTTPS URL for the output file, or `false` when the job has not finished yet. | | `qcReport` | The QC report object when QC is enabled, otherwise `false`. See [Automatic QC Tests](https://www.closedcaptionconverter.com/docs/api/qc-tests#qc-report) for its structure. | | `qc_status` | `pass`, `warn`, or `fail` when QC ran, otherwise `null`. See [QC status](https://www.closedcaptionconverter.com/docs/api/qc-tests#qc-status). | | `qc_errors` | Total number of QC errors found, or `null` when QC did not run. | | `status` | `passed` when the job finished, `queued` or `in progress` while it is still running, `failed` on error. | | `statusMsg` | A human-readable status message. | | `warning` | Present on some convert jobs. Non-empty when an output file was produced despite a problem (for example, no events could be decoded). | | `progress` | Completion percentage from `0` to `100`. | ### Asynchronous Jobs Most `convert`, `qc`, and `translate` jobs complete within the request and return `status: "passed"`. Long-running work returns immediately with `status: "queued"` or `status: "in progress"` and `target: false`: - `transcribe` jobs, and `align` jobs that require transcription - Very large files written to some target formats, which are processed in a background queue For these jobs, poll `GET /jobs/{id}` until `status` is `passed` (then download `target`) or `failed` (then read `statusMsg`). A polling interval of 5–15 seconds is reasonable. ```bash curl https://api.closedcaptionconverter.com/jobs/JOB_ID \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" ``` `GET /jobs/{id}` returns the stored job record, including `status`, `statusMsg`, `progress`, the job `config` as a JSON string, and signed download URLs in `target` and `source` when those files exist. ### Deleting a Job `DELETE /jobs/{id}` removes the job's stored source, output, and transcript files and marks the job as deleted: ```json { "jobId": "1b0e6f1a-6a7e-4c1e-9d0b-3f5f7c2a9e11", "id": "1b0e6f1a-6a7e-4c1e-9d0b-3f5f7c2a9e11", "deleted": true, "deletedFiles": 2 } ``` ## Submitting a Job from a URL If your source file is hosted at a public HTTPS URL (or a pre-signed URL for private cloud storage), you can pass the URL string in the `source` field instead of uploading the file directly: ```bash curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -F "source=https://your-bucket.s3.amazonaws.com/captions/input.srt" \ -F 'config={ "job_type": "convert", "source_profile": "SubRip Video Subtitle Script", "target_profile": "EBU STL" }' ``` ## Submitting a JSON Body When your sources are URLs, you can send `Content-Type: application/json` instead of multipart form data. The request body is the Job Description itself, with the source URL in `source` (or an array of URLs in `sources`) and an optional `preset_id`: ```bash curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -H "Content-Type: application/json" \ -d '{ "job_type": "convert", "source": "https://your-bucket.s3.amazonaws.com/captions/input.srt", "source_profile": "SubRip Video Subtitle Script", "target_profile": "WebVTT" }' ``` ## Using a Preset If you have saved a Job Preset in the **Job Presets** workspace, you can reference it by ID instead of passing a full `config` object. Closed Caption Converter will retrieve the stored Job Description and apply it to your source file: ```bash curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -F "source=@/path/to/input.srt" \ -F "preset_id=your-preset-id" ``` See [API — Presets](https://www.closedcaptionconverter.com/docs/api/presets) for details on creating and managing presets. ## Postman Collection A Postman collection is available directly from the Closed Caption Converter web application: - **Subtitle Converter** — configure your job, open the **Job Description** button in the page header, and click **Download Postman Collection**. - **API Playground** — configure your endpoint, source, and job description, then click **Export Postman Collection**. Both exports include pre-configured requests for file upload and URL-based submissions using your current API key, `username` header, and job configuration, and can be imported directly into Postman or any compatible REST client. ## Building with AI To give an AI coding assistant the full API reference as plain markdown, see [Build with AI](https://www.closedcaptionconverter.com/docs/api/build-with-ai). ## Errors & Rate Limits The API uses standard HTTP status codes. Error responses have a **plain-text** body describing the problem, not JSON. | Status | Meaning | Example body | |---|---|---| | `400` | Malformed request, invalid configuration, or the job failed during processing. | `No configuration found in request.` | | `401` | Missing headers, or the API key does not match the `username`. | `Invalid credentials` | | `404` | The job ID does not exist or has been deleted. | `Job not found.` | | `429` | Too many failed authentication attempts. Wait for the number of seconds in the `Retry-After` header before retrying. | `Too many requests` | | `500` | Unexpected server error. | `Internal server error` | A job that fails after it has been accepted (for example, an asynchronous transcription) is reported through `GET /jobs/{id}` with `status: "failed"` and the reason in `statusMsg`. --- # Job Types & Descriptions A Job Description is the JSON document that instructs Closed Caption Converter what to do with a caption file. It is passed as the `config` field in API requests, used by the CLI as a configuration file, and generated automatically by the web application when you configure and run a job. Every job — from a simple format conversion to a multi-step transcription and delivery workflow — is expressed as a Job Description. The **Subtitle Converter** workspace includes a **Job Description** button in the page header that opens a modal with the exact JSON sent to the API for your current configuration. You can copy it directly or export it as a Postman collection. The [API Playground](https://www.closedcaptionconverter.com/docs/api-playground) workspace also lets you edit job description JSON and export Postman collections for API testing. ## Job Description Structure Every Job Description is a JSON object. The following table describes the top-level fields: | Field | Type | Default | Description | |---|---|---|---| | `job_type` | string | `"convert"` | The type of job to perform. See Job Types below. | | `source_profile` | string | `"SubRip Video Subtitle Script"` | The profile name used to decode the source file. Must match a supported source profile name exactly. | | `target_profile` | string | `"SubRip Video Subtitle Script"` | The profile name used to encode the output file. Must match a supported target profile name exactly. | | `default_frameRate` | number | `29.97` | The frame rate used when the source format does not carry frame rate metadata. | | `default_dropFrame` | boolean | `true` | The drop-frame flag used alongside `default_frameRate`. | | `source_frameRate` | string or number | `"auto"` | The frame rate to use when reading source timecodes. Set to `"auto"` to read from the file. | | `target_frameRate` | string or number | `"auto"` | The frame rate to write to the output file. Set to `"auto"` to match the source. | | `offset` | string | `"00:00:00:00"` | SMPTE timecode offset applied to all events. | | `offset_type` | string | `"add"` | Whether to `"add"` or `"subtract"` the offset value. | | `incode` | string | `"00:00:00:00"` | Programme start timecode. All events are normalised relative to this value. Set to `"auto"` to use the first event's in-time. | | `encoding_options` | array | `[]` | Format-specific encode options. Each element is an object with `name` and `selected` properties matching a target profile's available options. Set `selected` to `"auto"` on mapped metadata fields to copy matching source header values into the target. See [Metadata Passthrough](https://www.closedcaptionconverter.com/docs/encoding-decoding-options#metadata-passthrough). | | `decoding_options` | array | `[]` | Format-specific decode options. Each element is an object with `name` and `selected` properties. | | `auto_format_options` | object | see below | Configuration for the Auto Format filter. | | `auto_correct_timing_options` | object | see below | Configuration for the Auto Correct Timing / reading speed correction panel. | | `event_gap_options` | object | see below | Configuration for the Event Gap filter. | | `remove_forced_subs` | object | see below | Configuration for the Remove Forced Subtitles filter. | | `searches` | array | `[]` | Array of Search & Replace rules. | | `segments` | array | `[]` | Array of Segmentation & Conform segment definitions. | | `timecode_mode` | string | `"exclusive"` | How segment end times and black-segment durations are interpreted: `"exclusive"` or `"inclusive"`. Inclusive adds 1 frame to each file segment's end time and each black segment's duration during conform. | | `qc` | object | see below | Automatic QC configuration: `stage` (`"pre"` or `"post"`) and a `tests` array. See [Automatic QC Tests](https://www.closedcaptionconverter.com/docs/api/qc-tests). | | `media_path` | string | `""` | URL of the audio/video file for transcription or alignment jobs. | | `webhook` | string | `""` | A URL that receives a POST callback when the job completes. | | `delivery_options` | object | see below | Output delivery configuration for storage and platform providers. | | `transcribe_options` | object | see below | Transcription configuration including provider ID and language. | | `translate_options` | object | see below | Translation configuration including provider ID, source, and target languages. | --- ## Job Types The `job_type` field determines which processing path the job follows. If you omit it, Closed Caption Converter defaults to `convert`. The supported job types are described below. ### `convert` The standard job type for all format conversion and conform workflows. The source file is decoded using the specified source profile, any configured filters are applied in order, and the result is encoded using the target profile. You can include a `qc` object to run Automatic QC alongside conversion. Findings are returned as `qcReport`, along with `qc_status` and `qc_errors`, and do not change the encoded file. ```json { "job_type": "convert", "source_profile": "Scenarist V1.0", "target_profile": "EBU STL", "default_frameRate": 29.97, "default_dropFrame": true, "encoding_options": [ { "name": "Language Code", "selected": "English" }, { "name": "Country of Origin", "selected": "Canada" } ] } ``` ### `qc` A QC-only job. Nothing is encoded. The output file is `{jobId}_report.json`. The JSON body also includes `qcReport`, `qc_status` (`pass`, `warn`, or `fail`) and `qc_errors`. `qc.tests` must contain at least one enabled test, and a source file is required. Pre-processing (`qc.stage: "pre"`, the default) QCs the first source as decoded. Post-processing (`qc.stage: "post"`) runs every source through the same processing path as a convert job — filters, conform, offset, Auto Format, and timing correction — then QCs the result at the target frame rate. In both cases, technical tests and `sequentialTiming` inspect the source file, and no caption file is encoded. In the web application this job type is labelled **Verify**. ```json { "job_type": "qc", "source_profile": "SubRip Video Subtitle Script", "qc": { "stage": "post", "tests": [ { "id": "maxCharsPerLine", "max": 32, "level": "critical", "threshold": 0 }, { "id": "maxLinesPerEvent", "max": 2, "level": "critical", "threshold": 0 }, { "id": "maxCps", "max": 25, "level": "warn", "threshold": 3 }, { "id": "sequentialTiming", "level": "critical", "threshold": 0 } ] } } ``` ### `transcribe` Sends the audio or video at `media_path` to a configured transcription Access Provider, receives the transcript, converts it into the CCPRJ format, applies any configured filters, and encodes the result to the target profile. Requires a transcription provider to be configured in `transcribe_options`. ```json { "job_type": "transcribe", "target_profile": "SubRip Video Subtitle Script", "media_path": "https://presigned-url-to/media.mp4", "transcribe_options": { "source_language": "en", "provider_id": "your-transcription-provider-id", "provider_options": { "model": "nova-2", "punctuate": true, "diarize": false, "utterances": true, "utt_split": 0.8 } } } ``` The `provider_options` object is passed directly to the transcription service. Refer to your provider's documentation for supported parameters. ### `align` Aligns an existing caption or transcript file to audio/video content using a transcription provider's forced alignment capability. Like the `transcribe` job type, this requires a `media_path` and a configured transcription provider. The source caption file provides the text and the transcription engine provides the precise timing. ```json { "job_type": "align", "source_profile": "SubRip Video Subtitle Script", "target_profile": "WebVTT", "media_path": "https://presigned-url-to/media.mp4", "transcribe_options": { "source_language": "en", "provider_id": "your-transcription-provider-id", "provider_options": { "model": "nova-2", "punctuate": true } } } ``` ### `translate` Translates the text of the source caption file into a target language using a configured translation Access Provider. Timing and formatting are preserved throughout the translation process. Closed Caption Converter handles caption-aware batching to preserve sentence context across event boundaries. ```json { "job_type": "translate", "source_profile": "SubRip Video Subtitle Script", "target_profile": "SubRip Video Subtitle Script", "translate_options": { "provider_id": "your-translation-provider-id", "source_language": "en", "target_language": "fr" } } ``` Language codes are passed directly to the translation service. Refer to your provider's documentation for supported language codes and dialects. ### `deliver` When `delivery_options` are included in a Job Description alongside another job type (such as `convert` or `transcribe`), the output file is automatically delivered to the specified storage or platform provider after processing is complete. The response still includes the standard `target` download URL, and additionally the file is written to the destination. ```json { "job_type": "convert", "source_profile": "SubRip Video Subtitle Script", "target_profile": "WebVTT", "delivery_options": { "provider_id": "your-s3-provider-id", "provider_options": { "bucket": "your-bucket-name", "region": "us-east-1", "key": "output/captions/episode01.vtt" } } } ``` --- ## Filter Configuration Filters are configured as nested objects within the Job Description. Each filter has an `enable` flag that must be set to `true` to activate it, along with its specific settings. ### Auto Format ```json "auto_format_options": { "enable": true, "max_lines": 2, "max_characters": 32, "min_duration": 1, "allow_orphan_words": false, "selective": true } ``` ### Automatic Reading Speed ```json "auto_correct_timing_options": { "enable": true, "max_cps": 25, "min_duration": 1, "max_duration": 12, "min_frame_gap": 2 } ``` ### Event Gap ```json "event_gap_options": { "enable": true, "frames": 2, "min_gap": 0, "max_gap": 6, "shot_change_aware": false, "shot_changes": [] } ``` ### Search & Replace The `searches` array contains one or more replacement rules: ```json "searches": [ { "find": "colour", "replace": "color", "regex": false, "caseSensitive": false } ] ``` ### Segmentation & Conform The `segments` array defines the regions to extract. Set `timecode_mode` to `"inclusive"` when the source system includes the last frame in its duration calculations; otherwise leave it at `"exclusive"` (the default). ```json "timecode_mode": "exclusive", "segments": [ { "incode": "01:00:00:00", "outcode": "01:15:00:00", "tcFormat": "smpte" } ] ``` ### Remove Forced Subtitles ```json "remove_forced_subs": { "enable": true, "remove": true } ``` Set `remove` to `true` to remove forced events, or `false` to keep only forced events and remove all others. ### Automatic QC Automatic QC is a list of tests in `qc.tests`. Each test has an `id`, a `level` (`critical`, `warn`, or `info`), a `threshold`, and its own parameters. The job's `qc_status` is set as follows: - `fail` if any critical test reaches its threshold; - `warn` if no critical test does, but a warning test does; - `pass` otherwise. See [Automatic QC Tests](https://www.closedcaptionconverter.com/docs/api/qc-tests) for the full test catalog, and [Filters — Automatic QC](https://www.closedcaptionconverter.com/docs/filters#automatic-qc) for the web UI. `qc.stage` controls when content tests run. Technical tests and `sequentialTiming` always inspect the source file. | `qc.stage` | Aliases | Content tests | |---|---|---| | `"pre"` (default) | `"pre-processing"` | Source captions, immediately after decode, at the source frame rate | | `"post"` | `"post-processing"` | Captions after filters and processing, immediately before encode, at the target frame rate | Values are case-insensitive. - **Which jobs:** convert, transcribe, translate, and align jobs can include a `qc` object. The report is returned as `qcReport`, along with `qc_status` and `qc_errors`, and does not change the encoded file. - **Align jobs** also attach alignment drift fields to the report. - **Transcribe jobs** skip technical and source-order tests because there is no caption source file. ```json "qc": { "stage": "pre", "tests": [ { "id": "maxCharsPerLine", "max": 42, "level": "critical", "threshold": 0 }, { "id": "maxLinesPerEvent", "max": 2, "level": "critical", "threshold": 0 }, { "id": "maxCps", "max": 20, "level": "critical", "threshold": 0 }, { "id": "minGap", "min": 2, "level": "critical", "threshold": 0 }, { "id": "frameGap", "min": 2, "minTolerance": 3, "maxTolerance": 11, "level": "warn", "threshold": 0 }, { "id": "overlap", "level": "critical", "threshold": 0 }, { "id": "sequentialTiming", "level": "critical", "threshold": 0 }, { "id": "illegalCharsNetflix", "level": "critical", "threshold": 0 }, { "id": "xmlEntities", "level": "critical", "threshold": 0 } ] } ``` The legacy `qc.content` / `qc.technical` format is still accepted and is converted to tests automatically. See [Legacy configuration](https://www.closedcaptionconverter.com/docs/api/qc-tests#legacy-configuration). ```json "qc": { "stage": "pre", "content": { "enabled": true, "maxChars": 42, "maxLines": 2, "maxCps": 20 }, "technical": { "enabled": false } } ``` --- # Example Job Description A complete Job Description with every option populated. ```json { "id": "f378dcc9-c731-4c3e-8dea-4ed7d5098873", "job_type": "convert", "custom_name": "Untitled", "delivery_options": { "provider_id": "", "provider_options": {} }, "transcribe_options": { "source_language": "", "provider_id": "", "provider_options": {} }, "translate_options": { "source_language": "", "target_language": "", "provider_id": "", "provider_options": {} }, "auto_format_options": { "enable": false, "max_lines": 2, "max_characters": 32, "min_duration": 1, "allow_orphan_words": false, "selective": true }, "auto_correct_timing_options": { "enable": false, "max_cps": 25, "min_duration": 1, "max_duration": 12, "min_frame_gap": 2 }, "event_gap_options": { "enable": false, "frames": 2, "min_gap": 0, "max_gap": 6, "shot_change_format": "seconds", "shot_changes": [], "shot_change_aware": false }, "remove_forced_subs": { "enable": false, "max_repeats": 5, "min_duration": 2, "remove": false }, "sources": [], "source": "", "target": "", "media_path": "", "audio_track": 0, "webhook": "", "reorderRtl": false, "source_profile": "ssPoliscript", "target_profile": "subRip", "source_extension": "srt", "target_extension": "srt", "encoding_options": [ { "name": "Encode Formatting", "type": "list", "values": [ true, false ], "selected": true }, { "name": "Encode Positioning", "type": "list", "values": [ true, false ], "selected": true } ], "decoding_options": [ { "name": "Code Page", "type": "list", "values": [ "auto", "ISO 8859-1 Latin", "ISO 8859-7 Greek", "ISO 8859-2 Latin Czech", "ISO 8859-6 Arabic", "ISO 8859-8 Hebrew", "ISO 8859-9 Turkish", "Windows-874 Thai", "ISO 8859-5 Cyrillic", "Big5 Traditional Chinese", "GBK Simplified Chinese", "Korean", "Japanese Shift-JIS" ], "selected": "auto" }, { "name": "Ignore Metadata", "type": "list", "values": [ true, false ], "selected": true } ], "default_frameRate": "29.97", "default_dropFrame": true, "source_frameRate": "auto", "source_dropFrame": "auto", "target_frameRate": "auto", "target_dropFrame": "auto", "source_encoding": "UTF-8", "target_encoding": "UTF-8", "tcMultiplier": 1, "timecode_format": "smpte", "timecode_reformat": "match", "fix_overlap": false, "merge_by_time": false, "convert_to_pop_on": false, "dropFrame_convert": false, "offset": "00:00:00:00", "offset_type": "add", "incode": "auto", "bom": false, "postScript": "", "eol": "auto", "xml_format": false, "embed_type": "none", "embed_language": "eng", "split_speakers_by_color": false, "remove_color": false, "speaker_prefix": "- ", "remove_formatting": false, "extract_from_source": false, "extract_from_source_profile": "mp4", "util": false, "partial": "00:00:00:00", "segments": [], "qc": { "stage": "pre", "tests": [ { "id": "maxCharsPerLine", "max": 42, "level": "critical", "threshold": 0 }, { "id": "maxLinesPerEvent", "max": 2, "level": "critical", "threshold": 0 }, { "id": "maxCps", "max": 20, "level": "critical", "threshold": 0 }, { "id": "minGap", "min": 2, "level": "critical", "threshold": 0 }, { "id": "frameGap", "min": 2, "minTolerance": 3, "maxTolerance": 11, "level": "warn", "threshold": 0 }, { "id": "overlap", "level": "critical", "threshold": 0 }, { "id": "sequentialTiming", "level": "critical", "threshold": 0 } ] }, "transcript": "", "transcript_profile": "", "position": [], "searches": [], "srcWindow": { "height": 15, "width": 32, "xPadding": 10, "yPadding": 10 }, "trgWindow": { "height": 15, "width": 32, "xPadding": 10, "yPadding": 10 } } ``` --- # Job Presets A Job Preset is a named Job Description stored in your Closed Caption Converter account. Instead of including the full JSON configuration in every API or CLI call, you can create a preset once and reference it by its assigned **Preset ID** in subsequent requests. Presets reduce the amount of code in your integration, prevent configuration drift between environments, and make it easy for teams to share standardised workflows. ## Creating a Preset Presets can be created in two ways: **From the Job Presets workspace** — open **Job Presets** in the left sidebar, click **+ New**, and enter the preset name, ID, description, and Job Configuration JSON. **From the Subtitle Converter** — configure your job exactly as you want it, open the **Backup Settings** section, and click **Save Preset**. You will be prompted for a preset name and preset ID before the configuration is stored. ## Managing Presets To review or edit an existing preset, open **Job Presets** from the left sidebar and update the **Preset Name**, **Preset ID**, **Preset Description**, or **Job Configuration** JSON. You can also copy a ready-to-use `{ "preset_id": "..." }` snippet from the table. Editing a preset changes the stored Job Description but does not affect any jobs that have already been submitted. Deleting a preset makes its ID invalid for future jobs but does not affect job history. Naming conventions are important when using many presets. A consistent naming scheme (for example, `[client]_[source-format]_to_[target-format]_[version]`) makes it easy to find the right preset without needing to inspect its contents. ## Using a Preset in the API To use a preset, pass the `preset_id` in your API request body instead of a `config` object: ```bash curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -F "source=@/path/to/input.srt" \ -F "preset_id=your-preset-id-here" ``` The server loads the stored Job Description and processes the file exactly as if you had submitted the full JSON. No additional configuration is required in the API call beyond the source file and the preset ID. You can load a preset into the [API Playground](https://www.closedcaptionconverter.com/docs/api-playground) using **Load Preset** before submitting a test job. ## Using a Preset in the CLI The CLI supports presets in the same way as the API. Pass the preset ID in the job configuration file: ```json { "preset_id": "your-preset-id-here" } ``` A network connection is required to resolve the preset from the server when using presets with the CLI. For fully offline environments, store the complete Job Description locally instead of using `preset_id`. ## Preset IDs in Code Preset IDs are UUID strings. Store them in your application's environment configuration or secrets manager rather than hardcoding them in source code. This makes it easy to swap presets between environments (development, staging, production) without changing application code. ```bash # Example: store as an environment variable CCCONVERTER_PRESET_SRT_TO_STL="abc12345-0000-0000-0000-000000000001" # Use it in a curl request curl -X POST https://api.closedcaptionconverter.com/jobs \ -H "x-api-key: YOUR_API_KEY" \ -H "username: you@example.com" \ -F "source=@/path/to/input.srt" \ -F "preset_id=$CCCONVERTER_PRESET_SRT_TO_STL" ``` --- # API — Access Providers Access Providers extend the Closed Caption Converter API by connecting it to third-party services. They are configured once in the web application and then referenced by Provider ID in your Job Descriptions. For a conceptual overview of Access Providers and the full list of supported services, see the [Access Providers](https://www.closedcaptionconverter.com/docs/access-providers-guide) page. This page covers how to configure Access Providers in the web application and how to reference them in Job Description JSON. ## Adding an Access Provider Sign in to the web application and open **Access Providers** from the left **Workspaces** sidebar. Click **+ New**, select the provider type, enter a display name, and enter the required credentials. When you save the configuration a unique **Provider ID** (a UUID string) is assigned to that entry. This is the value you use in the `provider_id` fields of your Job Descriptions. Because credentials are stored server-side and referenced by ID, your application code never contains raw third-party API keys. Different environments (staging vs. production) can use different Provider IDs that point to separate accounts, while keeping the same Job Description structure. --- ## Transcription Providers Transcription provider IDs are used in the `transcribe_options.provider_id` field for `transcribe` and `align` job types. Provider-specific parameters are passed through `transcribe_options.provider_options` and forwarded directly to the service. ```json "transcribe_options": { "source_language": "en", "provider_id": "YOUR_TRANSCRIPTION_PROVIDER_ID", "provider_options": { "model": "nova-2", "punctuate": true, "diarize": true, "utterances": true, "utt_split": 0.8 } } ``` The `provider_options` object varies by service. Refer to the transcription provider's own API documentation for available parameters. Common options across providers include model selection, speaker diarisation, punctuation, and language detection flags. --- ## Translation Providers Translation provider IDs are used in the `translate_options.provider_id` field for `translate` job types. Source and target language codes are passed directly to the service, so use the language code format supported by your chosen provider — for example, DeepL uses `EN-US`, Google Translate uses `en`, and Amazon Translate uses `en`. ```json "translate_options": { "provider_id": "YOUR_TRANSLATION_PROVIDER_ID", "source_language": "en", "target_language": "fr" } ``` --- ## Storage Providers Storage provider IDs are used in the `delivery_options.provider_id` field. The `delivery_options.provider_options` object contains the bucket, path, and any other provider-specific settings. ### AWS S3 and Backblaze B2 ```json "delivery_options": { "provider_id": "YOUR_S3_PROVIDER_ID", "provider_options": { "bucket": "your-bucket-name", "region": "us-east-1", "key": "path/to/output/captions.srt" } } ``` Backblaze B2 uses the same configuration structure as AWS S3 because it supports the S3-compatible API. Configure Backblaze B2 credentials in an S3-type provider using your B2 application key ID and application key. ### Google Cloud Storage ```json "delivery_options": { "provider_id": "YOUR_GCS_PROVIDER_ID", "provider_options": { "projectId": "your-gcp-project-id", "clientEmail": "service-account@project.iam.gserviceaccount.com", "bucket": "your-gcs-bucket", "fileName": "captions/output.vtt" } } ``` ### Azure Blob Storage ```json "delivery_options": { "provider_id": "YOUR_AZURE_PROVIDER_ID", "provider_options": { "container": "your-container-name", "blobName": "captions/output.vtt" } } ``` --- ## Platform Providers ### Iconik MAM Jobs for Iconik assets are submitted to a dedicated endpoint rather than the standard `/jobs` endpoint: ``` POST https://api.closedcaptionconverter.com/iconik ``` The payload format is the same as a standard job. When Closed Caption Converter receives a request at the `/iconik` endpoint, it reads the asset context automatically from the Iconik action payload, locates the associated subtitle files, processes them according to the job configuration, and writes the output back to the originating Iconik asset. For setup instructions, including creating the Custom Action in Iconik and configuring the Iconik provider in the web application, see the [Access Providers — Platform](https://www.closedcaptionconverter.com/docs/access-providers-guide#iconik-mam) section. ### Closed Caption Creator When a Closed Caption Creator provider is configured and referenced in `delivery_options`, the processed output file is automatically registered as a new project in Closed Caption Creator and assigned to the configured workspace for editorial review. --- ## Combining Delivery with Other Job Types Delivery options can be combined with any job type — convert, transcribe, translate, or align. The output file is delivered to the specified destination after processing completes. The API response still includes the standard `target` download URL, so you can inspect the result even when delivery is configured. ```json { "job_type": "transcribe", "target_profile": "SubRip Video Subtitle Script", "media_path": "https://presigned-url/media.mp4", "transcribe_options": { "source_language": "en", "provider_id": "YOUR_TRANSCRIPTION_PROVIDER_ID" }, "delivery_options": { "provider_id": "YOUR_S3_PROVIDER_ID", "provider_options": { "bucket": "my-caption-bucket", "region": "us-west-2", "key": "output/transcribed.srt" } } } ``` --- # Job Status Dashboard The **Job Status Dashboard** provides a complete audit trail of every API job submitted under your account, whether from the API, the [API Playground](https://www.closedcaptionconverter.com/docs/api-playground), or the CLI (when connected to your account). Open it from **Job Status Dashboard** in the left **Workspaces** sidebar. ## What Is Recorded Every job submission creates a history entry that records the job ID, timestamp, job type, source and target profiles, frame rate, job status, and any error messages returned for failed jobs. For jobs that produced output files, the history entry retains links to download the source, target, and job response. ## Filtering and export Above the table you can filter jobs by: - **Job type** — for example `convert`, `transcribe`, or `translate` - **Status** — passed or failed - **Date range** — last 24 hours, week, month, year, or a custom range Use **Refresh** to reload the latest data from your account. Enable **Auto-refresh (15s)** to poll for updates every 15 seconds; this reloads the current page of results without changing your filters or pagination. Your auto-refresh preference is saved in the browser. **Export CSV** downloads the current filtered view for reporting or offline analysis. The table supports pagination (25, 50, or 100 rows per page). Your page size preference is saved in the browser. ## Job Statuses | Status | Description | |---|---| | `completed` / `passed` | The job finished successfully and output is available. | | `failed` | The job encountered an error during processing. The error message is shown in the job detail view. | | `processing` | The job is currently being processed. Common for long-running jobs such as transcription. | | `queued` | The job has been accepted and is waiting in the processing queue. | ## Per-job actions Each row in the dashboard provides actions to work with that job: | Action | Description | |---|---| | **View JSON** | Open the full API response in a modal and copy it to the clipboard. | | **Download** | Download the source file, target output, or job response JSON. | | **Retry** | Resubmit the job with the same configuration. | | **Delete** | Send `DELETE /jobs` (with job ID) to remove the job and its stored files from the API. | | **Open in Caption Editor** | Available for passed jobs — opens the job in the built-in Caption Editor (powered by Closed Caption Creator) with its media, source, and target captions loaded. Use the editor's **Save** button to download the edited captions in the job's target format. | ## Using the dashboard for debugging When a job fails, the Job Status Dashboard is the first place to investigate. The detail view for each failed job includes the full error message returned by the processing engine, the Job Description that was submitted, and the source file name. Common causes of job failures include: - A mismatch between the selected source profile and the actual file format (for example, selecting the Scenarist SCC profile for a file that is actually a TTML XML file). - Encoding option values that are invalid for the selected profile. - A `media_path` URL that the server cannot access (expired pre-signed URLs, private endpoints, or incorrect permissions). - Malformed JSON in the `config` field. ## Webhook Notifications Rather than polling the API for job status, you can configure a `webhook` URL in your Job Description. When the job completes (whether successfully or with a failure), Closed Caption Converter will POST a notification to the webhook URL with the job result payload. This is the recommended approach for high-volume automated workflows where polling would be inefficient. ```json { "job_type": "convert", "source_profile": "SubRip Video Subtitle Script", "target_profile": "WebVTT", "webhook": "https://your-server.example.com/webhooks/cc-converter" } ``` The webhook payload is the same JSON structure as the synchronous API response, allowing you to process it with the same code. --- # Closed Caption Profiles & Formats Closed Caption Converter supports over 30 file formats through a system of Profiles. A Profile is a module that knows how to read (decode) a specific format into the internal CCPRJ representation, and/or write (encode) a CCPRJ object back out to that format. Because every format passes through CCPRJ, any supported source format can be converted to any supported target format without a dedicated converter for each pair. Profiles are divided into **source profiles** (decode) and **target profiles** (encode). Most profiles support both operations, though some are decode-only (such as raw transcription outputs from speech-to-text services) or encode-only. When selecting profiles in the web application, the **Source Profile** dropdown shows all readable formats and the **Target Profile** dropdown shows all writable formats. Within each section below, the most commonly encountered formats are listed first where practical. ## The CCPRJ Intermediate Format CCPRJ (Closed Caption Project) is the internal JSON schema used to store caption data between the decode and encode steps. Every decode operation produces a CCPRJ object containing events (individual caption cues with start/end timecodes and text content), metadata (frame rate, author information, technical attributes), speakers, markers, and format-specific style data. Document-level fields such as language and programme title can be copied into a target format when the matching encoding option is set to `auto`; see [Metadata Passthrough](https://www.closedcaptionconverter.com/docs/encoding-decoding-options#metadata-passthrough). Filters operate directly on CCPRJ, making them format-agnostic. You can also use CCPRJ as a source or target profile directly, which allows you to inspect the raw internal representation of any file or feed pre-built CCPRJ directly into the encoder. ## Closed Caption Converter Version in Encoded Files Some target profiles stamp the conversion-engine version into the encoded file. The string is `Closed Caption Converter v` followed by the engine version that produced the file — for example `Closed Caption Converter v3.5.35`. This is always on for the profiles listed below: there is no encoding option or API flag to disable it. The same stamp appears in files produced by the web application and the API. It is independent of the version shown in the web application's About dialog. ### SMPTE TTML SMPTE TTML writes the stamp in `` as ``: ```xml Closed Caption Converter v3.5.35 ``` The version number in that example matches the engine build that encoded the file; later builds write their own version. ### Other profiles that stamp the version | Profile | Where it appears | Example | |---|---|---| | SMPTE TTML, Adobe TTML, A&E TTML, Broadstream TTML | `` | `Closed Caption Converter v3.5.35` | | Timed-Text Markup Language, Sandflow TTML | `` | `Closed Caption Converter v3.5.35 - TTML Export` | | YouTube TTML | `` | `Closed Caption Converter v3.5.35 - YouTube TTML Export` | | DFXP | `` | `Encoded by Closed Caption Converter v3.5.35` | | Netflix TT Captions | `` | `Closed Caption Converter v3.5.35 - Netflix TT Captions (4x3)` | | Netflix TT Subtitles | `` | `Closed Caption Converter v3.5.35 - Netflix TT Subtitles` | | IMSC Text Captions | `` | `IMSC1 Text Profile document created by Closed Caption Converter v3.5.35` | | IMSC Text Subtitles | `` | `IMSC1 Text Subtitles document created by Closed Caption Converter v3.5.35` | | IMSC 1.1 Text Profile | `` | `IMSC 1.1 Text Profile document created by Closed Caption Converter v3.5.35` | | IMSC Text Captions — JA | `` | `Created by Closed Caption Converter v3.5.35` unless **Program Description** is set | | HBO MAX SMPTE | `` | `Created by Closed Caption Converter v3.5.35 \| www.closedcaptionconverter.com` | | EBU TT | `` | `Closed Caption Converter v3.5.35` | | DLP Cinema | XML comment before `` | `` | | MacCaption 608/708 | MCC header `Creation Program=` | `Creation Program=Closed Caption Converter v3.5.35` | | Substation Alpha / Advanced SSA | `[Script Info]` comment | `; Script generated by Closed Caption Converter v3.5.35 \| www.closedcaptionconverter.com` | | ProCap Transfer | Header comment | `\ Generated By: Closed Caption Converter v3.5.35 ...` | | Vitac | `.vnl` header | `** Using Closed Caption Converter v3.5.35` | | Avid DS | First line | `@ This file written by Closed Caption Converter v3.5.35` | | LMS Transcript, MS2 Transcript, As-Broadcast Dialogue List Word, Dialogue List Custom 01 | Word document `creator` property | Office Author field, not caption text | For **IMSC Text Captions — JA**, the **Program Description** encoding option replaces `` when it is set. The profile default is `Create by CC Converter 3`, which omits the engine version. Clear that option (or omit it in the API) if you want the version stamp. MacCaption **MCC Version** (`1.0` / `2.0`) is the MacCaption file format, written as `File Format=MacCaption_MCC V2.0`. That is separate from `Creation Program=`. ### Profiles that do not stamp the engine version WebVTT, iTunes Timed Text, SubRip, and Scenarist SCC do not include this generator string. HBO SMPTE TTML writes `SMPTE 2052` with no version number. IMSC Rosetta writes a Rosetta specification version (`rosetta:version`), not the Closed Caption Converter engine version. ## North American Broadcast These formats are used in North American broadcast television workflows and carry CEA-608 and CEA-708 caption data. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Scenarist V1.0 (SCC) | `.scc` | ✓ | ✓ | Standard CEA-608 caption format used across North American broadcast. | | Scenarist V1.0 Advanced | `.scc` | — | ✓ | Encode-only variant with extended channel and pop-on configuration options. | | MacCaption 608/708 (MCC) | `.mcc` | ✓ | ✓ | Carries both CEA-608 and CEA-708 data with SMPTE timecode headers. | | MacCaption 608/708 Advanced | `.mcc` | — | ✓ | Encode-only with extended 708 service configuration and style options. | | MacCaption Project | `.cca` | ✓ | — | Native MacCaption project file format. Decode only. | | 608/708 VANC Data | `.raw` | — | ✓ | Raw binary VANC payload data. Encode only. | ## European Broadcast These formats are used in European and international broadcast workflows. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | ScreenSystems Poliscript (PAC) | `.pac` | ✓ | ✓ | Common European broadcast subtitle format used in ScreenSystems and SubStation workflows. | | EBU STL | `.stl` | ✓ | ✓ | Binary STL format as defined by EBU Tech 3264. | | Spruce STL | `.stl` | ✓ | ✓ | Text-based STL variant used in some Spruce editing environments. | | EBU TT | `.xml` | ✓ | ✓ | EBU-TT XML format based on the W3C Timed Text specification. | ## TTML & XML Subtitle Formats These XML-based profiles cover a wide range of TTML dialect variants used across streaming platforms, broadcast, and localisation workflows. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Timed-Text Markup Language (TTML) | `.xml` / `.ttml` / `.mp4` | ✓ | ✓ | Base TTML profile conforming to W3C TTML 1.0. | | Distribution Format Exchange Profile (DFXP) | `.xml` / `.dfxp` | ✓ | ✓ | DFXP (TTML 1.0 Distribution) used across many delivery specifications. | | SMPTE TTML | `.xml` / `.ttml` / `.mp4` | ✓ | ✓ | TTML with SMPTE timecode references. Encoded files include the Closed Caption Converter version in ``. | | IMSC 1.0 Basic | `.xml` / `.ttml` | ✓ | ✓ | W3C IMSC 1.0 Basic document profile. | | IMSC Text Captions | `.xml` / `.ttml` | ✓ | ✓ | IMSC Text profile targeting caption delivery. | | IMSC Text Subtitles | `.xml` / `.ttml` | ✓ | ✓ | IMSC Text profile targeting subtitle delivery. | | IMSC Text Captions — JA | `.xml` | — | ✓ | IMSC variant with Japanese language caption styling. Encode only. | | EBU TT | `.xml` | ✓ | ✓ | EBU-TT XML. | | Verizon TTML | `.ttml` / `.mp4` | ✓ | — | Verizon Media TTML variant. Decode only. | | Disney TTML | `.xml` | — | ✓ | Disney-specific TTML delivery format. Encode only. | | Sandflow TTML | `.xml` / `.ttml` | ✓ | ✓ | Sandflow-compliant TTML used in IMF workflows. | | HBO GO TTML | `.xml` / `.ttml` | — | ✓ | HBO Go TTML delivery format. Encode only. | | HBO MAX SMPTE | `.xml` / `.ttml` | — | ✓ | HBO Max SMPTE TTML delivery format. Encode only. | | HBO SMPTE TTML | `.xml` / `.ttml` | — | ✓ | Legacy HBO SMPTE TTML. Encode only. | | Netflix DFXP | `.dfxp` | ✓ | ✓ | Netflix-specific DFXP format. | | Netflix TT Captions | `.xml` | ✓ | ✓ | Netflix Timed Text captions profile. | | Netflix TT Subtitles | `.xml` | ✓ | ✓ | Netflix Timed Text subtitles profile. | | Crunchyroll DFXP | `.dfxp` | ✓ | ✓ | Crunchyroll subtitle delivery format. | | YouTube TTML | `.xml` / `.ttml` | ✓ | ✓ | YouTube caption TTML format. | | Ooona TTML | `.xml` / `.ttml` | ✓ | ✓ | Ooona platform TTML variant. | | TTML FooEngine | `.xml` / `.ttml` | ✓ | ✓ | Foo Engine platform TTML variant. | | TTML Legacy | `.ttml` | — | ✓ | Legacy TTML output for older toolchains. Encode only. | | MAGIC TT | `.xml` | ✓ | ✓ | MAGIC TT XML-based subtitle format. | | DCDM Subtitle | `.xml` | ✓ | — | Digital Cinema Distribution Master subtitle XML. Decode only. | | DLP Cinema | `.xml` | ✓ | ✓ | DLP Cinema subtitle format. | | FCP XML | `.xml` | — | ✓ | Final Cut Pro XML caption export. Encode only. | ## Web & Streaming Subtitles These are the most common formats used in online video, OTT platforms, and open subtitle workflows. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | SubRip Video Subtitle Script (SRT) | `.srt` | ✓ | ✓ | The most widely-used plain-text subtitle format. | | WebVTT | `.vtt` / `.webvtt` | ✓ | ✓ | W3C Web Video Text Tracks. Supports cue positioning. | | Able Player DV | `.vtt` / `.webvtt` | ✓ | ✓ | Described video WebVTT variant used with the Able Player web player. | | SubViewer | `.sbv` / `.sub` | ✓ | ✓ | Simple text subtitle format compatible with YouTube uploads. | | Substation Alpha (SSA) | `.ssa` | ✓ | ✓ | Original Substation Alpha format for styled subtitles. | | Advanced Substation Alpha (ASS) | `.ass` | ✓ | ✓ | Extended variant of SSA with advanced styling and layout. | | Synchronized Accessible Media Interchange (SAMI) | `.smi` / `.sami` | ✓ | ✓ | Microsoft caption format used in Windows Media Player. | | iTunes Timed Text (iTT) | `.itt` | ✓ | ✓ | Apple's format for iTunes and Final Cut Pro subtitle tracks. | | iTunes Timed Text Media | `.itt` | ✓ | ✓ | Media variant of iTT. | | iTunes Timed Text SMPTE | `.itt` | ✓ | — | SMPTE timecode variant of iTT. Decode only. | ## Binary & Legacy Broadcast These are binary or proprietary formats used in older broadcast and specialised captioning systems. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Cavena 890 | `.890` | ✓ | ✓ | Binary subtitle format used in Cavena CPC subtitle hardware. | | Cavena CIP | `.cip` | ✓ | — | Cavena CIP binary format. Decode only. | | Cheetah CAP (binary) | `.cap` | ✓ | ✓ | Binary format used by Cheetah captioning software. | | Cheetah (ASCII Text) | `.asc` | ✓ | ✓ | ASCII text variant of the Cheetah format. | | Videotron Lambda | `.cap` | ✓ | ✓ | Legacy Videotron Lambda binary caption format. | | NCI Caption | `.cap` | ✓ | — | NCI binary caption format. Decode only. | | CaptionMaker Plus | `.cap` | ✓ | — | CaptionMaker binary format. Decode only. | | CaptionMaker Plus V2 | `.cap` | ✓ | — | CaptionMaker binary V2. Decode only. | | Caption Inc | `.cin` | ✓ | — | Caption Inc legacy format. Decode only. | | Canvass SST Project | `.sdb` | ✓ | — | Canvass SST project format. Decode only. | | Vitac | `.vnl` | ✓ | ✓ | Vitac (Verbit) VNL caption format. | ## NLE & Post-Production These profiles integrate with non-linear editing systems and post-production software. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Avid DS | `.txt` | ✓ | ✓ | Caption export format for Avid DS editing system. | | Adobe Encore | `.txt` | ✓ | ✓ | Adobe Encore DVD subtitle format. | | Apple DVD Studio Pro | `.txt` | ✓ | ✓ | Apple DVD Studio Pro caption export. | | DaVinci Resolve ADR Cue List | `.csv` | ✓ | ✓ | ADR cue list CSV export from DaVinci Resolve. | | DaVinci Resolve Edit Index List | `.csv` | ✓ | ✓ | Edit index list CSV from DaVinci Resolve. | | DaVinci Resolve Timeline Markers | `.edl` | ✓ | ✓ | Timeline markers exported as an EDL from DaVinci Resolve. | | FCP XML | `.xml` | — | ✓ | Final Cut Pro XML with embedded subtitle data. Encode only. | | EZ Title | `.txt` | ✓ | ✓ | EZ Title plain-text caption format. | | Eclipse | `.txt` | ✓ | ✓ | Eclipse caption system format. | | QuickTime Text | `.txt` | ✓ | ✓ | QuickTime text track subtitle format. | | PowerPixel Format | `.txt` | ✓ | ✓ | PowerPixel caption format. | | ProCap Transfer | `.txt` | ✓ | ✓ | ProCap transfer format for caption exchange. | | Sofni | `.sub` | ✓ | ✓ | Sofni subtitle format. | | Micro DVD | `.sub` | ✓ | — | Micro DVD subtitle format. Decode only. | | DVD Architect | `.sub` | ✓ | ✓ | Sony DVD Architect subtitle format. | ## Transcription & Speech-to-Text (Decode Only) These profiles decode the JSON output returned by speech-to-text services into CCPRJ for further processing, encoding, and delivery. They are decode-only because they represent raw transcription data, not a delivery format. These profiles are used internally when an Access Provider performs a `transcribe` or `align` API job. | Profile Name | Extension | Provider | |---|---|---| | Deepgram | `.json` | Deepgram | | Assembly AI | `.json` | Assembly AI | | Amazon Transcribe | `.json` | Amazon Web Services | | Google Speech-to-Text | `.json` | Google Cloud | | Rev AI | `.json` | Rev AI | | Speechmatics | `.json` | Speechmatics | | Voicegain | `.json` | Voicegain | | ElevenLabs Scribe | `.json` | ElevenLabs | ## Document & Dialogue List Formats These formats are used to exchange caption content in human-readable document form, often for review, as-broadcast logging, or integration with production scripts. | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Comma-Separated Values (CSV) | `.csv` | ✓ | ✓ | Generic CSV with configurable column mapping. | | JSON | `.json` | — | ✓ | Generic structured JSON output. Encode only. | | JSON Format Custom 01 | `.json` | ✓ | — | Custom JSON variant with a predefined schema. Decode only. | | Rich Text Format Custom 01 | `.rtf` | ✓ | — | Custom RTF dialogue list variant. Decode only. | | As-Broadcast Dialogue List CSV | `.csv` | — | ✓ | As-broadcast dialogue list in CSV format. Encode only. | | As-Broadcast Dialogue List Word | `.docx` | — | ✓ | As-broadcast dialogue list formatted as a Word document. Encode only. | | Dialogue List Custom 01 | `.docx` | — | ✓ | Custom Word dialogue list format. Encode only. | | LMS Transcript | `.docx` | ✓ | ✓ | Learning management system transcript format. | | MS2 Transcript | `.docx` | ✓ | ✓ | MS2 transcript format. | | DVW QC Script | `.xlsx` | ✓ | ✓ | DVW quality control script in Excel. | | DVW Studio Script | `.xlsx` | ✓ | ✓ | DVW studio script in Excel. | | ExAD | `.xlsx` | ✓ | ✓ | ExAD Excel format for audio description and caption exchange. | | Text Transcript | `.txt` | ✓ | — | Plain text transcript. Decode only. | ## Native Format | Profile Name | Extension | Decode | Encode | Notes | |---|---|:---:|:---:|---| | Closed Caption Project (CCPRJ) | `.ccprj` | ✓ | ✓ | The native internal JSON format used by Closed Caption Converter. Inspect the raw CCPRJ or pass pre-built CCPRJ objects directly to the encoder. | | MacCaption Project (CCA) | `.cca` | ✓ | — | MacCaption project archive. Decode only. | --- # Filters Filters are transformation functions that operate on caption data between the decode and encode steps. Every filter receives a Closed Caption Project (CCPRJ) object, applies its transformation, and returns an updated CCPRJ. Most of the filters on this page work consistently regardless of whether you are converting SCC to SRT or TTML to WebVTT, because they operate on CCPRJ rather than on a specific file format. Some advanced panels are not universal filters. **Encoding Options**, **Decoding Options**, **608/708 Options**, **Embed Options**, **V-Chip Information**, and **Program Information** are profile-specific controls that only appear when the selected source or target profile supports them. Filters are configured individually and applied in the order they appear in your job configuration. --- ## Timing & Sync The Timing & Sync filter is the primary tool for all timecode and frame rate operations. It controls the frame rate used to interpret source timecodes, the frame rate written to the target file, and any offset or adjustment applied to event timecodes during processing. The filter exposes a **Default Frame Rate** that is used when the source format does not carry frame rate metadata and Closed Caption Converter cannot automatically detect it. The **Source Frame Rate** can be set explicitly or left on `auto` to let the engine read frame rate from the file. The **Target Frame Rate** determines the frame rate written into the output file. If source and target frame rates differ, all timecodes are mathematically converted. Drop-frame flags can be set independently for source and target. In addition to frame rate conversion, the Timing & Sync filter supports a **Timecode Offset**, which shifts all event in and out times by a fixed SMPTE timecode value — useful for resyncing content to a new programme start. An **Incode** value can also be set to establish a new programme start time that all events are normalised against. Setting Incode to `auto` uses the detected first event as the programme start. Stretch & Sync mode is available for cases where you have a reference point (such as a known dialogue line at a specific time) and need to proportionally scale all timecodes to match. This is useful when a file was created at one frame rate but the timecode numbers were not converted. --- ## Segmentation & Conform The Segmentation & Conform filter is used to extract one or more segments from source caption files and combine them into a single output file. It is essential in NLE-based workflows where a programme is assembled from multiple reels or edited segments, and the caption file must be conformed to match the final edit. Each segment defines a region of the source file to extract using a start and end timecode. Timecodes can be expressed as SMPTE timecode (`HH:MM:SS:FF`), millisecond timecode (`HH:MM:SS.mmm`), seconds (`0.000`), or frame count. Multiple source files with different frame rates can be included in a single segmentation job, and each segment can specify its own source file reference. **Timecode Mode** controls how those end times and black-segment durations are interpreted. **Exclusive** (the default) matches Closed Caption Converter's existing conform behaviour: the end time is the first frame *not* included in the segment. **Inclusive** is for source systems that include the last frame in their duration calculations. When Inclusive is selected, conform adds 1 frame to each file segment's end time and 1 frame to each black segment's duration. The values you enter in the form are left unchanged so they continue to match the source system. When segments are assembled, you can optionally insert blank space between them using the **Frame Gap** setting. This is commonly used to place filler between segments in multi-reel deliveries that require silence between acts or specific timing for ad breaks between programme segments. Although multi-source conform workflows are supported, first-time users will usually find it easier to start with one source asset per segmentation job and expand to multi-source jobs only when the delivery requires it. --- ## Auto Format The Auto Format filter automatically re-wraps caption event text to conform to maximum line and character constraints. It breaks long lines at natural word boundaries and attempts to produce visually balanced subtitle lines. This is most useful after translation workflows (where translated text may be significantly longer than the original) or when converting from a format that has no line-length restrictions into one that does. **Maximum Lines** and **Maximum Characters** define the upper bounds that every caption event must conform to. The engine will split or re-wrap events that exceed these limits. **Minimum Event Duration** sets the shortest allowed event in seconds — events shorter than this after splitting will not be split further. This is especially important when the target format has hard limits. For example, SCC workflows commonly need tighter character-per-line control than WebVTT or SRT. Automatic reformatting can introduce additional lines or events, so tightly timed files should be reviewed after formatting. **Selective Format** mode leaves events that are already within the configured limits unchanged, only reformatting those that exceed them. This is the recommended setting when you want to preserve existing formatting decisions in a file and only correct violations. **Allow Orphan Words** controls whether the formatter may produce a single-word line when text balancing requires it. When disabled, single-word lines (orphans) are merged back with the preceding line even if doing so causes that line to exceed the maximum character limit. --- ## Automatic Reading Speed The Automatic Reading Speed filter adjusts the duration of caption events to ensure they meet reading speed targets. It is designed to make captions readable at a natural pace for viewers, which is especially important after format conversion or when caption timing is generated from transcription. The filter can work in two modes: **Characters Per Second (CPS)** and **Words Per Minute (WPM)**. You set a target CPS or WPM value, and the engine calculates the minimum duration each caption event must be on screen to be readable at that speed. If an event is shorter than the required minimum, its out-time is extended. The filter is aware of gaps between events and will not push an event's out-time past the in-time of the next event. --- ## Search & Replace The Search & Replace filter finds and replaces text strings within caption events. It supports both literal string matching and full regular expression patterns, making it suitable for everything from simple terminology corrections to complex structural transformations of caption text. Each rule specifies a **Find** pattern and a **Replace** value. Rules are evaluated in order. Regular expression mode supports standard ECMAScript regex syntax including capture groups (referenced as `$1`, `$2`, etc. in the replacement string), character classes, and lookahead assertions. Multiple rules can be added to a single filter, allowing you to apply a complete set of corrections in a single pass. This is commonly used to normalise terminology, remove unwanted formatting codes that survive format conversion, or apply company-specific spelling and style policies to caption text. Search & Replace does not ignore downstream line-length or duration constraints. If a replacement makes an event too long for the selected output format, follow it with **Auto Format** or review the encoded result to confirm the event still fits the delivery specification. --- ## Event Gap The Event Gap filter inserts a blank frame gap between adjacent caption events. Many streaming platforms (including Netflix) require a minimum number of blank frames between events to prevent captions from appearing to "flash" when one event immediately follows another. The Event Gap filter automates this correction across an entire file. The **Minimum Gap** setting defines the number of blank frames that must exist between the out-time of one event and the in-time of the next. When the gap between two events is smaller than this value, the out-time of the earlier event is pulled back to create the required gap. The filter accepts **Minimum** and **Maximum** tolerance values — events with a gap already within this range are left unchanged. The filter is **Shot Change Aware**: if shot change data is embedded in the source file, the filter will not pull an event's out-time across a shot change boundary. **Fix Event Overlaps** can be enabled in conjunction with Event Gap to first correct any events that already start before the previous one ends, before applying gap insertion. --- ## Auto Correct Timing The Auto Correct Timing panel is focused on readability-based timing correction. In the current UI it exposes **Enable Reading Speed Correction**, **Maximum CPS**, **Minimum Frame Gap**, and minimum/maximum event duration controls. Use this panel when a file needs timing adjustments to meet reading-speed requirements after translation, editing, or format conversion. For frame rate conversion, offsets, and programme-start adjustments, use **Timing & Sync** instead. --- ## Caption Style The Caption Style panel provides cleanup and normalisation controls for common broadcast-caption text treatment operations rather than a full font and positioning style system. The available controls include **Convert To Pop-On**, **Merge By Time**, **Merge Sources**, **Split Speakers On Same Line**, **Speaker Prefix**, **Remove Color**, and **Remove Formatting**. These are useful when you need to simplify a source file before converting it to a delivery format with stricter styling support. **Merge Sources** is for multi-source jobs: it combines every source's events into one Event Group and sorts them by start timecode, instead of appending files sequentially. It does not collapse overlapping cues; that remains **Merge By Time**, which still runs per source first. --- ## Reposition The Reposition filter adjusts the screen position of caption events. It supports shifting events to a new row or screen region, applying safe-area offsets, and normalising position data that may have been carried through from a source format with a different coordinate system. Position rules can be applied globally across all events or selectively based on the current position of each event. This is useful when converting between formats with incompatible positioning schemes — for example, converting a subtitle file that uses absolute pixel coordinates into a broadcast caption format that uses row numbers. Position rules can be applied globally across all events or selectively based on the current position of each event. Typical use cases include moving centre-positioned captions to bottom-centre safe areas, normalising left-justified captions to centred alignment, or constraining captions to a specific row and column range for broadcast delivery. --- ## Remove Forced Subtitles The Remove Forced Subtitles filter strips forced subtitle events from a caption file. Forced subtitles are events that are marked as appearing even when the viewer has subtitles disabled — they are typically used for translated dialogue, signs, or on-screen text in foreign languages. Some delivery workflows require a version of the subtitle file that contains only the forced events, and others require the full subtitle track with forced events removed. The filter can be configured to either remove all forced events or retain only forced events, producing the correct output for either delivery scenario without needing to manually edit the source file. --- ## Automatic QC Automatic QC checks caption events against the tests you choose and writes a JSON report. QC does not change caption events or the encoded file. Each job gets a QC status of **pass**, **warn**, or **fail**, plus an error count. **Convert** jobs always produce their converted output, whatever the QC status. The panel appears for **Convert** and **Verify** jobs. Choosing **Verify** in the job type dropdown sets `job_type` to `qc` and runs QC without encoding; the primary button becomes **Verify**. If no tests are configured yet, the **Netflix English (Adult)** preset is added. ### Tests, levels and thresholds Every check is a separate **test**, for example *Max Characters Per Line*, *Frame Gap*, *Sequential Timing* or *XML Entity Escaping*. To build a test plan: 1. Choose a **Preset** to start from a ready-made plan (Netflix English Adult, Netflix English Children, or Broadcast 608 Captions), or start from an empty list. 2. Use **Add a test** to add individual tests. They are grouped into Text, Timing, Formatting and Technical (XML). 3. For each test, set its parameters (for example **Max characters**), its **Level**, and its **Threshold**. The **Level** sets how a failing test affects the job: | Level | Effect on the QC status | |---|---| | **Critical** | The job's QC status is **fail**. | | **Warning** | The job's QC status is **warn**, unless a critical test also fails. | | **Info** | The errors are reported but the QC status is not changed. | The **Threshold** is how many errors are allowed before the level applies. A threshold of `0` or `1` means the first error counts. A threshold of `3` means three or more errors are needed. You can add the same test more than once, for example *Max Characters Per Second* at 17 as a warning and at 20 as critical. Turn a test's switch off to keep it in the plan without running it. The full list of tests and their parameters is in [Automatic QC Tests](https://www.closedcaptionconverter.com/docs/api/qc-tests). ### QC Stage **QC Stage** controls *when* content tests run. Both stages use the same tests. The stage only changes which events are checked and which frame rate those checks use. Technical tests (the XML checks) and **Sequential Timing** always check the source file. | Stage | Content test events | Content test frame rate | Technical and source-order tests | |---|---|---|---| | **Pre-processing** (default) | Source captions, immediately after decode, before any filters | Source frame rate | Always the source file | | **Post-processing** | Captions after filters, conform, offset, Auto Format, and timing correction, immediately before encode | Target frame rate | Always the source file | Use **Pre-processing** to check the file as it was delivered to you. Use **Post-processing** when you apply corrective filters first, for example **Auto Format** and **Event Gap**, and want QC to verify that the processed captions meet the delivery specification. In the Job Description JSON, the stage is `qc.stage` and the tests are `qc.tests`. See [Automatic QC Tests](https://www.closedcaptionconverter.com/docs/api/qc-tests) for the schema. Configurations saved with the older **Content QC** / **Technical QC** settings are converted to tests automatically. ### QC Report On a single-file job, the report appears in the preview **QC Report** tab. The tab shows: - the QC status and the error count; - a table of tests with their error counts; - every error with its event number, timecode and text. Select **Show JSON** to see the raw report. On a multi-file job, Closed Caption Converter downloads `{filename}_report.json` for each source. When you run a **Verify** job, a notification shows the status. **Where the status appears outside the app:** - **API:** the job response includes `qc_status`, `qc_errors` and the full `qcReport`. - **Job history:** the **Jobs** page shows a QC badge next to the job status. - **QC jobs:** a dedicated QC job (`job_type: "qc"`) writes the report as `{jobId}_report.json` and does not encode a caption file. - **CLI:** the CLI writes the same JSON report and prints a one-line summary. --- ## 708 Options The **708 Options** panel appears when the selected target supports CEA-708 service mapping. It lets you map input caption files to **Program A** through **Program F** so you can build multi-service HD caption outputs. This is an output-specific panel rather than a universal filter, so it only appears when the chosen target profile supports 708 data. --- ## 608 Options The **608 Options** panel appears when the selected target supports CEA-608 channel mapping. It lets you map input caption files to **CC1**, **CC2**, **CC3**, and **CC4** for SD or mixed 608/708 broadcast outputs. Like 708 Options, this is a target-specific output panel and will only appear for compatible formats. --- ## Window The Window filter defines the safe-area window within which caption text must be positioned. It sets the width and height of the caption area in columns and rows, which the encoder uses to constrain event placement relative to the displayable area of the screen. For broadcast formats, the standard window is 32 columns × 15 rows (the CEA-608/708 grid). For subtitle formats, the window is used to calculate the percentage-based position values written into TTML or WebVTT. Adjusting the window is most commonly required when converting between formats with different safe-area definitions or when a delivery specification requires a specific caption area inset from the screen edges. --- ## File Encoding The File Encoding filter sets the character encoding used when writing text-based output files. Most modern subtitle formats use UTF-8, but some legacy broadcast systems and older players require files in Latin-1 (ISO-8859-1), Windows-1252, or other encodings. Selecting the correct file encoding is important for files that contain accented characters, special symbols, or non-Latin scripts. Writing a UTF-8 file when a legacy system expects Latin-1 will produce corrupted characters in the output. The filter also controls the line ending style (CRLF or LF), which may be significant for systems that are sensitive to line ending format. --- ## Embed Options Embed Options appears only for container-capable output workflows. It controls whether captions are wrapped as **MXF Embed**, **AAF Embed (SC)**, **AAF Embed (Linked)**, or left as **None**, depending on the selected target profile. Because this is tied to the target format, treat it as an output option rather than a general-purpose filter. --- ## V-Chip Information V-Chip Information is an output-specific metadata panel for broadcast targets that support XDS data. Enable it when you need to include a rating system such as **TV Parental Guideline**, **MPAA**, **Canadian English**, or **Canadian French**, along with any supported content descriptors. --- ## Program Information Program Information is another output-specific metadata panel for broadcast targets that support XDS or similar embedded metadata. It lets you include fields such as **Program Name**, **Program Length**, and advisory keyword groups used for downstream identification and logging. If you do not see **V-Chip Information** or **Program Information**, select a target profile that supports embedded broadcast metadata first. --- # Encoding & Decoding Options Encoding and decoding options are format-specific settings that control how a profile reads or writes a caption file. They appear automatically in both the web application and the Job Description JSON when a profile that supports them is selected. Options vary considerably by format — some profiles have no configurable settings at all, while complex binary formats like EBU-STL expose dozens of metadata fields. In the web application, options appear as collapsible panels beneath the source and target profile selectors. In the Job Description JSON, they are passed in the `decoding_options` and `encoding_options` arrays respectively. Some advanced controls that users may think of as filters are actually profile-specific encoding options. Examples include **608 Options**, **708 Options**, **Embed Options**, **V-Chip Information**, and **Program Information**. These only appear when the selected target format supports them. ## Metadata Passthrough Source header metadata is stored on the caption project at decode time, then copied into the target when an encoding option's `selected` value is the string `"auto"`. Explicit values always win, and there is no separate passthrough toggle. Profile defaults do not copy source values — for example Language Code is typically `en` or `English`, and EBU-STL Country of Origin defaults to `Canada`. `"auto"` is case-sensitive. In the web application, type `auto` into a text encoding option, or set `"selected": "auto"` in the **Job Description** JSON. List options such as EBU-STL **Language Code**, **Country of Origin**, and IMSC Rosetta **Default Outline** cannot pick `auto` from the dropdown; send it in the Job Description or the API instead. ### What is copied Decode populates canonical metadata from: - **TTML-family XML headers** (`xml`, `ttml`, `dfxp`, `itt`, and related profiles): `xml:lang`, `ttm:title`, `ttm:desc`, `ttm:copyright`, programme name, and EBU-TT programme / publisher fields. Only the root `` and `` are read. - **EBU STL** GSI header: language, original and translated programme / episode titles, translator, editor, publisher, subtitle list reference, and country of origin. - **IMSC Rosetta**: XML header fields plus font size (`rh`) and default outline. - **ESEF**: title and author. Plain-text formats such as SubRip, WebVTT, and Scenarist SCC generally contribute no document metadata on this path. At encode, `"auto"` is resolved only when the **target profile** exposes a mapped option: | Encoding option | Copied from | |---|---| | Language Code | Source language (BCP-47; converted to the EBU language list for STL) | | Program Name, Program Title, Programme Title, Title | Programme title | | Episode Title | Episode title | | Translated Program Title, Translated Programme Title | Translated programme title | | Translated Episode Title | Translated episode title | | Translator, Translator's Name, Translator's Contact Details | Translator metadata | | Editor's Name, Editor's Contact Details | Editor metadata | | Publisher | Publisher | | Subtitle List Ref Code | Subtitle list reference | | Country of Origin | Country of origin (must match the target list) | | Description | Description | | Copyright | Copyright | | Author | Author | | Font Size, Default Outline | IMSC Rosetta font size (`rh`) and outline style (Rosetta targets only) | Richest targets include EBU STL (GSI fields), IMSC Rosetta (language, programme name, font size, outline), most TTML-family profiles (language, and often title / description / copyright), Spruce STL, ProCap Transfer, and ESEF. If the target has no matching option — for example SubRip or WebVTT — that field is not written. ### Resolution order 1. An explicit `selected` value (for example `"de"`) is never overwritten. 2. `"auto"` with valid source metadata (including list membership and BCP-47 → EBU language conversion). 3. The profile default when `"auto"` is set but no usable metadata exists (for example STL Language Code falls back to `English`). 4. The option is dropped when `"auto"` is set, there is no metadata, and the profile default is empty — the encoder then uses its own fallback. Format-specific `auto` values that have another meaning — Scenarist **Channel**, Scenarist **Timecode Format**, Cavena **Font Family**, and PAC **Code Page** — are left as `"auto"` and are not filled from document metadata. When several sources are merged, metadata is taken from the first event group. Language is converted across formats — for example EBU STL `French` becomes TTML `fr`, and TTML `fr-CA` becomes STL `French` when the target list supports it. ### API example The example below copies language and programme title from a TTML source into EBU STL. Contrast this with passing `"English"` or `"Canada"`, which would overwrite the source values. ```json { "source_profile": "Timed-Text Markup Language", "target_profile": "EBU STL", "encoding_options": [ { "name": "Language Code", "selected": "auto" }, { "name": "Program Title", "selected": "auto" }, { "name": "Translator's Name", "selected": "auto" }, { "name": "Country of Origin", "selected": "auto" } ] } ``` Omitted options still use their profile defaults. You do not need every mapped field — only the options you set to `"auto"` are filled from source metadata. The same `encoding_options` array can be reused across files; Closed Caption Converter does not mutate `"auto"` in the Job Description. ## Decoding Options Decoding options control how a source file is read and interpreted during the decode step. The most common decoding options are channel selection, metadata extraction, and control over which content layers are imported. The examples below are illustrative rather than exhaustive. ### Scenarist (SCC) — Decode Options | Option | Type | Default | Description | |---|---|---|---| | Channel | List | `auto` | Specifies which CEA-608 channel to read from the file. Options are `auto`, `ch01`, `ch02`, `ch03`, and `ch04`. When set to `auto`, the decoder reads the most populated channel. | ### MacCaption 608/708 (MCC) — Decode Options | Option | Type | Default | Description | |---|---|---|---| | Channel | List | `ch01` | Specifies which caption channel or service to read. Options include `ch01`–`ch04` (608 channels) and `programA`–`programF` (708 services). | ### EBU-STL — Decode Options | Option | Type | Default | Description | |---|---|---|---| | Decode Speakers By Color | List | `false` | When enabled, the STL colour attribute is used to identify different speakers and populate the CCPRJ speaker object. | | Speaker Identifier | Text | _(empty)_ | A text string used to identify speaker names within subtitle text. If the text of an event begins with this string, the prefix is treated as a speaker label and extracted accordingly. | | Insert Speaker Identifier | List | `false` | When enabled, the decoded speaker name is prepended to each event's text in the output. | | Speaker Is Greater Than | Number | `1` | The minimum number of characters a speaker identifier must contain to be recognised. | ### Cavena 890 — Decode Options | Option | Type | Default | Description | |---|---|---|---| | Decode Line 1 | List | `yes` | Whether to decode the first subtitle line track from the binary file. | | Decode Line 2 | List | `yes` | Whether to decode the second subtitle line track. | ### Text Transcript — Decode Options | Option | Type | Default | Description | |---|---|---|---| | Max Characters Per Line | Number | `32` | The maximum characters per line used when segmenting a plain-text transcript into timed events. | | Max Lines Per Event | Number | `2` | The maximum number of lines per event generated from the transcript. | | Reading Rate | Number | `20` | The reading rate in characters per second used to calculate event durations from the transcribed text. | | Split on Comma | List | `no` | Whether to create a new event at each comma. | | Split on Punctuation | List | `yes` | Whether to create a new event at each sentence boundary. | | Block Import | List | `no` | When enabled, imports paragraphs (blank-line-separated blocks) as single events rather than splitting by punctuation. | --- ## Encoding Options Encoding options control how the target file is written. They cover metadata fields required by the format specification, formatting preferences, channel assignments, and structural settings. ### Scenarist (SCC) — Encode Options | Option | Type | Default | Description | |---|---|---|---| | Channel | List | `ch01` | The CEA-608 channel to write caption data into. Options: `ch01`, `ch02`, `ch03`, `ch04`. Use `ch01` for the primary language and `ch03` for a secondary language in dual-language deliveries. | | Line Endings | List | `unix` | The line ending style of the output text file. Options: `windows` (CRLF), `unix` (LF), `macintosh` (CR). | | Timecode Format | List | `auto` | Controls whether semicolons (drop-frame) or colons (non-drop-frame) are used in timecode strings in the SCC file. `auto` selects based on the job frame rate. | ### MacCaption 608/708 (MCC) — Encode Options | Option | Type | Default | Description | |---|---|---|---| | MCC Version | List | `2.0` | The MCC file format version to write. Version 2.0 supports both CEA-608 and CEA-708 data. Version 1.0 is a legacy option for older decoders. | | Compress Output | List | `yes` | Whether to apply MCC's native run-length compression to the binary packet data in the output file, which reduces file size. | ### EBU-STL — Encode Options EBU-STL has the most extensive set of encoding options because the format mandates a large header block (the GSI block) containing programme and distribution metadata. All text fields in the GSI block can be populated directly. Set a mapped field to `auto` to copy matching source metadata instead of typing a value; see [Metadata Passthrough](https://www.closedcaptionconverter.com/docs/encoding-decoding-options#metadata-passthrough). Language Code and Country of Origin are list options, so `auto` must be sent in the Job Description JSON or the API. | Option | Type | Default | Description | |---|---|---|---| | Display Standard Code | List | `Open subtitling` | The STL display standard: `Undefined`, `Open subtitling`, `Level-1 teletext`, or `Level-2 teletext`. | | Double Height Characters | List | `no` | Whether to use double-height character rendering for the subtitle text. | | Program Title | Text | _(empty)_ | Programme title written into the GSI block. Set to `auto` to copy the source programme title. | | Episode Title | Text | _(empty)_ | Episode title written into the GSI block. | | Translated Program Title | Text | _(empty)_ | Translated programme title for the GSI block. | | Translated Episode Title | Text | _(empty)_ | Translated episode title for the GSI block. | | Translator's Name | Text | _(empty)_ | Translator name for the GSI block. | | Translator's Contact Details | Text | _(empty)_ | Contact details for the translator. | | Subtitle List Ref Code | Text | _(empty)_ | Reference code for the subtitle list. | | Publisher | Text | _(empty)_ | Distributor or publisher name. | | Editor's Name | Text | _(empty)_ | Subtitling editor name. | | Editor's Contact Details | Text | _(empty)_ | Editor contact details. | | Language Code | List | `English` | The language of the subtitle content, written into the GSI language code field. Full list of EBU-defined languages is supported. Set to `auto` in the Job Description or API to copy the source language. | | GSI Character Set | List | `Multilingual` | The GSI character set code. Options: `United States`, `Multilingual`, `Portuguese`, `Canada-French`, `Nordic`. | | Character Code Table | List | `Latin` | The character code table used for subtitle text encoding. Options: `Latin`, `Cyrillic`, `Arabic`, `Greek`, `Hebrew`. | | Country of Origin | List | `Canada` | The country of origin for the STL file's GSI block, selected from the full ISO 3166 country list. Set to `auto` in the Job Description or API to copy the source country when it matches the list. | | SOM (Start of Message) | Text | `00:00:00:00` | The programme start timecode written into the GSI block. | | Max Number of Rows | Number | `23` | Maximum number of subtitle rows, written into the GSI block. | | Max Number of Characters Per Row | Number | `40` | Maximum characters per row, written into the GSI block. | | Include Blank Subtitle At Start | List | `no` | When enabled, a blank subtitle event is inserted at the beginning of the file, which some STL systems require. | ### Cavena 890 — Encode Options | Option | Type | Default | Description | |---|---|---|---| | Line 1 Language | List | `English` | Language of the first subtitle track: Danish, Norwegian, English, Russian, Greek, Romanian, Swedish, Arabic, Hebrew, Traditional Chinese, Simplified Chinese. | | Line 2 Language | List | `English` | Language of the second subtitle track. | | Font Family Line 1 | List | `auto` | The font family code for the first track, corresponding to Cavena hardware font IDs. | ### Text Transcript — Encode Options | Option | Type | Default | Description | |---|---|---|---| | Include Speaker Name | List | `no` | Whether to prepend the speaker name to each event's text in the output. | | Include Timestamp | List | `no` | Whether to include a timestamp at the start of each line. | | Split On Event Gap | Number | `4` | The minimum gap in seconds between events that triggers a paragraph break in the output text. | | Max Words | Number | `99999` | Maximum number of words per output file. | | Event Prefix | Text | _(empty)_ | A string prepended to each event in the output. | | Event Suffix | Text | _(empty)_ | A string appended to each event in the output. | | Encode Formatting | List | `false` | Whether to include inline formatting codes (italic, bold) in the output text. | ### TTML / DFXP / IMSC Variants — Common Encode Options Most TTML-family profiles expose the following options where applicable. Set Language Code, Title, Description, or Copyright to `auto` to copy matching source metadata; see [Metadata Passthrough](https://www.closedcaptionconverter.com/docs/encoding-decoding-options#metadata-passthrough). Several TTML-family profiles also stamp the Closed Caption Converter version into the encoded file; that stamp is not an encoding option. See [Profiles & Formats](https://www.closedcaptionconverter.com/docs/profiles-formats#closed-caption-converter-version-in-encoded-files). | Option | Type | Default | Description | |---|---|---|---| | Language Code | Text | `en` | The BCP-47 language tag written into the TTML `xml:lang` attribute (e.g. `en`, `fr`, `de`, `ja`). Set to `auto` to copy the source language. | | Timebase | List | `media` | Whether timecodes are expressed relative to media time (`media`) or wall-clock time (`clock`). | | Title | Text | _(empty)_ | The programme title written into the TTML metadata header. Set to `auto` to copy the source title. | | Description | Text | _(empty)_ | Description metadata written into the TTML header. Set to `auto` to copy the source description. | | Copyright | Text | _(empty)_ | Copyright string written into the TTML header. Set to `auto` to copy the source copyright. | ## Passing Options in the API When submitting a Job Description to the API, encoding and decoding options are passed as the `encoding_options` and `decoding_options` fields respectively. Each field is an **array of option objects** — the same structure returned by the `GET /help/profiles/all` endpoint. Every option object contains four fields: | Field | Description | |---|---| | `name` | The option name, matching the label shown in the web application. | | `type` | The input type: `list`, `text-input`, `number-input`, or `textarea`. | | `values` | For `list` types, an array of allowed values. For other types, an empty string. | | `selected` | The value to use for this conversion. Set this to override the default, or to `"auto"` on mapped metadata fields to copy matching source header values. | The easiest way to construct the options array is to call `GET https://api.closedcaptionconverter.com/help/profiles/all`, find your profile, copy the `decode` or `encode` array from the response, and then set the `selected` field on any options you want to change. The example below converts from EBU STL to Scenarist V1.0, using the `ch02` channel on the target: ```json { "source_profile": "EBU STL", "target_profile": "Scenarist V1.0", "decoding_options": [ { "name": "Decode Speakers By Color", "type": "list", "values": [true, false], "selected": false }, { "name": "Speaker Identifier", "type": "text-input", "values": "", "selected": "" }, { "name": "Insert Speaker Identifier", "type": "list", "values": [true, false], "selected": false }, { "name": "Speaker Is Greater Than", "type": "number-input", "values": "", "selected": 1 } ], "encoding_options": [ { "name": "Channel", "type": "list", "values": ["ch01", "ch02", "ch03", "ch04"], "selected": "ch02" }, { "name": "Line Endings", "type": "list", "values": ["windows", "unix", "macintosh"], "selected": "unix" }, { "name": "Timecode Format", "type": "list", "values": ["colon", "semi-colon", "auto"], "selected": "auto" } ] } ``` You do not need to include every option in the array — omitted options use their profile defaults. However, if you do include an option object, the entire object (including `name`, `type`, and `values`) must be present and accurate; only the `selected` field needs to differ from the default.