# Hebrew & Arabic Subtitle Fixer (RTL punctuation, encoding) (`harushlabs/rtl-subtitle-fixer`) Actor

Fix Hebrew and Arabic SRT/VTT subtitles: punctuation on the wrong side, gibberish encoding (Windows-1255/1256 to UTF-8), timing shift, frame-rate conversion, SRT to VTT, line re-wrap and quality report. Pure file processing, no scraping.

- **URL**: https://apify.com/harushlabs/rtl-subtitle-fixer.md
- **Developed by:** [Harush Studio](https://apify.com/harushlabs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 subtitle file processeds

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

## Hebrew & Arabic Subtitle Fixer (RTL punctuation, encoding, timing)

Fix the classic problems of **Hebrew and Arabic subtitles** in one run:

- **Punctuation on the wrong side** – `.שלום` → `שלום.`, `?ماذا` → `ماذا؟`-style issues, dialogue dashes at the end of the line
- **Gibberish characters (×©×œ×•×, ÷ìåí)** – auto-detects **Windows-1255 (Hebrew)**, **Windows-1256 (Arabic)**, UTF-16 and UTF-8 BOM and outputs clean **UTF-8**
- **RTL display** – adds invisible RLM marks (or RLE/PDF embedding for old TVs) so players such as VLC, Plex, Kodi, YouTube, browsers and smart TVs show the line right-to-left
- **Timing** – shift by milliseconds, convert **23.976 ↔ 25 fps** and other frame rates
- **Convert SRT ↔ WebVTT**, remove `<i>`/`{\an8}` tags and hearing-impaired notes (`[music]`), re-wrap long lines
- **Quality report** – overlapping cues, cues that are too short or too fast to read (characters per second)

Pure file processing: **no scraping, no external APIs**. Works on files you upload or link to.

### Input example

```json
{
  "subtitleUrls": [{ "url": "https://my-bucket.s3.amazonaws.com/episode-01.he.srt" }],
  "outputFormat": "srt",
  "punctuationSwap": "auto",
  "shiftMs": -1500,
  "removeHearingImpaired": true
}
```

You can also paste the subtitles into `subtitleText`.

### Before / after

Input (Windows-1255, typed in a left-to-right editor):

```
1
00:00:01,000 --> 00:00:03,000
.שלום, מה שלומך

2
00:00:03,500 --> 00:00:05,000
?מה קורה
אני בסדר -
```

Output (UTF-8, logical punctuation + RLM marks, displays correctly everywhere):

```
1
00:00:01,000 --> 00:00:03,000
שלום, מה שלומך.

2
00:00:03,500 --> 00:00:05,000
מה קורה?
- אני בסדר
```

Dataset item:

```json
{
  "fileName": "broken_he_cp1255.srt",
  "status": "ok",
  "detectedEncoding": "cp1255",
  "outputKey": "fixed-0001-broken_he_cp1255.srt",
  "report": { "cues": 4, "rtlLines": 5, "punctuationSwapped": true, "overlaps": 0, "tooFast": 0, "tooShort": 0, "emptyRemoved": 1, "warnings": [] }
}
```

The fixed file is saved in the run's key-value store under `outputKey` (download it from the **Storage** tab or via API).

### How "auto" punctuation detection works

A file is treated as "typed backwards" only if at least 3 right-to-left lines start with sentence punctuation and such lines outnumber correctly punctuated lines 2:1. Correct files are never modified, so it is safe to run on mixed batches. Force the behaviour with `"punctuationSwap": "always"` or `"never"`.

### Pricing

**$0.01 per subtitle file fixed.** Failed downloads and files that are not subtitles are free.

### Integrations

Call it from the Apify API, Make, Zapier or n8n after your transcription or translation step, or chain it with **Hebrew & Arabic Audio Transcription + RTL Subtitles**.

### Privacy

Files are processed only in your run. Logs contain no file names, URLs or subtitle text. Only process subtitles you have the rights to use.

# Actor input Schema

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

Direct links to .srt or .vtt files (any encoding: UTF-8, UTF-16, Windows-1255 Hebrew, Windows-1256 Arabic). Upload files in the Console or link to your own storage.

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

Paste SRT or WebVTT content directly.

## `outputFormat` (type: `string`):

Format of the fixed file.

## `rtlMode` (type: `string`):

How to force right-to-left display of Hebrew/Arabic lines so punctuation and numbers appear on the correct side.

## `punctuationSwap` (type: `string`):

Fixes files where lines were typed as '.שלום' to look right in a left-to-right editor; moves the punctuation to the logical end and dialogue dashes to the start.

## `shiftMs` (type: `integer`):

Positive = later, negative = earlier.

## `fpsFrom` (type: `string`):

Retime subtitles made for a different video frame rate (e.g. 23.976 -> 25 for PAL). Leave empty to skip.

## `fpsTo` (type: `string`):

Target frame rate.

## `removeFormattingTags` (type: `boolean`):

Strips <i>, <b>, <font>, {\an8} and WebVTT voice/class tags.

## `removeHearingImpaired` (type: `boolean`):

Removes \[music], (laughs) and similar annotations.

## `rewrapMaxChars` (type: `integer`):

0 keeps the original line breaks. Otherwise each cue is re-wrapped into balanced lines of at most this many characters.

## `maxLines` (type: `integer`):

Used only when re-wrapping.

## Actor input object example

```json
{
  "subtitleUrls": [],
  "subtitleText": "1\n00:00:01,000 --> 00:00:03,000\n.שלום, מה שלומך\n\n2\n00:00:03,500 --> 00:00:05,000\n?מה קורה\n\n3\n00:00:05,500 --> 00:00:07,000\n!יופי",
  "outputFormat": "srt",
  "rtlMode": "rlm",
  "punctuationSwap": "auto",
  "shiftMs": 0,
  "removeFormattingTags": false,
  "removeHearingImpaired": false,
  "rewrapMaxChars": 0,
  "maxLines": 2
}
```

# Actor output Schema

## `results` (type: `string`):

Dataset with one item per subtitle file: detected encoding, output format and key, fix report and fixed content.

## `subtitleFiles` (type: `string`):

Fixed SRT/VTT files ready to download (key is also in the outputKey field).

# 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,000
.שלום, מה שלומך

2
00:00:03,500 --> 00:00:05,000
?מה קורה

3
00:00:05,500 --> 00:00:07,000
!יופי`
};

// Run the Actor and wait for it to finish
const run = await client.actor("harushlabs/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,000
.שלום, מה שלומך

2
00:00:03,500 --> 00:00:05,000
?מה קורה

3
00:00:05,500 --> 00:00:07,000
!יופי""",
}

# Run the Actor and wait for it to finish
run = client.actor("harushlabs/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,000\\n.שלום, מה שלומך\\n\\n2\\n00:00:03,500 --> 00:00:05,000\\n?מה קורה\\n\\n3\\n00:00:05,500 --> 00:00:07,000\\n!יופי"
}' |
apify call harushlabs/rtl-subtitle-fixer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,harushlabs/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/86ggz9JzHG0DVbkIT/builds/U3cP5UQ3Fc5TeYryV/openapi.json
