Speech to Text — Advanced reference
This reference preserves the detailed input, engine, recovery and operator contracts for Speech to Text. Start with the Store quickstart for normal hosted runs.
Hosted availability and verification limits
The current hosted deployment does not enable Gemini text add-ons: summarize, translateTo, extractKeywords, chapters and actionItems. The add-on instructions below apply only to a deployment whose operator has configured Gemini Paid Services. These input names and rates remain part of the implementation; documenting them does not make them available on the hosted Actor.
Use Apify’s central MCP service for the hosted onboarding path. The current Actor has no direct Standby URL. The direct Standby authentication and recovery contract below describes the implementation and still requires a live platform smoke for direct per-run routing and cross-run storage permissions. It is not a verified hosted endpoint.
The four-hour input limit and ten-minute chunking describe supported processing bounds, not demonstrated transcription quality over four hours of natural speech. A direct-audio Google Docs append with connected OAuth was checked on 23 October 2026 after manual destination recovery. One complete YouTube-to-Docs workflow passed on 24 October on build 0.2.5 without manual recovery; see the acceptance report. These examples do not establish general platform availability.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
urls |
array of strings | (required) | YouTube/TikTok/Instagram/podcast/X links, or direct https media URLs (mp3, wav, m4a, mp4, …). One dataset item per processed URL. |
language |
string | auto-detect | BCP-47 hint (en, ru, ro, …). Omit the field to auto-detect; an explicit empty string is invalid. |
timestamps |
none | segment | word |
segment |
Granularity of the returned timing information. |
diarize |
boolean | false |
Label speakers using premium engines. Whole-file results use S1, S2, …; chunked results use C1_S1, C2_S1, … and report speaker_scope: "chunk". Labels from different chunks do not identify the same person. |
subtitleProfile |
standard | short |
omitted | Optional SRT/VTT line layout and QA. Requires segment or word timestamps. Omission preserves the existing exports and operation identity. |
provider |
string | auto | Advanced: pin one exact engine, such as "groq/whisper-large-v3", "google/gemini-3.5-transcribe" or "deepgram/nova-3". The engine must be configured and support the requested language/timings/speakers. A pin never silently changes providers. |
startTime / endTime |
seconds | whole source | Select an interval. API/MCP also accepts start_time / end_time; conflicting aliases fail. Zero is a valid start; the end must exceed the start and is capped at source duration. Output times stay relative to the original recording; minutes use the selected duration. The source still has to be downloaded. |
exportRag |
boolean | false |
Return rag_chunks and downloadable JSONL passages with original times, URL, language and speaker. Requires timestamps. |
glossary |
string array | empty | Up to 100 phrases of at most 80 characters, with a conservative total of 500 UTF-8 bytes including separators. Nova-3 supports timed hints; Gemini supports hints without timing or diarization. Unsupported combinations fail before download. |
chapters / actionItems |
boolean | false |
Analysis anchored to source segments; requires timestamps and Gemini Paid Services. |
Source URLs must use HTTPS without embedded credentials. Invalid URL syntax is rejected before the custom actor-start charge; Apify-managed startup fees can still apply.
duration_s uses two-decimal display rounding. source_duration_s, start_time_s and end_time_s retain measured precision; JSON words and segments remain inside that effective source interval. SRT/VTT exports use millisecond precision and omit cues whose rounded end is not later than their rounded start. Point annotations and submillisecond spans remain in JSON and the full transcript; no display duration is invented for them.
Output and downloads
The srt and vtt files are saved to the run’s key-value store as transcript-000.srt / transcript-000.vtt, indexed by the URL’s position in the input list. An SRT with no cues representable in milliseconds is saved as an empty file. A failed URL produces one dataset row with url and error; an ordinary item failure does not discard other successful items. A billing or uncertain-stage stop can halt the remaining batch.
Dataset rows stay below 9,000,000 UTF-8 JSON bytes. When a full result reaches that limit, its row contains source, timing, usage, billing and error metadata plus result_record_key (for example, item-000-result) instead of inline transcript and text products. Read that record in the run’s key-value store for the complete result under its signed value wrapper. The full transcript is preserved, and subtitle/RAG downloads remain available.
Subtitle profiles and QA
Request "subtitleProfile": "standard" or "subtitleProfile": "short" together with segment or word timestamps. These are product presets, not certification against a subtitle standard.
| Check | standard | short |
|---|---|---|
| Maximum Unicode code points per line | 42 | 28 |
| Lines per cue before warning | 2 | 2 |
| Minimum cue duration, seconds | 1 | 0.5 |
| Maximum cue duration, seconds | 7 | 4 |
| Maximum normalized text code points/second | 20 | 20 |
Line wrapping prefers whitespace, then splits an overlong token by Unicode code point. It is not grapheme-, language- or font-width-aware. The profile preserves cue intervals, source segments, words and full transcript; it reports excessive line count, duration and reading speed rather than truncating text or inventing timing. Fixes requiring different timing remain editorial work.
subtitle_qa contains profile, limits, cue_count, omitted_cue_count, issue_count, issues_truncated and up to 200 detailed issues. Every issue includes a zero-based segment_index; exported cues also include their one-based cue_number. Codes are omitted_timing, empty_text, too_many_lines, too_short, too_long, reading_speed and overlap. The optional actual and limit use seconds, line counts, or code points/second according to the code. Duration and overlap use the same rounded milliseconds as SRT/VTT. Reading speed counts normalized source text, including spaces, before WebVTT escaping. All issues are counted even when details are truncated.
Overlap is an advisory warning: overlapping speech/cues can be intentional. QA does not measure recognition accuracy or alignment correctness and does not turn warnings into item errors. No extra billing event is added. Existing transcription and platform charges still apply.
Batch runs also save transcript-000.subtitle-qa.json, indexed like the subtitles. Check artifact_errors if this download fails; the full saved result still contains its report. On deployments supporting timed translation, the same profile produces translated_subtitle_qa and transcript-000.translated.subtitle-qa.json. This does not enable translation on the hosted Actor.
Add-ons
Optional post-processing runs on transcript text, not audio. Results are saved before their custom-event charge:
-
summarize: true— a 2-4 sentence AI summary (summaryfield, orsummary_errorif it fails). -
translateTo: "<bcp-47>"— a full translation of the transcript (translation: { language, text }, ortranslation_error). -
extractKeywords: true— 5-10 extracted keywords/topics (keywordsarray, orkeywords_error). -
chapters: true— titles with original source time ranges (chapters). -
actionItems: true— explicit tasks with source evidence, quoted assignee/deadline when present (action_items). Dates are quoted, never calculated from ambiguous words such as “tomorrow”. Model interpretations still need human review.
Summary, chapters and action items share one analysis call and one existing transcript-summary event per requested bundle, including chapters-only/tasks-only requests. The rate is unchanged. Analysis failures use summary_error.
Timed translations also return translated_segments, translated_srt and translated_vtt. Segment IDs preserve timing/speakers despite response reordering; incomplete/duplicate IDs fail the add-on. Completed translation batches are saved for a supported retry. Encoded padding is bounded to the selected source interval. No translated word timing is invented. Untimed requests retain text-only translation.
All text add-ons require Gemini Paid Services. Unavailable add-ons fail validation before custom startup charges. A generation failure preserves the base transcript; an unknown charge outcome preserves saved output and stops further paid work.
Pricing
The table uses the FREE-tier base prices. Check the active Pricing tab for the tier prices and effective date applied to your run.
Custom-event pricing follows the stages below. billing.events distinguishes requested counts from confirmed charges. Apify platform charges can also apply.
| Event | Price | When it’s charged |
|---|---|---|
| Run setup | $0.005 | Once per run, flat; the event ID remains actor-start. |
| Platform video fetched | $0.02 | Once per URL, only after a platform video/audio (YouTube, TikTok, Instagram, X, …) is successfully downloaded via yt-dlp. Not charged for URLs classified as direct media by a recognized media extension in the pathname; extensionless file URLs take the platform route. |
| Audio transcribed | $0.01 / minute | Per started minute, only after transcription succeeds. |
| Audio transcribed (diarized) | $0.02 / minute | Per started minute with speaker labels, only after transcription succeeds. |
| Transcript analysis | $0.015 / item | One transcript-summary event for any requested combination of summary, chapters and action items after successful analysis is saved. |
| Transcript translation | $0.015 / item | Once per URL, only if translateTo is set and the translation succeeds. |
| Transcript keywords | $0.008 / item | Once per URL, only if extractKeywords is set and extraction succeeds. |
Custom-event subtotal: a 10-minute YouTube video, no diarization: $0.005 + $0.02 + 10 × $0.01 = $0.125. The same 10-minute video with diarization enabled: $0.005 + $0.02 + 10 × $0.02 = $0.225.
Apify-managed startup events, when configured, are additional and depend on the allocated memory; consult the active pricing panel for the full total. URLs classified as direct media skip the $0.02 platform-fetch charge; an extensionless file URL takes the platform route. Startup fees can still apply on failure. A successful platform download incurs its fetch fee even when later transcription fails; a failed transcription does not incur audio-minute events.
The current platform startup rate is $0.00005 per GB, with at least one event. At the default 4096 MiB, that adds $0.0002 per run. The public 45.3-second speech demo therefore has a $0.0152 event subtotal (one started audio minute, no platform download). The ten-minute YouTube examples above become $0.1252 / $0.2252 with this startup event. Check the active pricing panel before running; these examples exclude optional products and any additional applicable charges.
Before starting, set the run option maxTotalChargeUsd to your chosen budget (for example, $0.10 for the short demo). This is a run option, not an input field. The full selected-duration budget check happens after download, before ASR; it is not a free duration preview. If duration is unknown, use a short selected interval and a budget cap. Selecting an interval still downloads the source. The output’s usage.minutes and billing.events report started minutes and requested/confirmed custom events. Provider-cost estimates are separate from your charges and do not establish provider invoices or profit.
Engine routing and acquisition
The Actor transcribes audio rather than scraping an existing caption track. Routing selects among configured speech-to-text engines — Groq Whisper, OpenAI, Gemini Transcribe and Deepgram Nova — with failover for retryable provider errors. Only configured engines that support the requested capabilities are eligible; the configured list does not guarantee a backup for every mode. Google Chirp’s 60-second synchronous adapter is available by explicit pin for supported short requests, outside automatic long-recording fallback.
ASR and text-generation API requests disable automatic HTTP redirects. Rejected redirects use the existing retryable-provider error and failover rules. Successful ASR/text API response bodies are limited to 32 MiB of decoded bytes before JSON parsing, including the Actor’s token-usage observer. Overflow follows the existing provider/add-on failure and recovery rules; unknown usage stays unknown. This bounds each response, not total memory or concurrent work. Native direct-media acquisition accepts HTTP206 only for a verifiable complete resource; partial or invalid ranges fail before provider calls or audio-minute charges. This does not change yt-dlp or source-proxy range handling. See the repository acquisition checks (docs/research/2026-10-23-partial-http-acquisition.md).
Whole signed 16-bit PCM WAV files retain their bytes when no timeline repair is needed. Other WAV encodings use the existing mono 16 kHz, 64 kbps MP3 normalization path before provider routing, retaining logical duration and source offsets. Explicit google/chirp_3 pins also normalize non-AAC M4A and non-Opus Ogg/WebM; default ALAC/M4A remains byte-preserving when no timeline repair is needed.
Long recordings and chunking
The Actor accepts recordings up to four hours. Non-diarized long audio is processed in ten-minute chunks. Diarization keeps the recording whole when an eligible engine fits; otherwise it uses ten-minute chunks and reports speaker_scope: "chunk". Word and segment times are shifted back to the original recording timeline. Started minutes are rounded once per input file, not for each chunk. Silent windows produce empty text without discarding other chunks; processed silence is included in the duration. MCP output includes timed segments, transcript_llm speaker labels and speaker_scope.
Gemini Transcribe supports diarization and words but limits these requests to 30 minutes. This integration uses inline audio capped at 10 MiB; larger inputs are compressed/chunked without creating a persistent Gemini Files upload. Speaker attribution for three or more speakers is experimental in the model. Chunk labels are local identities, not speaker recognition across the recording.
openai/gpt-transcribe is the current text-only OpenAI route. Word timings and speaker labels still use separate compatible engines. The legacy OpenAI timestamp and diarization models are scheduled to shut down on February 26, 2027. ElevenLabs and the former generic google/gemini ASR route have been removed; old pins fail explicitly rather than being redirected.
Use via MCP (AI agents)
On a deployment with Standby enabled, the MCP server exposes transcribe_audio with the same interval, glossary, export and text-product options as batch. Use its URL from Apify Console only when that deployment exposes one. Standby platform usage is additional to custom events; an idle warm run can still consume resources. The custom actor-start event is charged by the batch controller, not once per MCP tool call. See Apify Standby.
prepare_transcription and transcribe_audio require an application Authorization: Bearer <Apify token> identifying the owner of the receiving run. The Actor validates that token through Apify’s /v2/users/me endpoint before creating an operation or starting paid work. Missing identity, foreign accounts and failed validation are rejected. Scoped tokens must permit this identity lookup.
For an Apify Standby hostname, send both headers:
X-Apify-Authorization: Bearer <your Apify token> Authorization: Bearer <your Apify token>
The platform uses the first header; the application validates the second. This follows Apify’s documented handling for application authorization. Clients that send only the platform’s ordinary Authorization need this configuration change. A direct per-run execution_url still requires application authorization for preparation/execution. This integration targets dedicated-user Standby runs; multi-tenant Server Actors are not supported.
For recovery after a lost response:
-
Call
prepare_transcriptionwith the desired parameters. It returns a secretoperation_idbefore any download/ASR/LLM/custom charge, plusexecution_urlfor the owning run when available from the platform. -
Connect to that run’s
execution_urland calltranscribe_audiowith the same parameters andoperationId. Keep the application authorization above. Execution is restricted to the owning run; another container rejects it rather than racing to charge the same operation. -
Call
get_transcription({ operationId })to read saved output/charge entries. The response also includes computed billing and per-operation metrics. Retrieval can use a later Standby run with storage access and makes no ASR, LLM or custom charge. Platform usage still applies. An interrupted/unknown stage is reported, not blindly restarted.
get_transcription retains capability-based access without a new caller-identity lookup. Keep platform authentication when using its Standby hostname. Foreign archive lookup only reads records; it does not create the requested store or write to it. The current execution store remains writable for normal processing.
Legacy one-call transcription still works and returns operation_id with its response. Processing failures after operation ownership, parameters and saved journal validation also return that ID beside a fixed error in MCP isError: true content. Earlier validation, preparation or admission failures return no capability. Recovering the loss of that very first response requires the preparation flow. Direct per-run routing and cross-run storage permissions need a live platform smoke before publishing this recovery contract. A run’s lifetime and storage expiry limit recovery. Treat capabilities and run URLs as secrets; anyone with underlying storage read access can also read operation keys and outputs.
Saved results and budget stopping
Each completed chunk and the base transcript are saved in run KVS before audio charges. Read item-000-result, item-001-result, etc. for JSON downloads; the corresponding item-NNN records contain stage/charge journals. Signed KVS records wrap their JSON in value; MCP retrieval returns the unwrapped product. Completed chunks are reused after a supported retry only if the downloaded source bytes still match. Source downloads may repeat during recovery; completed custom fetch events do not. Before a potentially paid TikTok fallback, the operation saves a source-stage marker. A failed or uncertain acquisition retains it for reconciliation instead of starting another child run on same-operation retry. A validated successful acquisition releases the marker; this is not remote exactly-once execution. Published batch positions, including error rows, are skipped on resurrection. If provider or Gemini configuration is unavailable, an existing confirmed batch startup receipt permits publication of completed saved output without another provider call or custom charge. Fresh or unfinished work still requires normal configuration; uncertain charges and Dataset publication remain stopped for reconciliation.
billing.status is paid, unpaid, partial or unknown; calculated usage.minutes is not proof of payment. Remaining allowance is checked before each new custom charge, including cached unpaid output; confirmed paid retrieval submits no charge. Hosted custom charges use one request attempt with a 30-second SDK request timeout; storage requests retain their existing retry policy. Partial/unknown charges stop additional paid work and the batch. An unknown receipt is not resent: this integration does not use a stable charge idempotency key across separate calls or restarts. See the repository transport check (docs/research/2026-10-23-charge-transport-retry.md). A forced interruption during an external call also requires reconciliation. This is not an atomic transaction across Apify storage, providers and billing.
Hosted runs reject paid apify-default-dataset-item pricing before custom work; configure the explicit stage events listed above. Local SDK simulation retains its original charging manager and charging-log lifecycle.
Dataset append is journaled separately. If its acknowledgement is lost, retrieve the saved JSON and reconcile the append; resurrection does not blindly add a duplicate row. A subtitle-download failure leaves JSON available and reports artifact_errors. Optional text-product failures preserve the base transcript. Oversized results use the bounded reference row described above; this does not change the full result record or the append reconciliation rules.
Operator metrics and integrations
Batch runs save RUN_METRICS with provider attempts, failures, audio/time totals, LLM calls/token metadata and requested/confirmed charge counts. It contains no URLs, transcript or client operation IDs. Optional PROVIDER_COSTS_USD_PER_MINUTE maps engine IDs to operator-maintained numeric estimates. Missing rates and failed-call costs remain unknown; estimates are not invoices, cash payments or profit. The metrics follow run-storage access permissions and are not a public dashboard. Available OpenAI usage counters are retained per attempt and included in provider_usage; missing or malformed optional counters remain unavailable. Groq estimates account for its ten-second minimum per request.
Operator cost admission
The Actor bootstrap enables durable cost reservations before ASR and paid source fallbacks. ASR gets at most half of the lower of the actual audio event price and $0.01/minute (ordinary) or $0.02/minute (diarized), multiplied by the selected started minutes. Source fallbacks get half of the lower of the platform-fetch event price and $0.02. These are internal spending policies, not published tariff changes, customer charges, or a guarantee of positive profit on every request.
Every dispatched attempt consumes its reservation permanently, including failed or ambiguous attempts. An unaffordable ASR candidate is skipped without dispatch; later affordable candidates may still run. Exhaustion stops the batch. Missing configured engine rates, unsupported cost models and failed reservation saves prevent new paid calls. Existing completed results remain retrievable. Incomplete legacy work without a cost ledger requires reconciliation before new paid work.
Duration-priced reservations use the higher of the configured estimate and the policy rate floor, rounded up to seconds (at least ten seconds for Groq), with 10% headroom. Deepgram’s glossary surcharge is included in its floor. Token-priced OpenAI Mini/Diarize, Google/Gemini and new LLM add-on calls are refused by this policy until bounded costing is implemented; saved text products remain usable.
Residential fallback reserves the whole 16 MiB allowance at a planning $10 per decimal GB; TikTok fallback reserves its existing $0.50 child-run cap. Neither fits the current $0.01 source spending allowance, so these paid fallback routes are refused before dispatch. Direct source extraction remains available. This reduces platform-link availability; it must be accounted for before deployment.
Rate floors and buffers are planning assumptions. Provider invoices, network overhead, infrastructure, failed requests with no delivered revenue, and external API costs from Free-plan users still require reconciliation. The standalone HTTP gateway does not use the Actor’s cost policy.
Importable inactive n8n examples cover Telegram voice, video-to-Google-Docs and podcast retrieval passages. Configure credentials and a run budget before activation. Their live delivery has not been tested.
Language coverage
Powered by Whisper-family and other models; language coverage depends on the selected engine and mode. Omit language for auto-detection, or pass a BCP-47 hint when you know the source language. Automatic recognition does not guarantee a detected-language field in every engine’s response; Gemini’s current REST mapping preserves a supplied hint. Some Gemini word annotations are point timestamps with equal start/end; these are retained in JSON without inventing durations.
Privacy
The Actor attempts to remove the local working copy of audio/video when processing that URL finishes. ASR providers receive audio; optional text add-ons send the transcript to Gemini. Results, chunk caches, translation batches and operation journals remain in run Dataset/KVS according to Apify permissions and retention settings. Resume/recovery requires these saved records; local-file deletion does not remove them. Text add-ons send relevant transcript content to Gemini, including evidence for chapters/tasks. Deepgram requests use mip_opt_out=true; Gemini ASR requests use store=false and require the operator’s Paid Services confirmation. These controls are not a promise of universal zero retention, including abuse/security metadata.
The TikTok download fallback can create a separate child Actor run and stored media; each child is started with a $0.50 spending cap, the published minimum on 2026-10-23. This is an operator limit per child, separate from the customer’s parent-run budget and the $0.02 fetch event; it does not guarantee a margin. Local temporary-file cleanup does not establish deletion from that child’s storage. Its retention must be reviewed before offering a stronger deletion guarantee.
Local simulation
The Actor requires a private STATE_SIGNING_KEY containing 64 random hexadecimal characters, configured by its owner in the private environment. Keep it unchanged for recovery of existing journals. Signatures bind stored journals and operation metadata to their store and record key; unsigned legacy records fail closed and must not be automatically trusted. Signatures authenticate writes, do not encrypt customer data, and cannot prevent a storage owner deleting or restoring an older valid snapshot. Save-before-charge remains a recovery tradeoff, not a guarantee of payment before the customer can read stored output.
Set ACTOR_TEST_PAY_PER_EVENT=true before apify run or the local Actor launcher. The installed SDK then simulates event receipts locally; these are not customer payments and its local test prices do not reproduce the published rate table. A non-PPE runtime fails clearly before processing instead of returning an empty successful run. Never set the SDK test flag on the Apify platform.