# Video & Audio Toolkit: Probe, Cut, Convert, Extract Audio (`andrew_babo/video-audio-toolkit`) Actor

Cloud ffmpeg/ffprobe/yt-dlp toolkit: probe video metadata, extract 16 kHz mono audio for speech to text, build a 480p proxy, cut segments frame-accurately, download and remux MP4.

- **URL**: https://apify.com/andrew\_babo/video-audio-toolkit.md
- **Developed by:** [Andrew Babo](https://apify.com/andrew_babo) (community)
- **Categories:** Videos, Developer tools
- **Stats:** 1,145 total users, 795 monthly users, 96.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-usage

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Video & Audio Toolkit — Probe, Cut, Convert, Extract Audio

A single cloud actor that replaces a local ffmpeg / ffprobe / yt-dlp install.
Give it a media URL (or a page URL) and get back metadata, a mono speech track
for transcription, a lightweight 480p analysis proxy, trimmed segments, or a
clean H.264/AAC faststart MP4.

**Use it when you need to:**

- read video metadata (duration, resolution, fps, codecs, streams) before processing
- extract **16 kHz mono audio** to feed a speech-to-text model
- build a **480p proxy** so face detection / scene analysis costs a fraction of the master
- **cut** one or many time windows out of a long video without re-encoding
- **download** a video by page URL, or just **resolve** its direct media URLs
- **remux / ingest** any container into a browser-friendly MP4
- grab **one window** of audio or video straight from a page URL, so you can fan
  out hundreds of parallel shards without ever hosting the full file

Everything runs headlessly on CPU. No GPU, no local installs, no desktop software.

### Quick start

```json
{
  "op": "probe",
  "source": "https://example.com/video.mp4"
}
```

Feature-detect the build (free, a few seconds, needs no source):

```json
{ "op": "capabilities" }
```

### Operations

| `op` | What it does | Needs `source` |
| --- | --- | --- |
| `probe` | ffprobe metadata: duration, size, streams, codecs, fps | yes |
| `plan_shards` | split a duration into shards for parallel processing | yes |
| `audio16k` | mono speech audio (`wav` / `mp3` / `opus`), optional time range | yes |
| `proxy` | fast 480p analysis proxy (audio kept by default) | yes |
| `cut` | trim one or many segments, stream copy or re-encode | yes |
| `ytdlp` | download by page URL (cookies / proxy supported) | yes (page URL) |
| `resolve` | print the direct media URLs only, no download | yes (page URL) |
| `audio_shard` | resolve + range-read + encode ONE audio window in one run | yes (page URL) |
| `video_window` | resolve + range-read + cut ONE full-res video window | yes (page URL) |
| `audio_full` | download the whole audio track once and host it | yes (page URL) |
| `ingest` | download and guarantee H.264/AAC faststart MP4 | yes |
| `remux` | any container/codec → faststart MP4 (stream copy when possible) | yes |
| `capabilities` | report ops, features and vCPUs of this build | no |

`source` accepts an `https://` URL or `kv:<storeId>/<key>` pointing at a record
produced by an earlier run, so actors can be chained without downloading
anything to your machine.

### Examples

**Extract speech audio for transcription**

```json
{
  "op": "audio16k",
  "source": "https://example.com/interview.mp4",
  "options": { "format": "wav", "sample_rate": 16000 }
}
```

**Build a 480p analysis proxy**

```json
{
  "op": "proxy",
  "source": "https://example.com/podcast.mp4",
  "options": { "height": 480, "fps": 15, "crf": 28, "audio": true }
}
```

**Cut three highlight segments (no re-encode)**

```json
{
  "op": "cut",
  "source": "https://example.com/stream.mp4",
  "options": {
    "segments": [
      { "start_sec": 12.4, "end_sec": 41.0, "name": "hook" },
      { "start_sec": 320, "end_sec": 372, "name": "tip" }
    ]
  }
}
```

**One audio window straight from a page URL (fan-out friendly)**

```json
{
  "op": "audio_shard",
  "source": "https://www.youtube.com/watch?v=XXXXXXXXXXX",
  "options": { "start_sec": 600, "duration_sec": 240, "format": "mp3", "bitrate": "64k" }
}
```

### Output

Every run pushes one dataset item:

```json
{
  "status": "success",
  "op": "audio16k",
  "artifacts": [
    { "name": "audio16k", "kv_key": "audio16k.wav", "url": "https://api.apify.com/v2/key-value-stores/.../audio16k.wav", "bytes": 5412233 }
  ],
  "meta": { "duration_sec": 338.4, "sample_rate": 16000, "channels": 1 }
}
```

- `artifacts[].url` is a public URL you can hand straight to the next actor.
- `artifacts[].kv_key` is the key inside this run's key-value store (`kv:<storeId>/<key>`).
- `meta` carries per-op details (probe streams, shard plan, proxy dimensions, offsets...).

Set `output.signed_upload_url` to have the artifact PUT directly into your own
storage (S3, R2, GCS) so heavy files never sit on Apify.
Set `callback: { "url": "...", "secret_header": { "name": "...", "value": "..." } }`
to be notified with the result JSON the moment the run finishes.

### Error handling

Failures never return SUCCEEDED with zero items. You always get:

```json
{ "ok": false, "reason": "UPSTREAM_BLOCKED", "message": "..." }
```

| `reason` | Meaning | What to do |
| --- | --- | --- |
| `BAD_INPUT` | missing/invalid `source` or options | check the payload against the schema |
| `UPSTREAM_BLOCKED` | the host refused the download | pass `options.cookies` / `options.apify_proxy` |
| `TIMEOUT` | the operation exceeded the run timeout | raise `timeoutSecs`, or shard the work |
| `OOM_LIMIT` | not enough memory for this file | run with 16 GB, or use `proxy` / `cut` first |
| `INTERNAL` | unexpected failure | retry; open an issue with the run ID |

### Performance and cost

| Operation | Typical memory | Typical time (1 h source) |
| --- | --- | --- |
| `probe`, `resolve`, `plan_shards` | 1–2 GB | a few seconds |
| `audio16k`, `audio_full` | 4 GB | 20–60 s |
| `proxy` | 8–16 GB | 1–4 min |
| `cut`, `remux` (stream copy) | 4 GB | under 1 min |
| `ingest` (transcode) | 16 GB | several minutes |

16 GB (≈4 vCPU) is the recommended setting for anything that transcodes.

### FAQ

**Do I need ffmpeg installed?** No. Everything runs in the actor.

**Can I chain this with other actors?** Yes — pass `artifacts[].url` or
`kv:<storeId>/<key>` as the `source` of the next run.

**Does it re-encode when cutting?** Only if you ask for it (`options.reencode`).
By default segments are stream-copied, which is fast and lossless.

**How do I analyse a big video cheaply?** Run `proxy` once and analyse the 480p
copy. Results in normalised coordinates apply back to the master unchanged.

**Can I avoid storing files on Apify?** Yes — use `output.signed_upload_url`
together with `cleanup: "always"`.

# Actor input Schema

## `op` (type: `string`):

probe = ffprobe metadata. plan\_shards = shard plan, returned both as meta.shards and top-level shards \[{index,startSec,endSec,durationSec}]. audio16k = mono speech audio (wav|mp3|opus) with optional range. proxy = fast 480p analysis proxy. cut = trim segments. ytdlp = raw download by page URL. resolve = print the DIRECT media URLs (yt-dlp -g) with no download at all (options.want=audio|video|both, options.height, options.audio\_format, options.video\_format); ASR/vision actors range-read those URLs. ingest = download + guarantee h264/aac faststart mp4. remux = any container/codec to mp4 (stream-copy compatible streams, transcode only incompatible streams). capabilities = report ops/features/vcpus of this build and does not need source. audio\_shard = resolve + range-read + encode ONE audio window straight from a PAGE URL in a single run (options.start\_sec/duration\_sec/format/bitrate) — same exit IP as the resolve, so signed URLs stay valid and a client can fan out N shards without hosting the full track. video\_window = resolve + range-read + cut ONE full-res video window straight from a PAGE URL in a single run (options.start\_sec/duration\_sec/height/crf/preset/with\_audio); the output timeline starts at 0 and meta.offset\_sec says where it came from, so a client never waits for a hosted copy of the whole video. audio\_full = download the WHOLE audio track ONCE and host it as mono 16 kHz mp3/wav/opus (options.format/bitrate/sample\_rate) so every ASR shard range-reads that KV URL instead of hitting YouTube per shard.

## `source` (type: `string`):

https:// URL, or kv:<storeId>/<key> to read a record produced by an earlier run. For op=ytdlp this is the page URL. Required for every op except capabilities.

## `options` (type: `object`):

Per-op options. plan\_shards: shard\_sec (default 120), overlap\_sec (default 1). audio16k: sample\_rate, format (wav|mp3|opus; default wav), bitrate (e.g. "64k"), start/dur (or start\_sec/duration\_sec) to cut one window. proxy: height, fps, crf, audio (default true — op=asd needs it). cut: segments\[{start\_sec,end\_sec,name}], reencode, crf. ytdlp: format, aria2c, cookies (Netscape file content), cookies\_url, proxy (proxy URL), apify\_proxy {groups:\["RESIDENTIAL"],country}, player\_client (default "android,web\_safari"). ingest/remux: max\_height, crf, preset, audio\_kbps, copy\_only, transcode\_audio, kv\_key. Failures always return {ok:false, reason: OOM\_LIMIT|TIMEOUT|UPSTREAM\_BLOCKED|BAD\_INPUT|INTERNAL} — never SUCCEEDED with zero items.

## `output` (type: `object`):

{ signed\_upload\_url } to PUT a single artifact straight to your own storage — keeps heavy files off Apify entirely.

## `cleanup` (type: `string`):

on\_success = keep only the result artifacts in the run's key-value store (Apify expires them). always = also drop the artifact from the store after it was pushed to signed\_upload\_url. off = keep everything for debugging.

## `callback` (type: `object`):

{ url, secret\_header: { name, value } } — POSTed with the result JSON when the run finishes.

## Actor input object example

```json
{
  "op": "capabilities",
  "cleanup": "on_success"
}
```

# Actor output Schema

## `results` (type: `string`):

Full run result JSON: status, op, artifacts \[{name, kv\_key, url, bytes}], meta, timings, errors.

## `resultRecord` (type: `string`):

The same result JSON stored as the RESULT record of the default key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "op": "capabilities"
};

// Run the Actor and wait for it to finish
const run = await client.actor("andrew_babo/video-audio-toolkit").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "op": "capabilities" }

# Run the Actor and wait for it to finish
run = client.actor("andrew_babo/video-audio-toolkit").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "op": "capabilities"
}' |
apify call andrew_babo/video-audio-toolkit --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,andrew_babo/video-audio-toolkit"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/9BJXSNONxKn3OGsyW/builds/WHdr8lJyDZoiEjJ9I/openapi.json
