From a photo to a talking clip
Two calls. Make the picture you want, then make it speak.
A common job: take one photo, put the person in a new place, and have them say something. Doing it in two steps gives you a look at the frame before you pay for the clip.
The commands use jq to pick fields out of the answers. RUN makes this run's idempotency keys its own, so you can run the guide more than once:
RUN=$(date +%s)1. Upload the photo
PHOTO_ID=$(curl -s https://api.nocamclub.com/v1/uploads \
-H "Authorization: Bearer $NOCAM_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://docs.nocamclub.com/examples/mascot.jpg" }' | jq -r .id)Use your own photo's address instead. The id works for 48 hours.
2. Make the frame
Vertical, since that's what the clip will be. Say what to keep.
FRAME_URL=$(curl -s https://api.nocamclub.com/v1/generations \
-H "Authorization: Bearer $NOCAM_API_KEY" \
-H "Content-Type: application/json" \
-H "Prefer: wait=60" \
-H "Idempotency-Key: rooftop-frame-$RUN" \
-d '{
"model": "nano-banana-2",
"input": {
"prompt": "Keep the face and hair of img1. The same person on a city rooftop at sunset, facing the camera, waist up. Phone photo.",
"images": ["'"$PHOTO_ID"'"],
"resolution": "2K",
"aspect_ratio": "9:16"
}
}' | jq -r '.outputs[0].url')Look at the result. If it isn't right, change the prompt and make another: a photo costs little and a clip costs more.
3. Make it speak
A result is a public link, so it goes straight to the next model.
Muse always makes 10 seconds with sound, and its shape follows the photo. About 2 words a second fits the length.
CLIP_ID=$(curl -s https://api.nocamclub.com/v1/generations \
-H "Authorization: Bearer $NOCAM_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: rooftop-clip-$RUN" \
-d '{
"model": "muse-video",
"input": {
"prompt": "img1 looks straight into the camera, smiles and says clearly: \"I made this whole video from one selfie.\" The camera does not move.",
"images": ["'"$FRAME_URL"'"]
}
}' | jq -r .id)Then poll GET /v1/generations/$CLIP_ID until status is succeeded or failed, usually a minute or two.
Why two steps
- You check the expensive part's input. A bad frame costs a few credits. A bad clip costs more, and takes longer to find out.
- You choose per step. Use the model that's best at photos, then the one that's best at clips.
- Failures stay small. If the clip fails, the credits come back and the frame is still there.
Keep it working in production
- Send a new
Idempotency-Keyper clip, and reuse it for retries of that clip. - Read
error.code: oncontent_refused, tell the person. Onprovider_unavailable, try again in a few minutes. - Download the result: links stop after 7 days.