Audio Splitter & Compressor for Whisper and Speech-to-Text avatar

Audio Splitter & Compressor for Whisper and Speech-to-Text

Pricing

from $2.00 / 1,000 audio minute processeds

Go to Apify Store
Audio Splitter & Compressor for Whisper and Speech-to-Text

Audio Splitter & Compressor for Whisper and Speech-to-Text

Split audio/video at pauses or compress under 25 MB for OpenAI Whisper, Groq & other STT APIs. Timestamps for stitching. ffmpeg, no AI key.

Pricing

from $2.00 / 1,000 audio minute processeds

Rating

0.0

(0)

Developer

Kaizoku Data

Kaizoku Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 hours ago

Last modified

Categories

Share

Make your own audio or video files ready for a speech-to-text API such as OpenAI Whisper / gpt-4o-transcribe, Groq, AssemblyAI or Deepgram. The Actor extracts the audio, compresses it under an upload limit (OpenAI: 25 MB) or splits long recordings at pauses into chunks, each with start and end times so you can stitch the transcripts back together.

Price: $0.002 per minute of audio + $0.006 per 10 MB downloaded. A 1-hour mp3 podcast costs about $0.16. Files that fail are not charged.

  • Split at pauses, not mid-word: chunks under your size and length limits, with optional 0–5 s overlap and a manifest (startSec, endSec) for stitching.
  • Fit under the limit: OpenAI 25 MB, Groq free tier 25 MB, Groq paid tier 100 MB, or a custom size.
  • Any format in, speech-ready out: m4a, opus, webm, mp4, mov, wav and most other formats become mono 16 kHz mp3 (or m4a, ogg, flac, wav). Video and all metadata are removed.
  • Built for n8n, Make and Zapier (n8n Cloud can't run ffmpeg) and for AI agents. It runs ffmpeg only: no AI key, no transcription, no browser, no proxy.
  • Quick start: press Start. The prefilled input splits a 3.5-minute public-domain speech into 1-minute chunks: 4 mp3 files for about $0.014.

Why

  • OpenAI's transcription API rejects files over 25 MB, so an hour-long recording or any video is too big.
  • Phone and browser recordings (Android .m4a, WhatsApp .opus, browser .webm) are often rejected or mis-read.
  • Splitting at a fixed length cuts words in half and ruins the transcript at every seam.

This Actor fixes all three in one step and hands back download links.

What it does

OperationResult
Split (default)Chunks no longer than Max chunk length (default 10 min) and no bigger than the target size, cut in pauses. The pause level adapts to each recording, so noisy audio still gets clean cuts. Optional overlap of 0 to 5 s.
FitOne file compressed to fit the target size. The bitrate is lowered as needed, but not below what keeps speech clear (16 kbps for mp3 and m4a, 8 kbps for Opus). If it can't fit, the file is skipped (not charged) and you're told to use Split.
ConvertOne file in the chosen format, with no size control.

Every output is mono, 16 kHz by default (what speech models use) in mp3 (accepted everywhere), m4a (AAC), ogg (Opus), flac or wav. Video, cover art, subtitles and all metadata (tags, GPS, device names) are removed.

Targets: OpenAI (25 MB), Groq free tier (25 MB), Groq paid tier (100 MB) or custom (1 to 150 MB). Files stay 3% below the limit.

Input

FieldWhat it does
Audio or video file URLsDirect http(s) links, one per line: mp3, m4a, aac, wav, ogg, opus, webm, flac, mp4, mov, mkv, amr and most other formats ffmpeg reads. Default: a 3.5-minute public-domain speech, so the default run works.
Uploaded filesUpload from your computer (the field stores the file in a key-value store), or paste a key-value store record URL.
What to doSplit, Fit or Convert (see above).
Target size limitOpenAI 25 MB, Groq 25 MB, Groq 100 MB or Custom.
Max chunk lengthSplit only. Default 10 minutes (some models also limit duration).
OverlapSplit only. 0 to 5 s repeated at the start of each later chunk. Overlap is not charged.
Output format, bitrate, sample rate, monoDefaults: mp3, 48 kbps, 16000 Hz, mono. 48 kbps mono mp3 is about 21 MB per hour.
Max input file sizeDefault 500 MB, hard cap 2,000 MB. Also limited by the run's disk (2 × memory): the default 1 GB memory allows files up to about 1.2 GB. A file that would need more disk to process is skipped with a clear message, not charged.
Max duration per fileDefault 240 min, hard cap 600 min. Longer files are skipped, not charged.
Download timeoutPer file, default 300 s.

Example: split a list of meeting recordings for OpenAI, with 2 s overlap.

{
"audioUrls": ["https://files.example.com/meeting-2026-10-12.m4a", "https://files.example.com/interview.mp4"],
"operation": "split",
"target": "openai-25mb",
"maxChunkMinutes": 10,
"overlapSeconds": 2
}

Example: one WhatsApp voice note or phone recording, compressed into a single file under 25 MB for Groq's free tier.

{
"audioUrls": ["https://files.example.com/voice-note.opus"],
"operation": "fit",
"target": "groq-25mb"
}

Example: a long webinar video for Groq's paid tier (100 MB uploads), 30-minute chunks, smaller Opus files (check that your service accepts ogg first).

{
"audioUrls": ["https://files.example.com/webinar-recording.mp4"],
"operation": "split",
"target": "groq-100mb",
"maxChunkMinutes": 30,
"overlapSeconds": 3,
"format": "ogg",
"bitrateKbps": 32
}

Output

One dataset row per output file. The audio files are in the run's key-value store, and url is a direct download link:

{
"inputIndex": 0,
"sourceUrl": "https://files.example.com/meeting-2026-10-12.m4a",
"fileName": "meeting-2026-10-12.m4a",
"status": "ok",
"operation": "split",
"chunkIndex": 1,
"chunkCount": 7,
"startSec": 598.2,
"endSec": 1196.84,
"durationSec": 598.64,
"overlapBeforeSec": 2,
"cutAt": "silence",
"url": "https://api.apify.com/v2/key-value-stores/<store>/records/0001-meeting-2026-10-12-002.mp3?signature=…",
"key": "0001-meeting-2026-10-12-002.mp3",
"sizeBytes": 3591840,
"sha256": "…",
"format": "mp3",
"codec": "mp3",
"bitrateKbps": 48,
"sampleRate": 16000,
"channels": 1,
"sourceDurationSec": 3901.4,
"sourceSizeBytes": 61234567,
"sourceContainer": "mov,mp4,m4a,3gp,3g2,mj2",
"sourceCodec": "aac",
"sourceHadVideo": false,
"warnings": [],
"processedAt": "2026-10-19T09:00:00.000Z"
}
  • startSec / endSec are positions in the source. Add startSec to the timestamps your speech-to-text service returns for a chunk to get times in the full recording. With overlap, drop the first overlapBeforeSec seconds of each later transcript.
  • cutAt is silence (the cut is in a pause), hard (no pause near the limit, so the cut is at the limit and a few seconds of overlap helps) or end.
  • A file that can't be processed gets one row with status: "error", an errorCode and a message, and is not charged. Codes:
    • link and download: invalid-url, blocked, platform, dns, network, http, redirects, timeout, too-large, not-media, disk;
    • audio: unreadable, no-audio, too-long, cannot-fit, too-many-chunks, chunk-too-large, output-too-large, ffmpeg;
    • billing: budget.
  • The RUN_SUMMARY record has counts, minutes and input charged, bytes downloaded and stored, and why the run stopped.

Links stay valid as long as the run's storage is kept (your account's data retention). Download the chunks or transcribe them before then.

