Versions follow MAJOR.MINOR.PATCH (src/version.py); Apify shows MAJOR.MINOR from .actor/actor.json.
Every run logs its version and records it in the RUN_STATS key-value record.
RUN_STATS.platformLinksRefused: how many refused links per platform (names only), e.g. {"YouTube": 2}.
- README: real screenshots of the input form and the Output table, from our own runs.
- New: word timestamps (
includeWordTimestamps, off by default). A words field lists every word with its start
and end in seconds and the model's confidence; null when off. faster-whisper's own alignment
(word_timestamps=True), offset per 20-minute window like the segments. Same price per minute; it makes
transcription slower (measured in COSTS.md). A 300-minute file of fast speech with every output on stays under
Apify's 9 MB item limit (tested).
- New: audio links from another actor's dataset (
datasetId, with datasetUrlField). Each item's link is
transcribed like a mediaUrls line, in the dataset's order, duplicates (and links already in mediaUrls)
dropped; source is dataset. The field is a name or a dotted path; its value may be a URL, an object with a
url (or href/link/src), or a list of them (the first audio or video one wins, as for podcast enclosures). Left
empty, it's found among audioUrl, audio, mediaUrl, enclosures (RSS & Atom Feed Reader's output), enclosure,
videoUrl, fileUrl and downloadUrl; a page link such as url is never guessed. Read through Apify's API with the
run's own client (the user's run token, read-only; locally there is none, and the run says so), only the needed
field, at most 10,000 items and 1,000 distinct links. A dataset that can't be read, is the run's own output, or
has no links fails clearly (naming the fields its first item has) without affecting the other inputs; nothing is
fetched for it. RUN_STATS.dataset has the counts.
- Changed: direct links to video and social platforms' media servers (googlevideo.com, tiktokcdn.com,
fbcdn.net, cdninstagram.com, video.twimg.com, sndcdn.com, scdn.co, v.redd.it and the like) are refused before any
request, like those platforms' page links already were, whether in
mediaUrls or a dataset: a platform scraper's
dataset holds exactly these, and the same terms cover them (the legal hold on platform media).
- New: a published accuracy benchmark (
benchmark/): WER of base and small on a fixed subset of LibriSpeech
test-clean and test-other (CC BY 4.0), with the actor's own decoding and model settings; results in the README.
- The worker's model settings are one function (
worker.options), used by the actor and the benchmark alike.
- Fixed: the Small model failed every file on a 4 GB run with "the file needs more memory than this run has". The
worker's memory cap was RLIMIT_DATA, which counts address space, not memory in use: on x86-64 the small model
reserves ~3.4 GB of heap for a ~1.2 GB peak, past the 3.7 GB cap. The cap is now on the resident memory of the
worker and its ffmpeg, sampled by the run every 0.25 s from /proc; over it, the file's process group is stopped
and the file reported as
outOfMemory, as before, without affecting the others. The worker also makes itself the
kernel's first choice if the container runs out of memory between two samples, so a spike costs that file, not
the run. Windows and per-file deadlines are unchanged.
First release.
- Transcribes audio and video files the user supplies by URL, and podcast feeds' episodes (RSS, Atom, JSON Feed,
or a site that advertises its feed; read by the shared mms_feeds code), into text, timed segments, SRT and WebVTT.
- Whisper through faster-whisper/CTranslate2 on CPU, int8, beam 5, with the Silero voice-activity filter (skips
silence and long music before the model sees it) and without conditioning on the previous text (stops a misheard
passage from repeating for minutes). Two models: base (default) and small. Automatic language detection or one of
46 languages; transcribe or translate to English.
- ffmpeg decodes the first audio stream (video files: only the sound) to 16 kHz mono; ffprobe reads the container
first. Each file is decoded and transcribed in its own process with a deadline (the run's timeout) and a memory
cap; the transcript is written as it's produced, so a file stopped by the run's timeout or a crash still returns
what was transcribed, charged for what it covers.
- Charged per started audio minute of each file (
audio-minute for base, audio-minute-accurate for small), once
the transcript is in the dataset; transcripts themselves (apify-default-dataset-item) are free. Nothing is
charged for files that couldn't be downloaded or decoded, have no audio track, or have no speech. Minutes are
reserved before each file (its first minute before it's even downloaded), so a run stops at the maximum cost per
run and cuts a file where the budget runs out. Proposed prices: $10.00 and $25.00 per 1,000 minutes (COSTS.md).
- "Only new episodes since the last run": a named key-value store in the user's account, per feed and per model,
language and task. The first run marks the back catalogue as seen; an episode is remembered only once its
transcript is in the dataset, so failed episodes are retried.
- Downloads through the shared client (robots.txt incl. AI-crawler opt-outs, private-network guard, ports 80/443),
streamed to disk, 1 GB per file, 8 GB per run. Files are processed one at a time, in input order (feeds:
newest episode first), each deleted as soon as it's transcribed. Links to video and social
platforms' pages (YouTube, TikTok, Spotify, SoundCloud, ...) are refused before any request.
- The input schema's example recordings (the default for
mediaUrls, which Apify fills in whenever a run leaves the
field out) are skipped when a run gives only feeds, so an API user asking for feeds doesn't pay for them.
Before building (ACTOR-CHECKLIST.md, section 0), 2026-09-25:
- Source and terms: no fixed source. The actor fetches only the media URLs and podcast feeds the user supplies
(PLAN.md's allowed class "tools that only process URLs or files the user supplies"; feeds are RSS published for
machines), as a logged-out visitor, honouring robots.txt and AI-crawler opt-outs. No platform links and no
yt-dlp: YouTube and the other platforms stay on the legal hold. No API key, contact address or other identity of
ours is used; the only identity is the honest User-Agent every actor sends. The README tells users they need the
right to transcribe what they submit. The default input is two public-domain files on Wikimedia Commons
(Armstrong_Small_Step.ogg, NASA; The_New_Colossus.ogg), upload.wikimedia.org robots.txt:
User-agent: * /
Disallow: /wikipedia/commons/archive/ only.
- Models: downloaded at image build time from Hugging Face (Systran/faster-whisper-base and -small, pinned
revisions in src/models.py, MIT, converted from OpenAI's MIT-licensed Whisper weights); never during a run.
- Demand (RESEARCH-candidates.md, store_merged.json, 2026-09-24):
850 users/30d across non-platform transcriber
actors, the largest clean pool found. Leaders: sian.agency 283 ($300 per 1,000 minutes), steadyfetch 99 ($3),
kaz_kakyo 76 ($10), amanatools 49 ($8), sauliusautomatesit 37 ($40, fails 17%).
- Licences of every component: faster-whisper MIT; CTranslate2 MIT; Whisper weights MIT; Silero VAD model
(bundled with faster-whisper) MIT; onnxruntime MIT; tokenizers and huggingface_hub Apache-2.0; numpy BSD-3; PyAV
BSD-3 (installed by faster-whisper, not used for decoding; its wheel bundles LGPL FFmpeg libraries); ffmpeg from
Debian (a GPL build), run as a separate program, never linked.