Skip to main content
ClaudeWave

Assertions for AI-generated media. The worst bugs in generated video and audio don't throw — pace, loudness, truncation, dead air, wrong presenter, broken layout. rendercheck makes them throw.

ToolsRegistry oficial0 estrellas0 forksPythonMITActualizado today
ClaudeWave Trust Score
95/100
Verified
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Topics declared
  • Documented (README)
Last scanned: 8/6/2026
Get started
Method: Clone
Terminal
git clone https://github.com/rogermsc/rendercheck
1. Clone the repository.
2. Follow the README for installation and usage instructions.
Casos de uso

Resumen de Tools

# rendercheck

<!-- mcp-name: io.github.rogermsc/rendercheck -->
<!--
  The line above is not decoration. The MCP registry proves who owns a PyPI
  package by fetching its README and looking for that marker, so it has to ship
  inside the published long_description. Removing it un-verifies the registry
  listing on the next release. See server.json.
-->

[![PyPI](https://img.shields.io/pypi/v/rendercheck)](https://pypi.org/project/rendercheck/)
[![CI](https://github.com/rogermsc/rendercheck/actions/workflows/ci.yml/badge.svg)](https://github.com/rogermsc/rendercheck/actions/workflows/ci.yml)
[![Python](https://img.shields.io/badge/python-3.10%20%E2%80%93%203.14-blue)](https://github.com/rogermsc/rendercheck)
[![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)

**The worst bugs in generated media don't throw.**

> "the audio often cuts off the final sentence […] though the API returns
> success without error signals"
>
> — a developer on the [OpenAI forum](https://community.openai.com/t/1379584),
> April 2026, describing production output

![rendercheck demo](docs/demo.gif)

If you generate speech or video with a model — TTS, voice agents, podcasts,
avatars, AI video — your tests catch the exception that never happens. They do
not catch the narration that reads at 300 words per minute, the voice track
sitting 18 dB below the footage it's cut against, the clip that rendered at 42%
length and got cached as a success, the captions that describe the audio three
seconds before it happens, or the file whose audio track is missing entirely.

The 2026 state of the art for catching these is *a person listening to the
output*. That works, and it costs more than everything else in your pipeline
combined.

`rendercheck` makes them throw.

```python
from rendercheck import assert_pace, assert_loudness, looks_ok

assert_pace("episode-12.mp3", "episode-12.vtt")
assert_loudness("episode-12.mp3")
looks_ok("slide-14.png", ["the title fits on one line"])
```

Plain assert functions. No framework, no runner, no service. They raise
`AssertionError`, so they already work in pytest, in CI, or in a five-line
script. Seventeen of the eighteen checks have **no dependencies and make no
network calls** — if you have `ffmpeg`, you're ready.

---

## Quickstart

You need `ffmpeg` on your PATH (`brew install ffmpeg`, `apt-get install ffmpeg`,
or `winget install ffmpeg`). Then:

```bash
pip install rendercheck
rendercheck demo
```

Or drop a file into the **[playground](https://rogermsc.github.io/rendercheck/playground/)**
— same checks, running on ffmpeg compiled to WebAssembly, nothing uploaded.

`demo` synthesises eight defective files and runs the real checks against them,
so you can see it fire without owning a broken render. Verbatim, first two of
eight:

```
Narration too fast
  A voice picked to match a presenter's face read English at machine-gun speed. Valid audio, correct timing, perfectly in sync.

  $ rendercheck check machine-gun.wav --script narration.vtt

  FAIL  pace        narration pace 300 WPM exceeds 245 (300 words in 60.0s) -- this reads as machine-gun delivery and listeners cannot follow it: machine-gun.wav
  PASS  loudness    -16.1 LUFS
  PASS  dead air    0.0 s silence
  PASS  truncation  8.9 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS

Levels that don't match
  Synthesised narration landed 18 dB under the footage it was cut against. Nobody noticed until viewers rode the volume knob.

  $ rendercheck check too-quiet.wav

  SKIP  pace        no --script given
  FAIL  loudness    -34.2 LUFS is 18.2 dB quieter than the -16 target -- it will sound inaudible next to correctly-levelled audio cut alongside it: too-quiet.wav
  PASS  dead air    0.0 s silence
  PASS  truncation  8.8 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS
```

…and one of the two added in 0.3.0:

```
Captions against the wrong clock
  A concatenation added three seconds of pre-roll after the captions were written. Both files are perfectly valid on their own.

  $ rendercheck check late-captions.wav

  SKIP  pace        no --script given
  PASS  loudness    -16.0 LUFS
  PASS  dead air    0.0 s silence
  PASS  truncation  74.3 dB of fall-off at the end
  PASS  clipping    0 samples at 0 dBFS
  FAIL  captions    late-captions.vtt runs 3.0s late against late-captions.wav, past the 0.75s limit -- every line arrives at the wrong moment, and both files are individually valid so nothing else catches it
```

Then point it at your own output:

```bash
rendercheck check episode-12.mp3 --script episode-12.vtt --preset podcast
```

Exit code is 1 if anything failed — **or if nothing could be measured**, because
a run that looked at nothing is not a clean one. A path you typo'd exits 2.
`--json` gives you the same report for pipelines in any language, and `--strict`
rejects partial runs too.

## Where is this file going?

"How loud should this be?" has no single answer — it depends entirely on where
the file ends up, and every platform publishes a different number. `--preset`
turns that table into something a build can enforce:

```
$ rendercheck presets

  preset    target     tol     peak  source
  youtube     -14L   1.0dB   -1.0TP  YouTube normalises playback to -14 LUFS
  spotify     -14L   1.0dB   -1.0TP  Spotify, including podcasts, at -14 LUFS
  tiktok      -14L   1.5dB   -1.0TP  TikTok and Instagram, measured rather than published
  podcast     -16L   1.0dB   -1.0TP  AES71 / Apple Podcasts: -16 LUFS stereo, -19 mono
  apple       -16L   1.0dB   -1.0TP  Apple Music Sound Check, -16 LUFS
  web         -16L   2.0dB       --  spoken-word web video -- rendercheck's own defaults
  ebu         -23L   1.0dB   -1.0TP  EBU R128, European broadcast
  atsc        -24L   2.0dB   -2.0TP  ATSC A/85, North American broadcast
  netflix     -27L   2.0dB   -2.0TP  Netflix delivery, dialog-gated
```

None of those numbers are ours. The contribution is that `--preset ebu` is a
decision a reviewer can read, where `--target-lufs -23` is a magic number the
next person will not dare touch. A preset that states a ceiling also switches on
the **true-peak** check, which catches a master measuring clean locally and
distorting after upload. `web` exists only to *name* the built-in defaults, so
it states none and behaves exactly like passing no preset at all.

Project-wide settings go in `rendercheck.toml` (or `[tool.rendercheck]` in
`pyproject.toml`) so a CI step is not eight flags on one line:

```toml
preset = "podcast"
max_silence = 5.0
```

Flags you type still beat the file, and the file beats the built-in defaults.

In pytest they're just asserts — no plugin, no fixtures:

```python
@pytest.mark.parametrize("episode", EPISODES)
def test_episode_is_shippable(episode):
    assert_pace(episode.audio, episode.vtt)
    assert_loudness(episode.audio)
    assert_no_dead_air(episode.audio)
```

## "Isn't this forty lines of pyloudnorm?"

For one of the eighteen checks, roughly yes. None of these measurements are novel,
and it would be dishonest to imply otherwise:

| The measurement | Already available from |
|---|---|
| Integrated loudness, true peak | [pyloudnorm](https://github.com/csteinmetz1/pyloudnorm), ffmpeg's `loudnorm` |
| Silence detection | [pydub](https://github.com/jiaaro/pydub)`.silence`, ffmpeg's `silencedetect` |
| Duration, stream layout, frame rate | `ffprobe` |
| Black frames, freezes | ffmpeg's `blackdetect`, `freezedetect` |
| Caption↔audio offset | [ffsubsync](https://github.com/smacke/ffsubsync) — which *corrects* it |
| Container and codec conformance | [MediaConch](https://mediaarea.net/MediaConch) — policy-driven, pass/fail, from the CLI |
| Speaker identity | [resemblyzer](https://github.com/resemble-ai/resemblyzer) |
| Video quality metrics | [VMAF](https://github.com/Netflix/vmaf), [ffmpeg-quality-metrics](https://github.com/slhck/ffmpeg-quality-metrics) |

Most of those hand a **number to a researcher**. The two that are already gates
gate a different thing: MediaConch checks that a file conforms to a container
policy, which is a preservation question, not a perceptual one — a file can pass
every MediaConch rule and still be narrated at 300 WPM. ffsubsync will happily
realign captions that were never wrong, because it has no opinion about whether
they needed it.

What is actually missing, and what this is:

- **A threshold that came from a defect**, not from a paper. 245 WPM because a
  real voice narrated at 280 and shipped. −16 LUFS because narration landed at
  −34 against footage at −13.
- **A message that says what a person would notice.** "−34.0 LUFS" is a reading.
  "18.0 dB quieter than the −16 target — it will sound inaudible next to
  correctly-levelled audio cut alongside it" is a bug report.
- **Fail-open on infrastructure, fail-closed on a defect**, so it can sit in CI
  without becoming the thing that breaks the build for its own reasons.
- **Exit codes and one command over a directory**, rather than a notebook.

Against the LLM-eval tools the difference is structural rather than a matter of
coverage. [promptfoo](https://github.com/promptfoo/promptfoo),
[DeepEval](https://github.com/confident-ai/deepeval) and
[RAGAS](https://github.com/vibrantlabsai/ragas) are excellent and none of them
can do this: their test case is a **string**. There is no assertion to add,
because there is nowhere to put the file. Use them for the script; use this for
what the script turned into.

And if you already run broadcast QC — Interra BATON, Telestream Vidchecker,
QCTools — you have had most of this for twenty years. It just isn't in your git
hooks.

## In your pipeline

**GitHub Actions** — installs ffmpeg and fails the build on a defect:

```yaml
- uses: rogermsc/rendercheck@v0
  with:
    files: out/
    preset: podcast
    strict: "true"
```

**Node, Remotion, anything that renders in a build step:**

```bash
npx rendercheck check out/
```

**Docker**, if you would rather not have a Python toolchain
assertionsevaluationffmpeggenerative-aillmpytestqatestingtext-to-speechvideo

Lo que la gente pregunta sobre rendercheck

¿Qué es rogermsc/rendercheck?

+

rogermsc/rendercheck es tools para el ecosistema de Claude AI. Assertions for AI-generated media. The worst bugs in generated video and audio don't throw — pace, loudness, truncation, dead air, wrong presenter, broken layout. rendercheck makes them throw. Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-08-06.

¿Cómo se instala rendercheck?

+

Puedes instalar rendercheck clonando el repositorio (https://github.com/rogermsc/rendercheck) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.

¿Es seguro usar rogermsc/rendercheck?

+

Nuestro agente de seguridad ha analizado rogermsc/rendercheck y le ha asignado un Trust Score de 95/100 (tier: Verified). Revisa el desglose completo de comprobaciones superadas y flags en esta página.

¿Quién mantiene rogermsc/rendercheck?

+

rogermsc/rendercheck es mantenido por rogermsc. La última actividad registrada en GitHub es del 2026-08-06, con 0 issues abiertos.

¿Hay alternativas a rendercheck?

+

Sí. En ClaudeWave puedes explorar tools similares en /categories/tools, ordenados por popularidad o actividad reciente.

Despliega rendercheck en tu cloud

Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.

¿Mantienes este repo? Añade un badge a tu README

Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.

Featured on ClaudeWave: rogermsc/rendercheck
[![Featured on ClaudeWave](https://claudewave.com/api/badge/rogermsc-rendercheck)](https://claudewave.com/repo/rogermsc-rendercheck)
<a href="https://claudewave.com/repo/rogermsc-rendercheck"><img src="https://claudewave.com/api/badge/rogermsc-rendercheck" alt="Featured on ClaudeWave: rogermsc/rendercheck" width="320" height="64" /></a>

Más Tools

Alternativas a rendercheck