# Subtitle Timing Quality Gate (`ceddl/subtitle-timing-quality-gate`) Actor

Audit bounded subtitle cue exports for invalid timing, overlaps, reading-speed risk, empty text, and duplicate cue IDs.

- **URL**: https://apify.com/ceddl/subtitle-timing-quality-gate.md
- **Developed by:** [Cedric Günther](https://apify.com/ceddl) (community)
- **Categories:** Automation, Developer tools, Open source
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 subtitle timing quality gate completeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Subtitle Timing Quality Gate

Audit bounded subtitle cue exports for invalid timing, overlaps, reading-speed risk, empty text, and duplicate cue IDs. The Actor works only on caller-supplied bounded records and returns stable machine-readable evidence. It is built for data operations teams, integration engineers, quality assurance reviewers. The main result is structured, deterministic evidence that can be consumed from the default dataset or an Apify automation.

### When to use this Actor

- Audit subtitle cue timing: Check cue durations, ordering, empty text, overlaps, and reading speed.
- Find overlapping subtitle cues: Locate cue intervals that overlap the preceding exported cue.
- Check subtitle reading speed: Flag cue text whose character rate exceeds the bounded delivery threshold.

### How it works

- Validate the top-level input and every bounded subtitle cue record against the Actor-specific contract.
- Apply identity, field, and product-specific consistency rules without external calls.
- Sort evidence deterministically, persist the detailed report, and emit the summary through the retry-safe PPE boundary.

The Actor validates only the declared product contract. It does not infer facts outside the supplied data or claim outcomes that the source material cannot prove.

### Quick start

1. Open the Actor's **Input** tab or create a Task from one of the public examples.
2. Paste or adapt this bounded example.
3. Click **Start** and inspect the default dataset plus the output links shown on the run page.

```json
{
  "auditId": "sample-subtitle-timing-quality-gate",
  "records": [
    {
      "cueId": "c1",
      "startMs": 0,
      "endMs": 1800,
      "text": "Welcome to the product tour."
    },
    {
      "cueId": "c2",
      "startMs": 1700,
      "endMs": 2600,
      "text": "This cue overlaps the first cue and is intentionally long for its duration."
    }
  ]
}
```

Expected result: a deterministic summary and Actor-specific evidence for the bounded fixture.

### Input

The quick-start example is intentionally small. These are the material controls; the Input tab remains authoritative for the complete current schema.

| Field | Purpose and format | Default | Important bounds or interaction |
|---|---|---|---|
| `auditId` | Stable caller-defined label used to route and reconcile the audit output. | No implicit default | minimum length 1; maximum length 120 |
| `records` | Bounded normalized subtitle cue records evaluated by the Actor-specific rules. | No implicit default | minimum items 1; maximum items 1000 |
| `maxRecords` | Optional lower safety cap for this run without raising the product maximum. | No implicit default | minimum 1; maximum 1000 |

Unknown top-level fields and invalid field combinations fail validation rather than being guessed.

### Output

The default dataset contains typed records. The run's Output tab links the dataset and any key-value-store reports declared by the current output schema.

| Field | Meaning |
|---|---|
| `recordType` | Discriminates finding, change, duplicate-group, and summary records. |
| `auditId` | Caller-defined analysis context copied to every output record. |
| `code` | Stable product-specific finding code. |
| `severity` | ERROR or WARNING level for a quality finding. |
| `stableKey` | Stable normalized identity for comparison evidence. |
| `changeType` | ADDED, REMOVED, or CHANGED when snapshot comparison applies. |
| `findings` | Total findings in the summary. |
| `errors` | Number of ERROR findings. |
| `warnings` | Number of WARNING findings. |
| `engineVersion` | Version of the deterministic analysis engine. |

Representative current-schema dataset item:

```json
{
  "recordType": "finding",
  "auditId": "sample-subtitle-timing-quality-gate",
  "code": "SAMPLE_EVIDENCE",
  "severity": "WARNING",
  "message": "Representative bounded finding.",
  "engineVersion": "1.0.0"
}
```

When no defects or material changes are found, the run succeeds with a summary record and zero findings; absence of findings is not treated as failure.

### Pricing and billing

This Actor uses `PAY_PER_EVENT`; platform usage is included in event prices. A charge is eligible only after the billable unit described below is durably completed. Validation failures and the non-billable failure classes in the product contract do not emit the custom completion event. The current live policy uses the same event price at every Store tier; no tier discount is active. The Apify **Pricing** tab is authoritative if a later approved pricing change takes effect.

| Event | What triggers it | FREE | BRONZE | SILVER | GOLD | PLATINUM | DIAMOND |
|---|---|---:|---:|---:|---:|---:|---:|
| `subtitle-batch-audited` | One bounded subtitle cue audit converted into durable evidence. | $0.01000000 | $0.01000000 | $0.01000000 | $0.01000000 | $0.01000000 | $0.01000000 |
| `apify-actor-start` | Platform-managed Actor start event. | $0.00005000 | $0.00005000 | $0.00005000 | $0.00005000 | $0.00005000 | $0.00005000 |

The Actor does not have Task-specific prices: public Tasks use this same live Actor pricing. Third-party costs are not implied; see the data and security section for external services actually contacted.

### Limits and bounds

- At most 1,000 subtitle cue records are accepted per run; maxRecords may set a lower cap.
- The serialized semantic input is capped at 10 MB and unknown top-level controls fail closed.
- Only normalized caller-supplied records are inspected; source fetching, authentication, and unbounded recursion are outside version 1.

These are product-facing limits, not targets. Use smaller inputs when you need faster feedback or simpler evidence.

### Failure and edge-case behavior

- Invalid top-level input, missing required fields, unsupported value shapes, or over-limit inputs fail before the custom event.
- Quality defects inside valid records are returned as findings and do not make the infrastructure run fail.
- If the PPE spending limit cannot cover the completion event, billable output is not emitted.

Operationally:

- Keep stable identifiers across repeated exports.
- Normalize source-specific structures before calling the Actor.
- Treat zero findings as a successful bounded preflight, not a certification.

### Use with Tasks and automation

Public Tasks provide reusable saved inputs for distinct supported workflows. Start with the closest Example Task, review its visible fields and scope caveat, then save your own Task for schedules or repeated runs. Do not treat an Example Task as evidence that unsupported behavior exists.

### Integration and API usage

Every saved Task can be started manually, through the Apify API, or from an Apify schedule. Run-completion webhooks can notify a downstream system after output is durable. Actor-to-Actor calls should consume the typed dataset/output links instead of scraping the Store page.

- Run a saved Task after producing the normalized export and route findings by recordType and code.
- Use the inputHash and stable identifiers for downstream reconciliation.
- Run-completion webhooks can notify the next review or import step after output is durable.

No third-party integration is claimed unless it is named above and supported by the current product contract.

### Data, privacy, and security

- Input and evidence are written only to the run storage configured by Apify.
- No external service is contacted and no credentials are required.
- Use appropriate storage retention for personal, financial, or operational records.

Set Apify storage retention and access according to the sensitivity of your inputs and outputs. This documentation does not create legal, privacy, compliance, or security certification.

### Support and known limitations

- Version 1 does not fetch or parse raw source files.
- Preflight rules do not replace authoritative registry, legal, accounting, archival, or standards validation.
- Source-specific semantics outside documented fields are not inferred.

For support, use the [Actor Issues page](https://apify.com/ceddl/subtitle-timing-quality-gate/issues). Include the run ID, a minimal reproducible input with sensitive values removed, the failing record or error code, and what you expected. Do not post credentials, private source files, customer data, or full confidential payloads.

# Actor input Schema

## `auditId` (type: `string`):

Stable caller-defined identifier copied to every output record.

## `records` (type: `array`):

Bounded normalized subtitle cue records to audit.

## `maxRecords` (type: `integer`):

Optional lower safety cap; the product maximum remains 1,000.

## Actor input object example

```json
{
  "auditId": "sample-subtitle-timing-quality-gate",
  "records": [
    {
      "cueId": "c1",
      "startMs": 0,
      "endMs": 1800,
      "text": "Welcome to the product tour."
    },
    {
      "cueId": "c2",
      "startMs": 1700,
      "endMs": 2600,
      "text": "This cue overlaps the first cue and is intentionally long for its duration."
    }
  ]
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

## `reports` (type: `string`):

No description

## `output` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "auditId": "sample-subtitle-timing-quality-gate",
    "records": [
        {
            "cueId": "c1",
            "startMs": 0,
            "endMs": 1800,
            "text": "Welcome to the product tour."
        },
        {
            "cueId": "c2",
            "startMs": 1700,
            "endMs": 2600,
            "text": "This cue overlaps the first cue and is intentionally long for its duration."
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ceddl/subtitle-timing-quality-gate").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "auditId": "sample-subtitle-timing-quality-gate",
    "records": [
        {
            "cueId": "c1",
            "startMs": 0,
            "endMs": 1800,
            "text": "Welcome to the product tour.",
        },
        {
            "cueId": "c2",
            "startMs": 1700,
            "endMs": 2600,
            "text": "This cue overlaps the first cue and is intentionally long for its duration.",
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("ceddl/subtitle-timing-quality-gate").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "auditId": "sample-subtitle-timing-quality-gate",
  "records": [
    {
      "cueId": "c1",
      "startMs": 0,
      "endMs": 1800,
      "text": "Welcome to the product tour."
    },
    {
      "cueId": "c2",
      "startMs": 1700,
      "endMs": 2600,
      "text": "This cue overlaps the first cue and is intentionally long for its duration."
    }
  ]
}' |
apify call ceddl/subtitle-timing-quality-gate --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ceddl/subtitle-timing-quality-gate"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/nY5JofxVY5Vm00bdG/builds/uyZhYK1QD0F22FgrB/openapi.json
