affaan-m/ECC · error · RuntimeError

Decoder produced a truncated frame

Error message

Decoder produced a truncated frame

What it means

transform_stream reads raw RGB frames from the ffmpeg decoder's stdout in exact frame_bytes chunks. If a read returns a partial chunk (neither empty nor a full frame), the frame would be malformed, so it raises RuntimeError('Decoder produced a truncated frame'). This guards against ffmpeg dying mid-frame or a pipe returning short reads.

Solutions

  1. Validate the source media integrity first (ffprobe / try a full decode pass: ffmpeg -v error -i src -f null -)
  2. Check ffmpeg's stderr for the real failure (codec errors, OOM kill, signal)
  3. Re-encode/re-mux the input to a well-formed intermediate file before applying the glitch effect
  4. Re-run; transient kills (OOM) may pass on a machine with more free memory or a lower width/height

Example fix

// before
render('truncated.mp4', ...)  # dies mid-frame
// after
subprocess.run(['ffmpeg','-v','error','-y','-i','truncated.mp4','-c','copy','fixed.mp4'])
render('fixed.mp4', ...)
Defensive patterns

Strategy: validation

Validate before calling

import subprocess
r = subprocess.run(['ffmpeg','-v','error','-i', src,'-f','null','-'], capture_output=True)
assert r.returncode == 0, r.stderr.decode()

Try / catch

try:
    render(src, 0, out)
except RuntimeError as e:
    if 'truncated frame' in str(e):
        # re-mux or re-encode source before retrying
        ...

Prevention

When it happens

Trigger: ffmpeg decoder process exits or is killed between full frames; a partial read from dec.stdout that returns fewer bytes than frame_bytes; corrupted/truncated source media ending mid-frame.

Common situations: ffmpeg crashing mid-decode (OOM, bad packet); source file truncated on disk; decoding a file whose advertised size exceeds actual bytes; platform pipe buffering edge cases.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/485945b9bf12a674. Report an issue: GitHub.

Appendix: source

Thrown at skills/taste-application/scripts/tasteforge/media/glitch.py:64

        zoomed = np.asarray(z.crop((x0, y0, x0 + width, y0 + height)), dtype=np.float32)
        decay = 0.90 + 0.06 * p
        acc = np.maximum(f.astype(np.float32), zoomed * decay)
        return acc.astype(np.uint8)

    def fx_drift(f, p):
        # subtle horizontal shift + RGB separation, very light
        shift = int(rng.integers(2, 18) * p) * (1 if rng.random() < 0.5 else -1)
        f = f.copy()
        f[:, :, 0] = np.roll(f[:, :, 0], shift, axis=1)
        f[:, :, 2] = np.roll(f[:, :, 2], -shift // 2, axis=1)
        return f

    while True:
        buf = dec.stdout.read(frame_bytes)
        if not buf:
            break
        if len(buf) != frame_bytes:
            raise RuntimeError("Decoder produced a truncated frame")
        f = np.frombuffer(buf, np.uint8).reshape(height, width, 3).copy()
        total = max(1, int(duration * fps))
        p = min(1.0, (n + 1) / (total * 0.6))

        if mode == "pixelsort":
            out = fx_pixelsort(f, p)
        elif mode == "feedback":
            out = fx_feedback(f, p)
        elif mode == "drift":
            out = fx_drift(f, p)
        else:
            # very light mosh
            out = f
            y = 0
            while y < height:
                bh = int(rng.integers(8, 28))
                if rng.random() < 0.12 * p:
                    shift = int(rng.integers(4, 40) * p) * (

View on GitHub (pinned to 8321021c54)