An old photo comes alive
Restore and colourise an old photo, then animate it.
What moves
The restored 1975 group photograph comes to life for a moment: the brigade members shift their weight, a few glance at each other and break into shy smiles, one adjusts his cap, the red flag stirs in a light wind, dust blows across the threshing ground. The camera holds still at eye level, as if the photographer had kept filming. Natural, subtle motion.
+ Old photo
Elapsed–
Cost$0.635
Recorded run, replayed faster than it ran.
$0.635this recorded run's cost
- 720p, 6 sdefault≈ $0.635
- 1080p, 6 s≈ $1.235
Forking copies the 2 steps into your dashboard. You change the input, press Run, and each call is billed to your balance.
Build it yourself
Each step is one request to the Hyperouter API with your key. A later step reads an earlier one's output through {{steps.<id>…}}, and your inputs through {{vars.<name>}}. Models: bytedance/seedream-5.0-lite, alibaba/wan3.0.
The 2 requests
Restore and colourise
POST /v1/images/editsbytedance/seedream-5.0-lite1 image · 2400×1800{ "model": "bytedance/seedream-5.0-lite", "prompt": "Restore and colourise this photograph: remove the scratches, dust and the crease, recover the faces, and give it natural, period-true colour, {{vars.tint}}. Keep every person, their pose, the composition and the handwritten date exactly as they are, as a carefully restored 1970s colour photograph. Documentary realism shot on 65mm large-format film: natural and practical light only, deep blacks with detail held in the shadows, fine organic film grain, true skin texture with pores and wrinkles, no retouching, no digital sharpening, no beauty filter.", "size": "2400x1800", "n": 1, "images": [ { "image_url": "{{vars.photo_url}}" } ] }Bring it to life
POST /v1/videosalibaba/wan3.0720p · 6 s · 4:3 · silent{ "model": "alibaba/wan3.0", "prompt": "{{vars.motion}}", "first_frame": "{{steps.restore.url[0]}}", "seconds": 6, "resolution": "720p", "ratio": "4:3" }
Run the whole pipeline from code
API=https://api.hyperouter.app/v1
call() { curl -s "$API/$1" -H "Authorization: Bearer $HYPEROUTER_API_KEY" -H 'Content-Type: application/json' "${@:2}"; }
PHOTO='https://example.com/your-photo.jpg' # an https URL of your photo
LOOK='Documentary realism shot on 65mm large-format film: natural and practical light only, deep blacks with detail held in the shadows, fine organic film grain, true skin texture with pores and wrinkles, no retouching, no digital sharpening, no beauty filter.'
TINT='faded army-green and blue cotton jackets, a red flag, yellow earth and a red-brick granary, warm afternoon sun'
MOTION='The restored 1975 group photograph comes to life for a moment: the brigade members shift their weight, a few glance at each other and break into shy smiles, one adjusts his cap, the red flag stirs in a light wind, dust blows across the threshing ground. The camera holds still at eye level, as if the photographer had kept filming. Natural, subtle motion.'
# 1. restore and colourise
RESTORED=$(jq -n --arg p "Restore and colourise this photograph: remove the scratches, dust and the crease, recover the faces, and give it natural, period-true colour, $TINT. Keep every person, their pose, the composition and the handwritten date exactly as they are, as a carefully restored 1970s colour photograph. $LOOK" --arg u "$PHOTO" '{model:"bytedance/seedream-5.0-lite", prompt:$p, size:"2400x1800", n:1, images:[{image_url:$u}]}' | call images/edits -d @- | jq -r '.data[0].url')
# 2. six seconds from the restored photo: create, then poll
ID=$(jq -n --arg p "$MOTION" --arg f "$RESTORED" '{model:"alibaba/wan3.0", prompt:$p, first_frame:$f, seconds:6, resolution:"720p", ratio:"4:3"}' | call videos -d @- | jq -r .id)
while s=$(call videos/$ID | jq -r .status); [ "$s" = queued ] || [ "$s" = in_progress ]; do sleep 5; done
echo "$s"
call videos/$ID/content -L -o film.mp4
// run.mjs import OpenAI from 'openai'; const c = new OpenAI({ baseURL: 'https://api.hyperouter.app/v1', apiKey: process.env.HYPEROUTER_API_KEY }); const PHOTO = 'https://example.com/your-photo.jpg'; // an https URL of your photo const LOOK = 'Documentary realism shot on 65mm large-format film: natural and practical light only, deep blacks with detail held in the shadows, fine organic film grain, true skin texture with pores and wrinkles, no retouching, no digital sharpening, no beauty filter.'; const TINT = 'faded army-green and blue cotton jackets, a red flag, yellow earth and a red-brick granary, warm afternoon sun'; const MOTION = 'The restored 1975 group photograph comes to life for a moment: the brigade members shift their weight, a few glance at each other and break into shy smiles, one adjusts his cap, the red flag stirs in a light wind, dust blows across the threshing ground. The camera holds still at eye level, as if the photographer had kept filming. Natural, subtle motion.'; // 1. restore and colourise const restored = (await c.post('/images/edits', { body: { model: 'bytedance/seedream-5.0-lite', prompt: `Restore and colourise this photograph: remove the scratches, dust and the crease, recover the faces, and give it natural, period-true colour, ${TINT}. Keep every person, their pose, the composition and the handwritten date exactly as they are, as a carefully restored 1970s colour photograph. ${LOOK}`, size: '2400x1800', n: 1, images: [{ image_url: PHOTO }] } })).data[0].url; // 2. six seconds from the restored photo: create, then poll let v = await c.post('/videos', { body: { model: 'alibaba/wan3.0', prompt: MOTION, first_frame: restored, seconds: 6, resolution: '720p', ratio: '4:3' } }); while (['queued', 'in_progress'].includes(v.status)) { await new Promise((ok) => setTimeout(ok, 5000)); v = await c.get('/videos/' + v.id); } if (v.status !== 'completed') throw new Error(JSON.stringify(v.error)); console.log((await c.get('/generations/' + v.id)).data.outputs[0].url);
import os, time from openai import OpenAI c = OpenAI(base_url='https://api.hyperouter.app/v1', api_key=os.environ['HYPEROUTER_API_KEY']) PHOTO = 'https://example.com/your-photo.jpg' # an https URL of your photo LOOK = 'Documentary realism shot on 65mm large-format film: natural and practical light only, deep blacks with detail held in the shadows, fine organic film grain, true skin texture with pores and wrinkles, no retouching, no digital sharpening, no beauty filter.' TINT = 'faded army-green and blue cotton jackets, a red flag, yellow earth and a red-brick granary, warm afternoon sun' MOTION = 'The restored 1975 group photograph comes to life for a moment: the brigade members shift their weight, a few glance at each other and break into shy smiles, one adjusts his cap, the red flag stirs in a light wind, dust blows across the threshing ground. The camera holds still at eye level, as if the photographer had kept filming. Natural, subtle motion.' # 1. restore and colourise restored = c.post('/images/edits', cast_to=object, body={ 'model': 'bytedance/seedream-5.0-lite', 'prompt': f'Restore and colourise this photograph: remove the scratches, dust and the crease, recover the faces, and give it natural, period-true colour, {TINT}. Keep every person, their pose, the composition and the handwritten date exactly as they are, as a carefully restored 1970s colour photograph. {LOOK}', 'size': '2400x1800', 'n': 1, 'images': [{'image_url': PHOTO}]})['data'][0]['url'] # 2. six seconds from the restored photo: create, then poll v = c.post('/videos', cast_to=object, body={ 'model': 'alibaba/wan3.0', 'prompt': MOTION, 'first_frame': restored, 'seconds': 6, 'resolution': '720p', 'ratio': '4:3'}) while v['status'] in ('queued', 'in_progress'): time.sleep(5) v = c.get('/videos/' + v['id'], cast_to=object) assert v['status'] == 'completed', v['error'] print(c.get('/generations/' + v['id'], cast_to=object)['data']['outputs'][0]['url'])
Run An old photo comes alive on your account
Restore and colourise an old photo, then animate it. Fork it, change the input, and run it from the dashboard: ≈ $0.635 per run at the default settings.