# RTL Subtitle Fixer (Arabic, Hebrew, Persian, Urdu) (`inkbridge/rtl-subtitle-fixer`) Actor

Fix punctuation, numbers and mixed English in right-to-left SRT and WebVTT subtitles. Reads UTF-8, Windows-1255 and Windows-1256; returns UTF-8 SRT and VTT plus a report.

- **URL**: https://apify.com/inkbridge/rtl-subtitle-fixer.md
- **Developed by:** [Inkbridge Studio](https://apify.com/inkbridge) (community)
- **Security:** Limited permissions
- **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 file fixeds

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

## RTL Subtitle Fixer

Fixes right-to-left subtitle files (Arabic, Hebrew, Persian, Urdu) whose punctuation, numbers or English words show up on the wrong side in some players and editors. Give it SRT or WebVTT files by URL or pasted text. You get a corrected SRT, a corrected VTT and a short report.

### What it fixes

- **Line direction.** Each right-to-left line is wrapped in Unicode embedding marks (RLE at the start, PDF at the end), so a player that assumes left-to-right text still lays the line out right-to-left. Full stops, question marks and commas then land at the left end of the line, where a reader expects them. Numbers, times such as 10:30, and English words inside the line keep their own reading order.
- **Multi-line cues.** Every line of a cue is wrapped on its own.
- **Reversed punctuation (optional).** With `repairReversed` on, a closing mark at the start of a line (`.مرحبا`) moves to the end, and an opening bracket at the end of a line moves to the start. This is for files an earlier tool damaged. Leave it off otherwise.
- **Encodings.** Reads UTF-8 with or without a BOM, UTF-16 with a BOM, Windows-1256 (Arabic) and Windows-1255 (Hebrew). Output is always UTF-8.
- **Timing lines.** Copied unchanged. When the output format differs from the input (VTT in, SRT out, or the reverse), only the millisecond separator changes (`,` or `.`), a missing hour is added for SRT, and VTT cue settings such as `align:end` are dropped from the SRT.
- **Other lines.** Lines with no right-to-left letters, or with more Latin than right-to-left letters, are left as they are. `<i>` tags and `{\an8}` positioning stay outside the wrap.
- **Running it twice changes nothing.** You can feed the output back in.

### What it does not do

- It does not burn subtitles into video, and it does not shape or restyle letters.
- It does not translate, retime, or fix spelling.
- It cannot rescue text that was fully reversed letter by letter.
- Embedding marks are invisible characters. A player or editor that strips them, or that draws its own direction logic on top, may still show the line wrongly.
- The `repairReversed` rule is a heuristic. It skips lines that already end with punctuation and leading ellipses (`...`), so it can miss some damage and should be checked on a sample.
- Persian and Urdu use the same rules as Arabic. Only Arabic and Hebrew were used in testing.
- Windows-1255 and Windows-1256 are told apart by counting right-to-left letters, so a very short file may be guessed wrongly. Check the `inputEncoding` field in the report.

### How it was tested

Results depend on the player. This was **not tested on Plex, Premiere Pro, Emby, Infuse, VLC or any other real player or editor.** What was done:

- Unit tests with Arabic and Hebrew lines (punctuation, numbers, mixed English, tags, VTT and SRT, all supported encodings, running twice).
- Each fixed line was run through the Unicode bidirectional algorithm with a left-to-right base direction, which imitates a player that forces left-to-right. The result matches how the plain line looks in a correct right-to-left player, and the unfixed line does not.
- Before and after lines were drawn to an image and checked by eye, using the same simulation.

If a player ignores direction marks, try the repair option or tell us in an issue which player and what you see.

### Input

| Field | Meaning |
| --- | --- |
| `subtitleUrls` | Public URLs of `.srt` or `.vtt` files |
| `subtitleText` | SRT or WebVTT text pasted in, handled as one more file |
| `repairReversed` | Move reversed punctuation back (default off) |

### Output

One dataset row per file: `source`, `srt`, `vtt`, `report`, `error`. The report has `inputFormat`, `inputEncoding`, `cues`, `linesFixed`, `linesLeftAlone` and `repairReversed`. A file that cannot be read gets a row with `error` and does not stop the others. Files up to 20 MB are accepted.

### Pricing

Pay per event: one charge for each subtitle file converted, nothing for files that fail.

# Actor input Schema

## `subtitleUrls` (type: `array`):

Public URLs of .srt or .vtt files, one per line.

## `subtitleText` (type: `string`):

SRT or WebVTT text pasted here is processed as one more file. You can use this, the URLs above, or both.

## `repairReversed` (type: `boolean`):

Turn this on when an earlier tool moved punctuation to the wrong end, for example a full stop at the start of an Arabic line. Closing marks at the start of a line move to the end, and opening brackets at the end move to the start. Leave it off for files that were not damaged this way.

## Actor input object example

```json
{
  "subtitleUrls": [],
  "subtitleText": "1\n00:00:01,000 --> 00:00:03,500\nمرحبا بالعالم!\n\n2\n00:00:04,000 --> 00:00:06,000\nاشتريت 3 كتب من Amazon.",
  "repairReversed": false
}
```

# Actor output Schema

## `results` (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 = {
    "subtitleUrls": [],
    "subtitleText": `1
00:00:01,000 --> 00:00:03,500
مرحبا بالعالم!

2
00:00:04,000 --> 00:00:06,000
اشتريت 3 كتب من Amazon.`
};

// Run the Actor and wait for it to finish
const run = await client.actor("inkbridge/rtl-subtitle-fixer").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 = {
    "subtitleUrls": [],
    "subtitleText": """1
00:00:01,000 --> 00:00:03,500
مرحبا بالعالم!

2
00:00:04,000 --> 00:00:06,000
اشتريت 3 كتب من Amazon.""",
}

# Run the Actor and wait for it to finish
run = client.actor("inkbridge/rtl-subtitle-fixer").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 '{
  "subtitleUrls": [],
  "subtitleText": "1\\n00:00:01,000 --> 00:00:03,500\\nمرحبا بالعالم!\\n\\n2\\n00:00:04,000 --> 00:00:06,000\\nاشتريت 3 كتب من Amazon."
}' |
apify call inkbridge/rtl-subtitle-fixer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inkbridge/rtl-subtitle-fixer"
        }
    }
}
```

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/axpSZdpS6ZMH1sn0E/builds/Ayk8KHXy8CbqaIZeG/openapi.json
