Audio & Video Transcription to Text, SRT, VTT avatar

Audio & Video Transcription to Text, SRT, VTT

Pricing

from $0.01 / 1,000 row returneds

Go to Apify Store
Audio & Video Transcription to Text, SRT, VTT

Audio & Video Transcription to Text, SRT, VTT

Turn audio and video links into text with timestamped segments. Get optional SRT or WebVTT subtitles, automatic or chosen language detection from 100+ languages, and optional English translation. Process up to 100 files per run.

Pricing

from $0.01 / 1,000 row returneds

Rating

0.0

(0)

Developer

bite-sized-insights

bite-sized-insights

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

2 hours ago

Last modified

Security

Limited permissions

Share

Audio & Video Transcription - Speech to Text, SRT & VTT

Turn audio and video links into text. Give it a list of direct links to recordings, podcasts, calls, lectures or videos; every file comes back as one dataset row with the full transcript, timestamped segments, optional subtitle files and an optional English translation. Billed per audio minute, only for the minutes that were transcribed.

What this actor does

  • Transcribes the files you actually have: MP3, M4A, MP4, MOV, WAV, OGG/Opus, FLAC, AAC, WebM, MKV, AVI, FLV, AIFF, AMR, WMA and MPEG-TS. The type is detected from the file itself, so a wrong file extension or content type does not matter. For video files the audio track is used.
  • Timestamps: every row carries the transcript as segments with start and end time in seconds, ready for search, highlights, chapters or alignment with the video.
  • Subtitles: ask for SRT and/or WebVTT and get ready-to-use subtitle text in the same row.
  • 100 languages: the spoken language is detected automatically, or you pass it as a hint if you know it. Accuracy is best for widely spoken languages and lower for rare ones.
  • Translate to English: switch on translation and get the English transcript of speech in any supported language, at the same price.
  • Safe by design: only public http(s) links are fetched, files are limited to 300 MB, and the minute limit keeps a single huge recording from running up your bill.

Direct media links only. A link to a web page that merely plays a video (a streaming or social media page) is not a media file and is reported as unsupported.

Quick start

{
"urls": ["https://upload.wikimedia.org/wikipedia/commons/d/dd/Armstrong_Small_Step.ogg"],
"subtitleFormats": ["srt"]
}

Click Start. Each file is added to the dataset as soon as it is transcribed.

Input parameters

ParameterTypeRequiredDescription
urlsArray[String]YesLinks to the audio or video files. Up to 100 per run, up to 2048 characters each.
languageStringNoauto (default) detects the language; or a code such as en, de, es, ja.
translateToEnglishBooleanNoReturn the English translation of the speech. Off by default.
subtitleFormatsArray[String]NoAny of srt and vtt. Empty by default (no subtitle text).
maxMinutesPerFileIntegerNoTranscribe only the first N minutes of each file. 1-120, default 60.
withSummaryBooleanNoAdd a compact summary of each transcript. Off by default.
withTagsBooleanNoAdd single-word topic tags for each transcript. Off by default.
with5w1hBooleanNoAdd who, what, when, where, why and how of each transcript. Off by default.
withSentimentBooleanNoAdd the overall sentiment of each transcript. Off by default.

Entries without a scheme are treated as https://. Links to private or local addresses, links with credentials and malformed links are rejected as invalid input before anything is fetched.

Output

One row per input file. Every key is always present: missing values are null, lists are empty, never omitted.

Transcribed file

