# Audiobook ACX Check & Master (`madrasco/audiobook-acx-check-master`) Actor

Measures audiobook chapter files against ACX's published technical specs (RMS, peak, noise floor, room tone, MP3 format) and returns mastered 192 kbps CBR 44.1 kHz MP3s with a before/after PASS/FAIL report per chapter.

- **URL**: https://apify.com/madrasco/audiobook-acx-check-master.md
- **Developed by:** [Madrasco](https://apify.com/madrasco) (community)
- **Categories:** For creators, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% 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

## Audiobook ACX Check & Master

Give it the download links to your audiobook chapter files. It measures each one against the technical specs ACX publishes for audiobook submissions, masters it, and gives you back a 192 kbps CBR 44.1 kHz MP3 for each chapter plus a before/after report with PASS or FAIL for each requirement.

**What this is not:** ACX also checks every audiobook by ear (plosives, mouth noise, edits, consistency, human narration). This actor measures only the published *technical* specs. A PASS here means the file meets those numbers as we measure them. It does **not** guarantee that ACX will approve your audiobook.

Not affiliated with or endorsed by ACX, Audible or Amazon. ACX and Audible are trademarks of Audible, Inc.; used only to name the specs we measure against.

### What it checks

Spec source: ACX audio submission requirements, https://help.acx.com/s/article/what-are-the-acx-audio-submission-requirements (page dated Apr 15, 2026; accessed 2026-09-25).

| Requirement (ACX) | How we measure it |
|---|---|
| RMS between -23 dB and -18 dB | Unweighted RMS of the whole file, in dBFS |
| Peaks no higher than -3 dB | Sample peak **and** 4x-oversampled true peak (ffmpeg `ebur128`); both must be at or below -3 dB. This is stricter than ACX's wording. |
| Noise floor no higher than -60 dB RMS | RMS of the quietest 500 ms of the file, ignoring pure digital silence. ACX doesn't define the window; 500 ms is what Audacity's ACX Check uses. |
| Room tone at the start and end: ACX recommends 1 to 5 s; more than 5 s is not allowed | Time before the first and after the last 100 ms of audio that is within 22 dB of the file's overall RMS. We mark under 1 s as FAIL as well as over 5 s. |
| 192 kbps or higher CBR, 44.1 kHz MP3 | Read from the output file (codec, bitrate, CBR header, sample rate) |
| No longer than 120 minutes | Duration |
| All files mono, or all stereo | Every output uses the channel setting you choose (mono by default) |

### What it does to the audio

1. Trims room tone longer than 1.5 s at the start or 2.5 s at the end. Where room tone is too short, it pads with a loop of the recording's own quietest half-second. It never adds digital silence.
2. If the noise floor would end up above -60 dB, it tries gentle spectral noise reduction (ffmpeg `afftdn`, 12 dB). It keeps the result only if the measured floor drops by at least 1 dB and nothing else breaks.
3. Sets the gain so the RMS lands at about -20 dB.
4. Limits peaks to -4 dB, or lower if the encoded file's true peak still goes over -3 dB.
5. Encodes to MP3 at 192 kbps CBR, 44.1 kHz. It then decodes that MP3 and measures it again. The report comes from that final measurement, not from the settings.

**Recordings it can't fix get FAIL with a reason, not a fake pass.** For example: a noise floor that stays above -60 dB even after noise reduction, no narration detected, files over 120 minutes (split them first), or unreadable files. If the pauses between phrases are pure digital silence (a noise gate or silence removal), the row says so (`cause`: digital-silence pauses) rather than calling it noise: the noise floor can't be measured and there is no room tone to pad with, so re-export without the gate or fill the pauses with recorded room tone. Digital-silence pauses in a file that otherwise passes are listed under `warnings`. When a FAIL file was still processed, the best-effort MP3 is stored so you can hear it, and the row is marked FAIL.

### Input

Only submit recordings you own or have permission to process.

- `audioUrls`: direct download links, one chapter per file, up to 100 per run (1 GB and 120 minutes each). Any format ffmpeg reads: MP3, WAV, FLAC, M4A and others.
- Run time: measured on Apify at the default 1 GB memory, a 13-minute chapter took about 4.5 minutes to process (run of 2026-09-25). The default run timeout is 1 hour, so for a whole book raise the timeout in the run options or split it across runs.
- `channels`: `mono` (default) or `stereo`.
- `allowDenoise`: default on.

### Output

- **Key-value store:** one MP3 per chapter, `001-<file name>-acx.mp3`, and so on. `OUTPUT` holds the run totals.
- **Dataset:** one row per chapter. Each row has `verdict`, `reasons`, `before` and `after` measurements (`rmsDb`, `samplePeakDb`, `truePeakDb`, `noiseFloorDb`, `headRoomToneS`, `tailRoomToneS`, `durationS`), `checksBefore` and `checks` (PASS/FAIL per requirement), `inputFormat` and `outputFormat`, `processing` (trim, pad, gain, limiter and denoise settings actually used), and `outputUrl`.

### Example (measured)

"The Gift of the Magi" by O. Henry, a public-domain LibriVox recording (13 min 22 s, 64 kbps stereo MP3 at 24 kHz):

| | RMS | True peak | Noise floor | Head / tail room tone | Format | Verdict |
|---|---|---|---|---|---|---|
| Before | -24.7 dB | -1.1 dBTP (sample peak +0.5) | -59.5 dB | 0.0 / 3.65 s | 64 kbps, 24 kHz | FAIL |
| After | -20.7 dB | -3.8 dBTP | -66.9 dB (noise reduction kept) | 2.45 / 2.5 s | 192 kbps CBR, 44.1 kHz mono | PASS |

### Privacy

Your files are downloaded into the run, processed, and the results are stored in your run's storage. They stay there for your Apify plan's retention period, then Apify deletes them. Depending on your account's storage access setting, anyone with an `outputUrl` link may be able to download a file, so share those links with care. We never copy or keep your files.

### Who built it

Built and maintained by Madrasco with AI assistance. Your audio is processed only by standard ffmpeg filters (gain, limiter, spectral noise reduction). No AI voice or generation is applied.

### Support

Report problems in this actor's Issues tab. Replies are AI-assisted, and a human owner can be reached on request.

# Actor input Schema

## `audioUrls` (type: `array`):

Direct download links to your chapter files (MP3, WAV, FLAC, M4A and other formats ffmpeg reads), one chapter per file, in book order. Up to 100 files per run, 1 GB and 120 minutes each.

## `channels` (type: `string`):

ACX needs every file in the same format. Mono suits most narration.

## `allowDenoise` (type: `boolean`):

Only tried when the noise floor would end up above -60 dB, and kept only if it lowers the measured floor by at least 1 dB.

## Actor input object example

```json
{
  "audioUrls": [
    "https://archive.org/download/spc141_1503_librivox/spc141_noiselesspatientspider_wt_64kb.mp3"
  ],
  "channels": "mono",
  "allowDenoise": true
}
```

# Actor output Schema

## `chapters` (type: `string`):

One dataset row per chapter file: before/after measurements, PASS/FAIL against ACX's published specs, reasons and a link to the mastered MP3.

## `files` (type: `string`):

The mastered 192 kbps CBR 44.1 kHz MP3 for each processed chapter, plus the OUTPUT run summary.

## `summary` (type: `string`):

Counts of files that pass, fail or could not be processed.

# 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 = {
    "audioUrls": [
        "https://archive.org/download/spc141_1503_librivox/spc141_noiselesspatientspider_wt_64kb.mp3"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("madrasco/audiobook-acx-check-master").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 = { "audioUrls": ["https://archive.org/download/spc141_1503_librivox/spc141_noiselesspatientspider_wt_64kb.mp3"] }

# Run the Actor and wait for it to finish
run = client.actor("madrasco/audiobook-acx-check-master").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 '{
  "audioUrls": [
    "https://archive.org/download/spc141_1503_librivox/spc141_noiselesspatientspider_wt_64kb.mp3"
  ]
}' |
apify call madrasco/audiobook-acx-check-master --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,madrasco/audiobook-acx-check-master"
        }
    }
}
```

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/mo4fEPcw5DWsWXrAG/builds/QfnmzZ35wRJ3vElcv/openapi.json
