Skip to content

Commit 9b4e19f

Browse files
authored
Add ai-content-pipeline example for on-brand product videos
1 parent ac1acd2 commit 9b4e19f

8 files changed

Lines changed: 1252 additions & 0 deletions

File tree

‎README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Clone this repository, or open the directory of the example you want. Each examp
77
## Examples
88

99
- [agency-client-social-videos](examples/agency-client-social-videos) renders one short vertical video per agency client from that client's own photos and video clips, ending on a card in the client's brand color. The Edit JSON is built in code, one clip per media item.
10+
- [ai-content-pipeline](examples/ai-content-pipeline) makes an on-brand 9:16 video for each product in a CSV, from a brand guide in JSON. Claude writes each script, AI models generate the still and the clip, and checks on the words and the pictures hold anything off-brand for review. Companion code for [AI content pipeline automation with video creation for brands](https://shotstack.io/learn/ai-content-pipeline-automation-brands/).
1011
- [automotive-inventory-videos](examples/automotive-inventory-videos) renders one vertical video per vehicle in a dealer inventory from a JSON feed: the photos in sequence with a pan or zoom on each, and an animated specification card. The Edit JSON is built in code, one clip per photo.
1112
- [bulk-csv-videos](examples/bulk-csv-videos) renders one video per row of a CSV from a single template with merge fields, tracked in a resumable manifest, with an optional AI step where Claude writes each row's headline and image prompt. Companion code for [Generate videos in bulk with an API and an AI agent](https://shotstack.io/learn/bulk-create-videos-from-csv-and-ai/).
1213
- [elevenlabs-voiceover-video](examples/elevenlabs-voiceover-video) narrates a video in an ElevenLabs voice, cloned from your own sample if you want, uploads the audio through the Ingest API and renders a captioned video.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# https://dashboard.shotstack.io/register
2+
# A production key. AI generation always uses production credits.
3+
SHOTSTACK_API_KEY=
4+
5+
# https://platform.claude.com/
6+
ANTHROPIC_API_KEY=
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules/
2+
.env
3+
out/
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# AI content pipeline
2+
3+
Make an on-brand 9:16 video for each product in a store's product export. A brand guide in `brand.json` sets the colors, font, layout limits, voice rules, backdrops, motion and music. You get one MP4 file for each product in `out/`. A sheet in `out/approval.csv` lists each video, or the reason why the pipeline held it.
4+
5+
Related guide: [AI content pipeline automation with video creation for brands](https://shotstack.io/learn/ai-content-pipeline-automation-brands/).
6+
7+
## Requirements
8+
9+
- A [Shotstack account](https://dashboard.shotstack.io/register) and your **production** API key
10+
- An [Anthropic API key](https://platform.claude.com/). To use another model that can read images, change `askClaude()`.
11+
- Node.js 22.9 or later. Node 20 is end of life.
12+
- ffmpeg on your PATH. The pipeline uses it to take frames from each clip. It was tested with ffmpeg 8.1.
13+
14+
AI generation always uses production credits, also with a sandbox key. The pipeline uses the production API. For each product, a run can make at most 2 images and 2 video clips. Each render also generates a voice-over. A run makes one music track for all products. It makes one render for each product. See [pricing](https://shotstack.io/pricing/). A request that is the same as an earlier request returns the stored file at no charge.
15+
16+
## Setup
17+
18+
```bash
19+
git clone https://github.com/shotstack/shotstack-cookbook.git
20+
cd shotstack-cookbook/examples/ai-content-pipeline
21+
cp .env.example .env
22+
```
23+
24+
Set `SHOTSTACK_API_KEY` and `ANTHROPIC_API_KEY` in `.env`. The `npm start` command loads this file with `node --env-file-if-exists=.env`.
25+
26+
## Run
27+
28+
Write the template to `out/template.json`. This does not need keys, and it is free:
29+
30+
```bash
31+
npm run dry
32+
```
33+
34+
Show what a run does, then stop. This does not use credits:
35+
36+
```bash
37+
npm start
38+
```
39+
40+
Make a video for each product. This uses credits:
41+
42+
```bash
43+
npm start -- --yes
44+
```
45+
46+
To use another product export, add its path: `npm start -- my-products.csv --yes`. The file needs the same columns as `products.csv`.
47+
48+
## What happens
49+
50+
For each product, the pipeline does these steps:
51+
52+
1. It checks the title, price and detail against the layout limits. They go on screen as they are in the data.
53+
2. Claude writes a short voice-over script. Code checks the script against the voice rules. A script that fails goes back with the reasons. A script gets 3 tries.
54+
3. An image-edit model puts the real product on a brand backdrop. A vision check compares the result with the packshot. A still gets 2 tries.
55+
4. An image-to-video model animates the still. A vision check compares frames from the clip with the packshot. A clip gets 2 tries.
56+
5. Shotstack renders the video from a saved template, with the voice-over, captions and music.
57+
58+
A product that fails a check is held, with the reason, in `out/approval.csv`. The checks are a first filter. A person still approves each video before it is posted. Each render has a permanent public link in the sheet.
59+
60+
Run the pipeline again to continue. It skips each product that has an `out/<handle>.mp4` file. If a video was rendered but not downloaded, it downloads the video from the link in the sheet. It renders the product again only if that link fails. A held row in the sheet is replaced on the next run. A row with a video keeps your review. Keep the six columns of the sheet. You can add columns. Do not edit the sheet while the pipeline runs. To make a product again, delete its video file and its rows in the sheet. The first run saves the template and keeps its id in `out/template.id`. Later runs update that template.
61+
62+
To use another store, change `brand.json`, not the code. A product type with no motion line, or a badge with no label, is held with a message that says what to add. A missing key in `brand.json` stops the run with the name of the key.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
{
2+
"name": "Field & Fold",
3+
"colors": {
4+
"panel": "#9b3b2c",
5+
"text": "#eef1f2",
6+
"mark": "#ecccc6"
7+
},
8+
"font": {
9+
"family": "Inter",
10+
"src": "https://fonts.gstatic.com/s/inter/v20/UcCo3FwrK3iLTfvlaQc78lA2.ttf"
11+
},
12+
"layout": {
13+
"titleMax": 13,
14+
"detailMax": 17
15+
},
16+
"labels": {
17+
"new": "New in",
18+
"bestseller": "Bestseller",
19+
"restock": "Back in stock",
20+
"small-batch": "Small batch",
21+
"gift": "Gift idea"
22+
},
23+
"voice": {
24+
"tone": "Warm, confident and short, like a good shop window. Two beats: a hook that names the product (back, new, meet the...), then one line about how it feels or fits into someone's day. Sell the moment, not the spec sheet.",
25+
"maxWords": 12,
26+
"avoid": [
27+
"best",
28+
"ultimate",
29+
"amazing",
30+
"perfect",
31+
"game-changer",
32+
"revolutionary",
33+
"unleash",
34+
"elevate",
35+
"must-have",
36+
"iconic",
37+
"luxe",
38+
"stunning"
39+
],
40+
"claimsNeedData": [
41+
"organic",
42+
"recycled",
43+
"sustainable",
44+
"ethical",
45+
"handmade",
46+
"handcrafted",
47+
"by hand",
48+
"waterproof",
49+
"lifetime",
50+
"eco-friendly",
51+
"vegan"
52+
],
53+
"avoidPatterns": [
54+
"listing more than two features",
55+
"describing how a part works (drains, adjusts, attaches)",
56+
"repeating the hook idea in other words"
57+
],
58+
"hooks": {
59+
"new": "open with Meet the... or New in:",
60+
"bestseller": "open with Our bestselling...",
61+
"restock": "open with Our ... is back.",
62+
"small-batch": "open with Made in small batches:",
63+
"gift": "open as a gift idea"
64+
},
65+
"examples": [
66+
"Our linen shirt is back. Light and made to be lived in.",
67+
"The stoneware mug. Just the right weight for the first coffee.",
68+
"Meet the brass desk lamp. Warm light for late ideas.",
69+
"Canvas sneakers, made for long days and longer walks."
70+
]
71+
},
72+
"voiceover": {
73+
"model": "elevenlabs-multilingual-v2",
74+
"voice": "Sarah"
75+
},
76+
"visual": {
77+
"backdrops": [
78+
"brick-red",
79+
"chalk-white",
80+
"deep navy",
81+
"mustard-yellow",
82+
"blush-pink",
83+
"deep forest-green"
84+
],
85+
"shot": "Studio product photo, vertical framing. The exact product from the reference image, alone, on a {backdrop} seamless paper backdrop, {light}. Keep the product's color, shape, material and details exactly as in the reference.",
86+
"scenes": {
87+
"Textiles": "Photo, vertical framing. The exact product from the reference image hanging from a wooden peg on a {backdrop} painted kitchen wall, front facing the camera, its ties hanging loose. Below it, the edge of a pale wooden worktop lightly dusted with flour, with a small heap of flour and a wooden rolling pin. {light}. Keep the product's color, shape, material and details exactly as in the reference."
88+
},
89+
"light": "soft natural side light, a gentle shadow",
90+
"rules": [
91+
"Product only: no people, faces, hands or body parts.",
92+
"No text, logos, labels or packaging.",
93+
"No window, no props except the ones the shot describes, and nothing that could be mistaken for a second product."
94+
],
95+
"motion": {
96+
"Apparel": "A soft breeze lifts the hem and sleeves, which sway and slowly settle.",
97+
"Textiles": "The apron has just been hung on the peg: it swings gently and settles, its long ties swaying. A soft puff of flour rises from the worktop and drifts slowly through the light, then settles.",
98+
"Ceramics": "A small green seedling pushes up out of the planter and grows into a lush leafy plant, new leaves unfurling one after another. The planter and its saucer never move.",
99+
"Lighting": "The lamp sways gently on its cord, then switches on; warm light glows through the shade and throws patterned shadows across the backdrop.",
100+
"Glassware": "The water inside ripples gently and light shimmers through the glass onto the backdrop."
101+
},
102+
"camera": "The camera stays still or slowly pushes in, and the motion is clearly visible. The product never turns or rotates, so no unseen side is shown, and its shape, color and details never change. No people or hands appear."
103+
},
104+
"music": {
105+
"model": "elevenlabs-music",
106+
"prompt": "Warm, calm acoustic background track, soft guitar and light percussion, 90 BPM, unhurried, instrumental only",
107+
"options": {
108+
"forceInstrumental": true
109+
}
110+
}
111+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "ai-content-pipeline",
3+
"version": "1.0.0",
4+
"private": true,
5+
"description": "Make on-brand 9:16 product videos from a brand guide and a product CSV, with AI generation and automatic checks",
6+
"type": "module",
7+
"scripts": {
8+
"dry": "node pipeline.js --dry",
9+
"start": "node --env-file-if-exists=.env pipeline.js",
10+
"format": "npx prettier@3 --write ."
11+
},
12+
"engines": {
13+
"node": ">=22.9"
14+
}
15+
}

0 commit comments

Comments
 (0)