{
"url": "https://example.com/podcast.mp3",
"status": "success",
"language": "en",
"language_probability": 0.99,
"translated": false,
"duration_seconds": 84.3,
"transcribed_seconds": 84.3,
"minutes_transcribed": 2,
"truncated": false,
"text": "Welcome to the show. Today we talk about timestamps.",
"segments": [
{"id": 0, "start": 0.0, "end": 2.4, "text": "Welcome to the show."},
{"id": 1, "start": 2.9, "end": 6.1, "text": "Today we talk about timestamps."}
],
"srt": "1\n00:00:00,000 --> 00:00:02,400\nWelcome to the show.\n\n2\n00:00:02,900 --> 00:00:06,100\nToday...",
"vtt": null,
"error_code": null,
"error": null,
"summary": {
"summary": "A short welcome and an introduction to timestamps.",
"stats": {"original_length": 52, "summary_length": 50, "compression_ratio": 0.9615}
},
"tags": {"tags": ["podcast", "timestamps"], "count": 2},
"five_w1h": null,
"sentiment": {"sentiment": "positive", "confidence": 0.82},
"analysis_truncated": false
}

Failed file

{
"url": "https://example.com/page.html",
"status": "failed",
"language": null,
"language_probability": null,
"translated": false,
"duration_seconds": null,
"transcribed_seconds": 0.0,
"minutes_transcribed": 0,
"truncated": false,
"text": null,
"segments": [],
"srt": null,
"vtt": null,
"error_code": "unsupported_format",
"error": "Unsupported file type. Supported: MP3, M4A/MP4, WAV, OGG/Opus, FLAC, AAC, WebM/MKV and more.",
"summary": null,
"tags": null,
"five_w1h": null,
"sentiment": null,
"analysis_truncated": false
}

The add-on fields (summary, tags, five_w1h, sentiment) are null unless you switched the add-on on and it succeeded; five_w1h also stays null for transcripts shorter than 50 characters. analysis_truncated is true when a transcript was longer than 100,000 characters (roughly 120 minutes of speech at a normal pace): the add-ons then only analysed its beginning.

status is one of:

  • success - the whole file (or the first maxMinutesPerFile minutes of it) was transcribed
  • partial - the time budget for the file ran out; segments holds everything transcribed until then. If the budget runs out before the first segment is finished, the row is failed with transcription_failed instead
  • failed - nothing was delivered; error_code and error say why (no transcription charge)

error_code values: blocked_url (private or unresolvable address), download_failed, too_large (over 300 MB), unsupported_format (not a supported audio or video file), invalid_media (corrupt or unreadable), no_audio (a video without an audio track), too_long (over 12 hours), no_speech (no speech found), transcription_failed, and service_unavailable (the transcription service could not be reached; try again).

Pricing: pay per audio minute

EventPrice
Audio minute transcribed$0.010 ($10.00 per 1,000 minutes)
Summary add-on, per transcribed minute$0.002
5W1H add-on, per transcribed minute$0.002
Tags add-on, per transcribed minute$0.001
Sentiment add-on, per transcribed minute$0.0005

A flat start fee of $0.00005 per run applies, and Apify's platform dataset-item fee ($0.00001 per row) applies to every row written to the dataset, failed rows included. Minutes are counted per file and rounded up: a 61-second file is 2 minutes. Only minutes that were actually transcribed are billed: failed files, files without speech and translation requests cost nothing extra, and a file cut short by maxMinutesPerFile or by the time budget is billed for the audio that was transcribed. minutes_transcribed in every row shows exactly what was billed.

Add-ons are optional and only billed when switched on: each is charged with the same minute count as the transcription, for every file where that add-on succeeded. If an add-on fails the transcript is still delivered, the add-on field is null and it is not billed.

Free test runs

New users on Apify's free plan get up to 5 free runs of this actor (lifetime total), each capped to 3 files of 2 minutes. Runs started via the Apify Console's "Test" button have the same caps regardless of plan and do not count against the 5 free runs.

How long does a run take?

Files are transcribed two at a time and results appear in the dataset as each one finishes. Expect roughly 8 to 12 times real time, so a one-hour recording takes about 5 to 8 minutes. Each file has a time budget of about 15 minutes. On a busy or slow server even a 120-minute recording can run out of time and come back as partial with the minutes transcribed so far. Lower maxMinutesPerFile or split the recording to avoid that.

Use it from code

Replace <APIFY_TOKEN> with your API token from the Apify Console (Settings, API and integrations).