Use it via API, n8n or Make (full transcription flow)

The flow is always the same: run this Actor → loop over the chunk rows → download each url → send it to your speech-to-text service → join the texts in chunkIndex order. Get an Apify API token in Apify Console → Settings → API & Integrations, and keep it and your speech-to-text key in environment variables (APIFY_TOKEN, OPENAI_API_KEY or GROQ_API_KEY below).

cURL (step 1: run the Actor and get the chunk rows as JSON; this synchronous endpoint waits up to 5 minutes, which suits short files; for long recordings or many files use the clients below, which wait as long as the run takes):

curl -X POST "https://api.apify.com/v2/acts/ataism~whisper-audio-splitter/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"audioUrls": ["https://files.example.com/meeting.m4a"], "operation": "split", "target": "openai-25mb", "overlapSeconds": 2}'

Step 2, for each row with "status": "ok": download url and transcribe it, for example with OpenAI (whisper-1 or gpt-4o-transcribe) or Groq (whisper-large-v3-turbo; same request shape, at https://api.groq.com/openai/v1/audio/transcriptions):

curl -s -o chunk.mp3 "<url from the row>"
curl https://api.openai.com/v1/audio/transcriptions \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-F file=@chunk.mp3 -F model=whisper-1

Python (pip install "apify-client>=3" openai):

import os, urllib.request
from apify_client import ApifyClient
from openai import OpenAI
apify = ApifyClient(os.environ["APIFY_TOKEN"])
run = apify.actor("ataism/whisper-audio-splitter").call(run_input={
"audioUrls": ["https://files.example.com/meeting.m4a"],
"operation": "split",
"target": "openai-25mb",
"overlapSeconds": 2,
})
chunks = [c for c in apify.dataset(run.default_dataset_id).iterate_items() if c["status"] == "ok"]
chunks.sort(key=lambda c: (c["inputIndex"], c["chunkIndex"]))
stt = OpenAI() # OpenAI key from OPENAI_API_KEY. For Groq:
# stt = OpenAI(base_url="https://api.groq.com/openai/v1", api_key=os.environ["GROQ_API_KEY"])
texts = []
for c in chunks:
audio = urllib.request.urlopen(c["url"]).read()
result = stt.audio.transcriptions.create(model="whisper-1", file=(c["key"], audio)) # Groq: "whisper-large-v3-turbo"
texts.append(result.text)
print("\n".join(texts))

(With apify-client versions before 3.0, call() returns a dict: use run["defaultDatasetId"].)

JavaScript (npm install apify-client; Node 18+ for the built-in fetch):

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('ataism/whisper-audio-splitter').call({
audioUrls: ['https://files.example.com/meeting.m4a'],
operation: 'split',
target: 'openai-25mb',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const chunks = items.filter((c) => c.status === 'ok').sort((a, b) => a.chunkIndex - b.chunkIndex);
const texts = [];
for (const c of chunks) {
const form = new FormData();
form.append('file', await (await fetch(c.url)).blob(), c.key);
form.append('model', 'whisper-1');
const res = await fetch('https://api.openai.com/v1/audio/transcriptions', {
method: 'POST',
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: form,
});
texts.push((await res.json()).text);
}
console.log(texts.join('\n'));

n8n (n8n Cloud needs no ffmpeg):

  1. Start with any trigger that gives you a direct file link (Webhook, Google Drive with a shared link, a form).
  2. Apify node, operation Run an Actor and get dataset, Actor ataism/whisper-audio-splitter, input {"audioUrls": ["{{ $json.fileUrl }}"], "operation": "split", "target": "openai-25mb"}. It outputs one item per chunk, and the next nodes run once per item.
  3. Filter on status = ok, then HTTP Request (GET {{ $json.url }}, response format File).
  4. OpenAI node, Audio → Transcribe a Recording on that file; or for Groq an HTTP Request POST to https://api.groq.com/openai/v1/audio/transcriptions with Form-Data: file (the binary) and model = whisper-large-v3-turbo.
  5. Sort by chunkIndex, then Aggregate the texts and join them. Add startSec to any timestamps your service returns.

Make:

  1. Apify module Run an Actor with ataism/whisper-audio-splitter and your input, Run synchronously set to Yes.
  2. Apify module Get Dataset Items with the run's default dataset ID: one bundle per chunk, so the next modules run once per chunk. Add a filter status = ok.
  3. HTTP Get a file with the chunk's url.
  4. Your transcription step: the OpenAI app's transcription action, or an HTTP request (multipart/form-data: file and model) to OpenAI's or Groq's /audio/transcriptions endpoint.
  5. A Text aggregator joining the texts (sort by chunkIndex first). Zapier works the same way with the Apify app's run-Actor action and the Webhooks/OpenAI steps.

Pricing

Pay per event, charged only for files that were processed and saved:

  • audio-minute: $0.002 per started minute of source audio (overlap is free);
  • input-10mb: $0.006 per started 10 MB downloaded;
  • plus Apify's standard Actor-start event.
ExampleCost
1-minute voice note (1 MB)$0.008
10-minute call (10 MB)$0.026
1-hour podcast mp3 (58 MB)$0.156
1-hour 720p video (700 MB)$0.54
10 one-hour podcast mp3s (58 MB each)$1.56

Failed downloads, non-media links, files that are too long or too big and files that can't fit are not charged. Set Max total charge in the run options to cap spending. The Actor checks the budget before working on each file, so it never charges part of a file. When the budget runs out, the rest of the list is skipped.

Privacy

  • Files are processed on the Actor's temporary disk and deleted as soon as each file is done. The original file is never stored. Only the outputs you asked for go into your run's key-value store.
  • No transcription, no analysis, no AI service. The audio is not listened to, and nothing is sent anywhere except your own storage.
  • All metadata is stripped from the outputs. Logs show only a URL's host and path (never its query string), the sizes and the status.
  • Your dataset and key-value store belong to your Apify account and follow its retention settings. sourceUrl echoes what you supplied (including any signed query string).

Safety and limits

  • Only http and https links to public addresses are fetched. Private, loopback, link-local and internal addresses are blocked, including after redirects (at most 5, each re-checked) and at connection time.
  • Direct file links only. Links to YouTube, TikTok, Instagram, Facebook, X, Vimeo, SoundCloud, Spotify, Twitch, Reddit, LinkedIn and Google services (including Google Drive) are refused: this Actor does not download from platforms. Upload the file instead.
  • The first 4 KB of every download are checked; web pages and other non-media files are rejected at once.
  • Limits: 1,000 files per run; input up to 2,000 MB and 600 min per file; at most 500 chunks per file; 150 MB per output file. Files are processed one at a time. Memory: default and minimum 1,024 MB. Give big files more memory, because disk is 2 × memory.
  • Bad links cost download and run time even though they aren't charged. A run therefore stops after 50 failed files, after 20 minutes spent on failed files, or after 1,000 MB downloaded for them. A download that sends no data for 60 s is dropped.
  • Billing uses the duration actually processed. If a file's header claims a shorter length than the audio really has, at most 10% + 5 s beyond the header is processed.
  • If Apify restarts the run (for example, a server migration), it continues where it stopped. Files already finished are not processed or charged again.
  • You are responsible for having the right to process the files you give this Actor (copyright, consent of the people recorded, data-protection law).
  • Built with FFmpeg (LGPL/GPL), run unmodified as a command-line tool.

FAQ

Does it transcribe? No. It prepares the audio for the speech-to-text service you already use, with your own key and at its price (for example, Groq listed whisper-large-v3-turbo at about $0.04 per audio hour in October 2026).

Why mp3 by default? Every major speech-to-text API accepts it. Opus (ogg) is smaller for the same quality: check that your service accepts it before you switch.

My file is a video. That's fine: the audio track is extracted, and video is dropped.

The cut fell in the middle of a word. That happens only when there is no pause near the limit (cutAt: "hard"). Add 2 to 3 s of overlap, or raise the max chunk length.