Script to Subtitle Aligner (SRT/VTT + Misread Check)
Pricing
from $20.00 / 1,000 media minutes
Script to Subtitle Aligner (SRT/VTT + Misread Check)
Give an audio or video URL and its script. Get SRT/VTT subtitles timed to each spoken word, a report of skipped and misread lines, and an optional MP4 with burned-in karaoke subtitles. 18 languages, including Chinese, Japanese and Korean. Batch many files. Without a script, it transcribes.
Script to Subtitle Aligner
What does Script to Subtitle Aligner do?
Script to Subtitle Aligner turns an audio or video file and its script into SRT and VTT subtitles that start and stop with the real speech. It also gives a report of the script lines that were skipped or misread. It can also make an MP4 with the subtitles burned in, with a karaoke highlight on each word. If you have no script, the Actor transcribes the media to subtitles.
To try it, click Start. The prefilled example uses a short speech clip and its script, and it finishes in less than a minute.
- Subtitles timed to each spoken word. The Actor uses the word times of the speech recognizer, not an even split of the text.
- Skipped and misread line report. You see which lines nobody said and which lines have words that do not match the speech.
- Your text, not the recognizer's text. The subtitles show your script exactly, with your punctuation and your line breaks.
- Video with burned-in subtitles. Get an MP4 for TikTok, Reels, or Shorts. In karaoke mode, each word turns yellow when it is said.
- Batch. Give many files in one run, each with its own script and language. A file that fails does not stop the batch.
- Share links work. You can use Dropbox and Google Drive share links.
- 18 languages, including Chinese (Simplified and Traditional), Japanese, Korean, English, Spanish, French, and German.
- No external AI API. Whisper runs inside the Actor. Your media does not go to a third-party AI service.
- All Apify platform features: API access, schedules, webhooks, and integrations with Make, Zapier, and other tools.
Who uses Script to Subtitle Aligner?
- Creators who subtitle AI-generated video, voice-overs, and text-to-speech output.
- Dubbing and localization teams who check that a voice actor read every line correctly.
- Teams that time an existing transcript to an audiobook, a podcast, a course, or a training video.
How to use Script to Subtitle Aligner
- Put a link to your audio or video file in Media URL. Use a direct file link, or a Dropbox or Google Drive share link.
- Paste your script in Script. Put each subtitle on its own line.
- Select the Spoken language. Auto detection also works, but it can fail when the media starts with music.
- Optional: in Video with subtitles, select Plain subtitles or Karaoke.
- Click Start.
- When the run ends, download
subtitles.srt,subtitles.vtt, orvideo.mp4from the Output tab. ReadmissingLinesandmisreadLinesto see which lines to check.
For many files, use Batch in place of Media URL and Script. See Batch.
How much does it cost to make subtitles?
The Actor uses the pay per event + usage model:
- $0.02 per started minute of media (event
media-minute). A 10-minute video costs $0.20. - Platform usage for the run. The default run uses 4096 MB of memory. In our test, an 11-second clip used 0.02 compute units. Transcription runs about 3 times faster than real time, so a 10-minute file uses about 0.25 compute units. The price of a compute unit depends on your Apify plan.
A failed run (bad URL, no speech, no audio track) is not charged per minute. In a batch, a file that fails is not charged.
Video with subtitles has no extra event price, but it uses more platform usage, because the Actor encodes the video again. Plan for an encode time of up to the length of the video for 1080p at the default memory. For videos longer than 20 minutes, set the memory to 8192 MB or more.
Input
| Field | Required | Description |
|---|---|---|
mediaUrl | Yes, if no batch | Direct http(s) link to an audio or video file (mp4, mov, mkv, webm, mp3, wav, m4a, and other formats), or a Dropbox or Google Drive share link. Maximum length is 60 minutes. Maximum size is 2 GB. |
script | No | The spoken text, in order, one subtitle per line. Leave empty to transcribe only. |
language | No | The spoken language. Default is auto detection. For Chinese, select Simplified or Traditional to set the characters of the transcript. |
videoWithSubtitles | No | off (default), plain, or karaoke. Makes video.mp4 with the subtitles burned in. The media must have a picture. |
batch | No | A list of files. Each item has mediaUrl, and optional script and language. When you use batch, the Actor ignores mediaUrl and script. |
{"mediaUrl": "https://raw.githubusercontent.com/openai/whisper/main/tests/jfk.flac","script": "And so, my fellow Americans,\nask not what your country can do for you,\nask what you can do for your country.","language": "en"}
Output
The Actor writes two subtitle files in the key-value store, subtitles.srt and subtitles.vtt. With videoWithSubtitles, it also writes video.mp4. It also writes one dataset item and the same data in the OUTPUT record. This is the output for the input above:
{"mediaUrl": "https://raw.githubusercontent.com/openai/whisper/main/tests/jfk.flac","mode": "align","timing": "measured","tokenErrorRate": 0.0,"missingLines": [],"misreadLines": [],"language": "en","durationSeconds": 11.0,"billedMinutes": 1,"srtUrl": "https://api.apify.com/v2/key-value-stores/.../records/subtitles.srt","vttUrl": "https://api.apify.com/v2/key-value-stores/.../records/subtitles.vtt","transcript": "And so my fellow Americans, ask not what your country can do for you. Ask what you can do for your country.","cues": [{ "index": 0, "startMs": 0, "endMs": 2120, "text": "And so, my fellow Americans,", "matchedTokens": 5, "expectedTokens": 5 },{ "index": 1, "startMs": 3260, "endMs": 7440, "text": "ask not what your country can do for you,", "matchedTokens": 9, "expectedTokens": 9 },{ "index": 2, "startMs": 8020, "endMs": 10340, "text": "ask what you can do for your country.", "matchedTokens": 8, "expectedTokens": 8 }]}
| Field | Meaning |
|---|---|
mode | align when you gave a script. transcribe when you did not. |
timing | measured: each line edge comes from the speech. estimated: the script and the speech differ too much for exact edges, so the Actor splits the measured speech window by line length. asr: transcription only. |
tokenErrorRate | Edit distance divided by the number of script tokens. This is the character error rate for Chinese, Japanese, and Korean, and the word error rate for other languages. Punctuation is not counted. |
missingLines | Script lines that nobody said. These lines get no subtitle. A skipped line does not change the timing of the other lines. |
misreadLines | Script lines that were said, but with one or more tokens that do not match the speech. Each item gives matchedTokens and expectedTokens. |
cues[].matchedTokens | Tokens of the line that the speech matched exactly. A value lower than expectedTokens shows a misread or a skipped word. |
videoUrl | The link to the MP4 with burned-in subtitles. Only when videoWithSubtitles is not off. |
Batch
Give the files in batch. Each file can have its own script and language. If an item has no language, the Actor uses language.
{"videoWithSubtitles": "karaoke","batch": [{ "mediaUrl": "https://example.com/episode-1.mp4", "script": "First lineSecond line", "language": "en" },{ "mediaUrl": "https://example.com/episode-1-es.mp4", "script": "Primera líneaSegunda línea", "language": "es" }]}
The Actor processes the files one by one. It writes one dataset item for each file, with item set to the position of the file in batch (1 is the first file). The files of item 1 are subtitles-1.srt, subtitles-1.vtt, and video-1.mp4. If a file fails, its item has an error field, and the Actor continues with the next file. A batch run does not write the OUTPUT record.
How does the alignment work?
- The Actor downloads the file and decodes the audio.
- Whisper (
smallmodel, on the Actor's CPU) transcribes the speech and gives a time for each word. - The Actor aligns the transcript to your script as one token stream with edit distance. Chinese, Japanese, and Korean use one token per character. Other languages use one token per word.
- Each line gets the time of its first and last matched token.
- For the video, each word of the line gets the time of its matched word. A word that the speech did not match gets a time between its neighbours. FFmpeg draws the subtitles with libass and encodes H.264 video and AAC audio.
The segment cuts of the speech recognizer do not change the result. One recognized segment can hold two lines, and one line can be split over two segments.
Other Actors from the same author
| Actor | What it does |
|---|---|
| AI Video Defect Scanner | Checks a batch of videos for black frames, frozen frames, silent or missing audio, wrong resolution, and corrupted data. |
FAQ
How accurate are the subtitle times?
In our test with 40 Chinese text-to-speech lines, the median error was 0.17 s at the start of a line and 0.06 s at the end. The largest error was 0.45 s. Results for real voices with music or noise can be less accurate.
Why is a correct line in misreadLines?
The speech recognizer can write a word that sounds the same as your word. In Chinese, this happens most with characters that have the same sound, for example 在 and 再. Listen to the line before you ask for a new recording.
What happens when the script and the speech are very different?
If tokenErrorRate is higher than 0.5, timing is estimated. The Actor then splits the measured speech window by line length. Check that the script belongs to the file and that the language is correct.
What are the limits?
- The media must have a speech track. A file with music only fails with "No speech was found".
- The maximum length is 60 minutes and the maximum size is 2 GB.
- For many files, use
batch. The run time limit applies to the whole batch. - Video with subtitles needs a picture. An audio file fails with a clear message and is not charged.
- In the video, the Actor breaks a long line into lines of about equal width. This also works for Chinese and Japanese, which have no spaces. A short line is easier to read: use about 16 characters or fewer for each line of a portrait video.
Can I use the Actor from my own code?
Yes. Use the Apify API or the Apify client for JavaScript or Python. The API tab of this Actor shows ready-to-use code.
Where can I report a problem?
Open an issue in the Issues tab of this Actor. Include the run ID, so we can find the run log.