Turn release notes into a short announcement video, automatically.
Every time you publish a GitHub release, shipreel reads the notes (or your CHANGELOG.md), renders a branded 15β30 second MP4 and attaches it to the release. It's ready to post on X, LinkedIn, Instagram and YouTube Shorts.
shipreel is free and open source. If it helps your releases, a coffee keeps it going. β
Install Β· Quick start Β· CLI Β· Config Β· Templates Β· Custom templates Β· FAQ Β· Support
Rendered from this changelog with the minimal template (GIF preview; the real output is a crisp MP4).
Every shipreel release ships its own announcement video, made with shipreel. See the latest release assets.
Most release announcements are a link to a changelog nobody clicks. Video gets more engagement on every social platform, but nobody has time to edit one for each patch release. shipreel does it for you in CI, with zero effort after setup:
- No server, no database, no account. It runs inside GitHub Actions or on your machine.
- Reads what you already write: GitHub release bodies, Keep a Changelog, conventional-changelog / release-please / semantic-release, changesets, or any markdown file.
- Picks the good stuff: features first, max 5 highlights. It strips PR links, commit hashes and
@mentions, and shortens long lines. - Every format at once: landscape 1920Γ1080, square 1080Γ1080 and vertical 1080Γ1920 (Shorts / Reels / TikTok).
- On brand: 3 built-in templates, your color, logo, Google Font, call to action and optional background music.
- Deterministic rendering: HTML/CSS scenes are rendered frame by frame in headless Chromium and encoded with ffmpeg. The same input always gives the same video.
There are three ways to use shipreel. All of them are free.
| Way | Best for | Install |
|---|---|---|
| GitHub Action | Automatic video on every release | Nothing to install. Add one workflow file (setup) |
| npx (no install) | Trying it, one-off videos | npx shipreel --changelog CHANGELOG.md |
| Project dependency | Teams and npm scripts | npm i -D shipreel (or pnpm add -D shipreel, yarn add -D shipreel) |
| Global CLI | Using it across many repos | npm i -g shipreel, then run shipreel anywhere |
- Node.js 20 or newer. Check with
node -v, and get it from nodejs.org. - Chromium for rendering. Download it once:
If Chromium isn't there, shipreel falls back to an installed Google Chrome or Microsoft Edge.
npx playwright install chromium # Linux servers / CI also need system libraries: npx playwright install --with-deps chromium - ffmpeg is bundled (
ffmpeg-static). Nothing to install. To use your own build, setSHIPREEL_FFMPEG=/path/to/ffmpeg.
Works on Windows, macOS and Linux.
cd your-project # a folder with a CHANGELOG.md
npx playwright install chromium # one time only
npx shipreel --dry-run # see which highlights will be used
npx shipreel # render landscape, square and vertical MP4s into ./videosAs a project script (npm i -D shipreel):
{
"scripts": {
"video": "shipreel --changelog CHANGELOG.md --out videos",
"video:preview": "shipreel preview"
}
}Then npm run video.
1. Add .github/workflows/release-video.yml:
name: Release video
on:
release:
types: [published]
permissions:
contents: write # to attach the videos to the release
jobs:
video:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- uses: 99proteam/shipreel@v1
with:
template: minimal # minimal | terminal | bold2. (Optional) add a shipreel.config.json with your brand color and logo (reference).
3. Publish a release. A minute or two later the videos show up as assets on the release:
my-project-v2.4.0-landscape.mp4
my-project-v2.4.0-square.mp4
my-project-v2.4.0-vertical.mp4
| Input | Default | Description |
|---|---|---|
template |
from config, else minimal |
minimal, terminal, bold or a path to a custom template folder |
sizes |
from config, else all three | Comma-separated: landscape,square,vertical or WIDTHxHEIGHT |
config |
shipreel.config.json |
Path to a config file |
upload |
true |
Attach videos to the release |
github-token |
${{ github.token }} |
Needs contents: write to upload |
tag |
Release tag to render when not triggered by a release event (e.g. workflow_dispatch) |
|
changelog |
Read notes from this CHANGELOG.md instead of the release body |
|
output-dir |
shipreel-videos |
Where videos are written |
| Output | Description |
|---|---|
videos |
Newline-separated video paths |
videos-json |
JSON array of video paths |
video |
First video path |
asset-urls |
Download URLs of the uploaded release assets |
The job summary also lists the selected highlights and links to every video. A ready-to-copy workflow with workflow_dispatch and artifact upload lives in examples/release-video.yml.
Requires Node.js 20+. The first run needs a Chromium build (npx playwright install chromium). shipreel also falls back to an installed Chrome or Edge.
# From a changelog (latest released version, or pick one)
npx shipreel --changelog CHANGELOG.md --version 2.4.0 -o ./videos
# From a GitHub release (token from GITHUB_TOKEN for private repos / rate limits)
npx shipreel --release v2.4.0 --repo owner/name
# From any markdown release notes
npx shipreel --notes NOTES.md --version 2.4.0
# Preview scenes in the browser before rendering (scrub, play, switch sizes)
npx shipreel preview --changelog CHANGELOG.md
# See which highlights would be used, without rendering
npx shipreel --changelog CHANGELOG.md --dry-run| Option | Description |
|---|---|
-c, --changelog <file> |
CHANGELOG.md to read (default ./CHANGELOG.md) |
--notes <file> |
Plain markdown release notes |
--version <version> |
Version to pick from the changelog (default: latest released) |
--release <tag> / --repo <owner/name> |
Fetch the notes of a GitHub release (latest works) |
--config <file> |
Config file path |
-t, --template <name|path> |
Template |
-s, --sizes <list> |
landscape,square,vertical or WIDTHxHEIGHT |
--name, --brand-color, --cta, --fps, --max-items |
Override config values |
-o, --out <dir> |
Output directory (default ./videos) |
--dry-run |
Print highlights and timing as JSON |
--json |
Print rendered files as JSON |
preview -p, --port <port> |
Preview server port (default 4848), --no-open to skip opening the browser |
Put a shipreel.config.json in your repo root, or a "shipreel" key in package.json. CLI flags and Action inputs override it. Paths are relative to the config file.
{
"template": "minimal",
"brandColor": "#6d28d9",
"logo": "./assets/logo.svg",
"font": "Inter",
"sizes": ["landscape", "square", "vertical"],
"cta": "npm i my-project@latest",
"maxItems": 5,
"music": "./assets/music.mp3"
}| Key | Type | Default | Description |
|---|---|---|---|
name |
string | package.json name, else repo name |
Project name shown in the video |
template |
string | minimal |
minimal, terminal, bold or a path to a custom template folder |
brandColor |
hex | template default | Accent color, e.g. #6d28d9 |
logo |
path | monogram | SVG, PNG, JPG, WebP or GIF |
font |
string | template default | Any Google Font name, or system-ui for no web font |
sizes |
string[] | all three | landscape (1920Γ1080), square (1080Γ1080), vertical (1080Γ1920) or WIDTHxHEIGHT |
cta |
string | npm i <name>@latest or homepage |
Outro call to action (commands get a $ prompt) |
ctaSecondary |
string | Star us on GitHub |
Second outro line |
url |
string | package.json homepage |
Website shown when there is no repo |
repo |
string | from package.json / GITHUB_REPOSITORY |
owner/name |
maxItems |
number | 5 |
Maximum highlight scenes (1β10) |
maxChars |
number | 72 |
Highlights longer than this are shortened |
music |
path | none | Background music (your own file). Looped, faded and trimmed to the video |
fps |
number | 30 |
Frames per second |
minDuration / maxDuration |
seconds | 15 / 30 |
Video length bounds |
outDir |
path | videos |
CLI output directory |
changelog |
path | CHANGELOG.md |
Default changelog for the CLI |
| Scene | Length | Content |
|---|---|---|
| Intro | 2s | Logo, project name, "v2.4.0 is out" |
| Highlights | 2.5s each | One feature per scene: big text, icon, progress |
| Fixes | 2s | "+ 12 bug fixes" (only when there are fixes) |
| Outro | 3s | Call to action + "Star us on GitHub" |
Short releases are stretched to minDuration. Long ones are squeezed to maxDuration, and highlights are dropped only as a last resort.
minimal |
terminal |
bold |
|---|---|---|
![]() |
![]() |
![]() |
| Clean light design with one brand accent | Dark code style with typed commands and a blinking cursor | Big type, brand color blocks, hard wipes |
A template is a folder with one HTML file per scene and a stylesheet:
my-template/
βββ template.json # name, default font and color (optional)
βββ intro.html
βββ highlight.html
βββ fixes.html
βββ outro.html
βββ styles.css # plus any images/fonts it references
Scenes are HTML fragments with {{variables}}, animated with plain CSS animations. shipreel pauses and seeks every animation per frame, so your animations render the same every time:
<!-- highlight.html -->
<p class="label">{{kindLabel}} Β· {{index}}/{{total}}</p>
<h2 class="text size-{{textSize}}" data-split="words">{{text}}</h2>.text .sr-word { animation: rise .5s both; animation-delay: calc(.2s + var(--i) * 50ms); }
@keyframes rise { from { opacity: 0; transform: translateY(3vmin); } }Use it with "template": "./my-template" and iterate with npx shipreel preview (press Reload after editing). The full variable list, helpers and rules are in docs/templates.md. There is a complete example in examples/custom-template.
import { loadConfig, findRelease, buildPlan, renderVideos } from 'shipreel';
import { readFileSync } from 'node:fs';
const config = loadConfig({ overrides: { template: 'bold', sizes: 'vertical' } });
const release = findRelease(readFileSync('CHANGELOG.md', 'utf8'), '2.4.0')!;
const videos = await renderVideos(buildPlan(release, config));
console.log(videos.map((v) => v.file));Also exported: parseChangelog, parseReleaseNotes, cleanItem, selectHighlights, buildTimeline, fetchRelease, uploadReleaseAsset, renderSceneDocument and more (fully typed).
- Parse the notes into releases and items (features, fixes, performance, breaking, other).
- Select up to 5 highlights (features first) and clean them up. Fixes become a count.
- Plan scene timing in whole frames (15β30s total).
- Render: each scene is an HTML page served locally to headless Chromium (Playwright). For every frame,
document.getAnimations()are paused and theircurrentTimeis set, then a screenshot is taken. - Encode: frames are piped into ffmpeg (
ffmpeg-static), producing H.264 / yuv420p / faststart MP4s that every social platform accepts.
"Could not launch Chromium"
Run npx playwright install chromium (on Linux CI: npx playwright install --with-deps chromium). Or install Google Chrome. shipreel uses it automatically. You can also point to any Chromium build with SHIPREEL_CHROMIUM=/path/to/chrome.
The Action fails with 403 when uploading
Give the workflow write access to releases:
permissions:
contents: writeWhich highlights will be picked?
Run npx shipreel --dry-run, or paste your notes into the live demo. Features come first, then performance, breaking changes and other changes, up to maxItems (5). Fixes are shown as a count. Docs, chores, CI and dependency bumps are ignored.
My changelog format isn't detected
shipreel understands version headings like ## [1.2.0] - 2024-01-01, ## 1.2.0 (2024-01-01), # [1.2.0](link) (date), ## v1.2.0 and ## pkg@1.2.0, plus sections such as Added / Features / Fixed / Bug Fixes / Performance / Breaking Changes. If yours isn't detected, use --notes file.md --version 1.2.0, and please open an issue with a sample.
Can I render a past release?
Yes. Use npx shipreel --release v1.2.0 --repo owner/name, or run the Action with workflow_dispatch and the tag input (see examples/release-video.yml).
How long does rendering take?
About 30β40 seconds per 1080p size on a GitHub-hosted runner. Rendering only the sizes you need (sizes: vertical) is faster.
Does it cost anything?
No. shipreel is MIT-licensed, runs on free GitHub Actions minutes for public repos, and doesn't call any paid API.
shipreel is free and MIT-licensed, built and maintained in spare time. If it saves you time on every release, please consider supporting it:
| Tier | Amount | You get |
|---|---|---|
| β Coffee | $5 one-time | Our thanks, and a faster release cycle |
| π Supporter | $10 / month | Your name in the Supporters list below |
| π Sponsor | $50 / month | Your logo in this README, plus priority on issues |
| π Partner | $200 / month | Large logo, a custom template for your brand, direct support |
Other ways to help: β star the repo, share a video you made with shipreel, or contribute a template.
Be the first! buymeacoffee.com/99proteam
Bug reports, parsers for more changelog styles and new templates are very welcome. See CONTRIBUTING.md and the roadmap.
MIT Β© 99proteam


