---
name: "data_animation_video"
description: "Turning a dataset into an animated chart video: pick the chart by the claim it must prove, keep every frame's numbers true to the source data, time annotations to data events, and hold axis and scale choices that do not mislead. Ships a CSV renderer and a frame verifier that recomputes every frame from the source CSV. Use when asked to animate a chart, make a data video, build a bar chart race, or turn a time series into a video."
---

# Data Animation Video

## Purpose
Turn a real dataset into a chart video a viewer can trust frame by frame. The difference from a template pack is the accuracy pass: the renderer records the exact value drawn in every frame in a manifest, and a verifier recomputes every frame from the source CSV before the video ships. A video that cannot pass the check does not ship.

Scope boundary: for a short looping GIF built from a handful of hand-picked numbers, use the animated-infographic skill instead. This skill is for dataset-driven video, where rows number in the dozens or hundreds and the numbers come from a file, not from memory.

## Workflow
1. **Write the claim first.** One sentence the video must prove, for example "north overtook south during the second half." Pick the chart from that sentence using `references/chart-choice.md`. The ranking behind the choices is Cleveland and McGill's: position and length are read more accurately than angle and area, so the headline number rides on position or length, never on pie slices or bubble sizes.
2. **Audit the data before animating it.** Load the CSV. Confirm the time column is sorted, samples are evenly spaced or the gaps are known, units are stated, and missing values are handled by a stated rule (drop, carry forward, or gap in the line). Record the source of the data. Any smoothing or aggregation gets decided here and labelled on screen later.
3. **Fix the scale before frame one.** Compute axis limits from the full dataset. Bars start at zero. One scale serves the whole video. Read `references/scale-integrity.md` for the lie factor, the log scale and dual axis rules, and why mid-animation rescaling fails viewers (Heer and Robertson, 2007: rescaling raised change-estimation error, common scales did better).
4. **Plan the timing and annotations.** Follow `references/annotation-timing.md`. Hold the first frame about 1 second, the last at least 1.5 seconds. Every annotation names a real data event (peak, crossover, threshold crossing) and appears when that event happens, then stays at least 1 second. Data time advances linearly: no easing on the mapping from video time to data time.
5. **Render with a manifest.** Default route is the bundled renderer: `python3 scripts/animate_csv.py data.csv --chart line --title "..." --source "Source: ..." --annotate "10:North moves ahead" --out out/video`. It writes `out/video.mp4` (H.264, yuv420p, 1280x720, 30 fps) and `out/video.manifest.json` with the data position and values drawn in every frame. Other stacks (matplotlib, D3, Flourish) are covered in `references/tooling-notes.md`, and each must produce an equivalent manifest.
6. **Verify every frame.** Run `python3 scripts/verify_frames.py data.csv out/video.manifest.json`. It checks that every frame's values match the declared interpolation of the CSV within 0.5 percent, that every source row appears as an exact frame at least once, that bar baselines sit at zero, and that annotations sit inside the data range and hold long enough. Fix fails by fixing the data, the plan, or the renderer. Never edit the manifest to make it pass.
7. **Watch three frames with your own eyes.** First, middle, last. Read every label at final size. Check that end labels do not collide when lines converge, that the axis note shows if the axis is broken, and that the final frame works as a still.
8. **Deliver the set.** The MP4, the manifest, the verifier output, the source CSV, and the final frame as a still image for viewers who cannot watch motion.

## Output Contract
- One MP4 per dataset: H.264, yuv420p, even dimensions, faststart, plus the frame manifest JSON that describes it.
- Every frame carries the title, labelled axes with units, direct series labels with current values, the current data time, and a source line.
- Axis limits computed once from the full dataset and constant across all frames, unless a staged rescale segment was planned and disclosed.
- A verifier report ending in PASS. Warnings (for example a flagged nonzero bar baseline with its lie factor) are reported to the user with the deliverable, never buried.
- Annotations only at data events that exist in the CSV, each held at least 1 second of frames.

## Operating Rules
1. Data accuracy comes before motion. Every number on every frame traces to the CSV through the declared interpolation. Unverifiable means cut.
2. Never rescale mid-animation to keep data in frame. Plan the axis from the full data. A chart that bursts its axis was planned wrong.
3. Bars start at zero. A broken bar axis needs the break drawn and labelled on the frame, and the verifier warning goes to the user with the video.
4. Interpolation is a claim. Linear is the default and is wrong for step data such as prices at events or discrete counts. For step data, hold each value until the next sample and say which mode was used.
5. Sample data in `assets/sample-data.csv` is invented test data, labelled as such in the file. It exists to test the pipeline. Never present it as real figures.
6. Color never carries a value alone. Every series gets a text label and a printed current value, and the palette avoids red-green pairs at similar lightness.
7. Test before shipping. Verified 2026-10-21 on ffmpeg 8.1.2 and Pillow in this environment: the sample CSV rendered 255 frames at 30 fps as both a line and a bar chart, the verifier passed both with a worst frame error of 0.0000 percent, a hand-tampered frame value failed the check with the frame named, and a bar chart forced to a baseline of 40 produced a lie factor warning of 21.00 at frame 0.