curl -X POST "https://api.apify.com/v2/acts/7V0WYMgIcZ4QCCPYO/runs?token=<APIFY_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"urls": ["https://example.com/podcast.mp3"], "subtitleFormats": ["srt"]}'

The call returns the run immediately; read the results from the run's default dataset when it has finished.

from apify_client import ApifyClient
client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("7V0WYMgIcZ4QCCPYO").call(run_input={
"urls": ["https://example.com/podcast.mp3"],
"language": "auto",
"subtitleFormats": ["srt", "vtt"],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["status"], item["minutes_transcribed"], item["text"])
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('7V0WYMgIcZ4QCCPYO').call({
urls: ['https://example.com/podcast.mp3'],
subtitleFormats: ['srt'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].status, items[0].text);

Use the asynchronous run shown above for long recordings. Apify's synchronous run endpoints stop waiting after about five minutes, which is shorter than the time a long file can need.

Use with AI agents (MCP)

Connect an AI client such as Claude Desktop, Cursor or VS Code to the Apify MCP server and it can call this actor as a tool. Authenticate with OAuth or your API token:

{
"mcpServers": {
"apify-transcription": {
"url": "https://mcp.apify.com/?actors=7V0WYMgIcZ4QCCPYO",
"headers": {"Authorization": "Bearer <APIFY_TOKEN>"}
}
}
}

Ask the agent to transcribe a direct media link; it passes the same input as in the table above and gets the dataset rows back. Billing is the same as for a normal run.

Troubleshooting

SymptomCauseFix
blocked_urlPrivate or local address, or the host name does not resolveUse a public link
download_failedServer error, too many redirects, slower than 120 s, or expired linkUse a stable public URL
unsupported_formatA web page, playlist or other non-media fileLink the media file itself
invalid_mediaThe file is empty, damaged or unreadableCheck that it plays; re-export it
too_largeOver 300 MBExtract the audio as MP3 or AAC, or split it
no_audioThe video has no audio trackNothing to transcribe
too_longOver 12 hoursSplit the recording
no_speechOnly music, silence or noiseNo transcription charge; check the file
transcription_failedModel error, or no segment finished in timeRetry; lower maxMinutesPerFile
service_unavailableTranscription service unreachableTry again later
partial statusTime budget ran out part wayLower maxMinutesPerFile; split it
Only 3 files of 2 minutes doneFree plan and Console test runs are cappedUse a paid plan
Wrong language or odd wordsDetection guessed wrong on a short or noisy clipSet language

FAQ

Why is a minute billed when the last part of my file is silent?

Minutes are counted over the audio that was processed, silence included. Files in which no speech is found at all are reported as no_speech and carry no transcription charge.

Can I transcribe only the start of a long recording?

Yes. maxMinutesPerFile transcribes the first N minutes. The row shows the real length in duration_seconds and truncated: true when audio was left out.

Which languages are supported?

100 languages. The Spoken language dropdown in the input form lists all of them. Automatic detection works for most recordings; a fixed language helps with short or noisy clips. Quality varies: it is best for widely spoken languages and lower for rare ones.

How do I get the translation instead of the original wording?

Switch on translateToEnglish. language is then the language that was spoken and translated is true. Speech that is already English is returned as is.

No. Only direct links to media files are fetched; pages that need scraping or sign-in are not supported.

Does this actor use a proxy?

No. It calls a dedicated transcription service, and the service fetches your public media links from its own server address, not from Apify's IPs or yours. Links that only work from an allowlisted IP, behind a login, or with expiring tokens bound to another address will fail with download_failed. Use a public link or a signed URL that is valid for anyone.

Disclaimer

Only transcribe recordings you are allowed to process. Accuracy depends on the audio: background noise, overlapping speakers, strong accents and music can reduce quality, and names and rare terms may be misspelled. Translations are machine translations. Speakers are not identified.


Need help? Open an issue on the actor's repository or contact support through Apify Console.