Bar‑chart races are a popular way to visualise how rankings shift over time. They combine a dynamic bar chart with a smooth animation that shows each bar growing or shrinking as its value changes, while the bars reorder themselves to reflect new leaders. For developers and content creators who want to automate this process, the Shotstack Edit API offers a straightforward path: read a CSV, calculate the necessary data, embed the animation in a single HTML5 asset, and let the API render the final MP4. This article walks through the entire workflow, from data preparation to API integration, and explains the key design choices that keep the solution lightweight and reproducible.
Context and practical value
The source demonstrates how to convert a wide CSV into a bar‑chart race MP4 using Python for data processing, GSAP for animation, and Shotstack’s Edit API for rendering. It includes a full script, validation steps, and performance checks.
This article distills the source into a concise, step‑by‑step guide, highlights key design decisions, and expands on how to adapt the workflow for different data shapes, output formats, and animation styles. It also adds practical troubleshooting tips and a community discussion prompt to encourage knowledge sharing.
Key takeaways
- Use a wide CSV format – one row per period, one column per bar – to simplify parsing.
- Compute rankings and relative widths in Python, then inject the results as a JSON literal into the HTML5 asset.
- Render the whole animation as a single HTML5 clip to stay well below Shotstack’s request size limits.
- Validate CSV rows for correct column count, numeric values, and non‑negative numbers to avoid runtime errors.
- Poll the Edit API until the render completes, then download the MP4 from the returned URL.
Preparing the Data
The script expects a CSV where the first column lists the period labels (e.g., months) and each subsequent column represents a bar. Every row must contain a numeric value for every bar. The example uses monthly sales for six stores, but any time‑series data will work. The CSV is read with Python’s built‑in csv module, which guarantees that the file is parsed correctly without external dependencies.
Calculating Ranks and Widths
For each period, the script sorts the bars by value to determine their rank. Ties are broken alphabetically. The width of each bar is calculated as the bar’s value divided by the period’s leader, multiplied by a constant maximum width (1,200 px). This relative scaling keeps the animation visually balanced even when values vary widely.
Building the HTML5 Asset
The animation is defined in a single HTML5 clip that contains the page’s HTML, CSS, and JavaScript. The JavaScript uses GSAP to animate the bars’ positions, widths, and labels. By embedding the pre‑computed data as a JSON literal, the clip remains self‑contained and avoids network requests during rendering. The clip’s length is derived from timing constants: a lead time, a per‑period step, and a final hold period.
Submitting the Render Request
The Edit API accepts a JSON payload that describes the timeline and output settings. The payload is under 5 KB for the example, well below the 390 KB limit. After submitting the request, the script polls the API every five seconds until the status changes to "done" or "failed". On success, the API returns a URL pointing to the finished MP4.
Validating the Render
The guide includes a dry‑run mode that prints the final period’s rankings without rendering. Additionally, the article describes how to extract frames from the rendered video and measure bar positions and widths to confirm that the animation matches the planned data.
Extending the Workflow
The same script can be adapted for different data sets, output resolutions, or animation styles. For example, you can change the output size to 1080 × 1920 for vertical videos, adjust the row height to accommodate more bars, or replace the relative width calculation with a fixed scale based on the global maximum value.
Practical next steps
- 1. Create a wide CSV with one row per period and one column per bar, ensuring all values are numeric and non‑negative.
- 2. Run the provided Python script (bar_chart_race.py) after setting SHOTSTACK_API_KEY to your API key; the script will output the render ID and URL once finished.
- 3. Use the "--dry-run" flag to verify the final rankings before committing to a render, saving API calls and time.
Limits and verification
- The script assumes the CSV is wide and ordered; it does not sort dates or handle missing periods automatically. If your data is long‑format, you must pivot it first.
FAQ
Can I limit the chart to the top five bars?
Not with the current script. To show only the top N, you would need to add a GSAP tween that fades out rows whose rank is N or higher during each period.
How do I use a fixed scale instead of the leader’s value?
Modify the race() function to divide each bar’s value by the global maximum across the entire file, rather than the period’s leader. This keeps the bar widths consistent over time.
Is it possible to create a vertical version for Shorts or Reels?
Yes. Change the output dimensions to 1080 × 1920, adjust BAR_MAX and the row positions in the CSS, and the script will render a vertical bar‑chart race.