Install
openclaw skills install @shurshanx/animate-old-photos-skillAnimate old photos into AI-generated videos using the Animate Old Photos API. Upload a photo, generate a 5-second animation video, and download the result. Use when the user wants to animate a photo, bring an old photo to life, turn old photos into videos, create a video from a still image, or convert a photo to video. Requires a paid API key from https://animateoldphotos.org
openclaw skills install @shurshanx/animate-old-photos-skillAnimate old photos into AI-generated videos via the Animate Old Photos API. The agent uploads a photo, submits an animation task, polls for completion, and downloads the resulting MP4 video.
This is a paid service. You need an API key and credits.
- Official Website: Animate Old Photos
- Get your API key: Profile > API Key
- Purchase credits: Buy Credits
Each animation costs 3 credits. View pricing plans
System requirements: curl and jq must be available in the shell.
AOP_API_KEY is not set.Exchange the API key for a short-lived access token and check the credit balance.
API_KEY="${AOP_API_KEY}"
AUTH=$(curl -s -X POST https://animateoldphotos.org/api/extension/auth \
-H "Content-Type: application/json" \
-d "{\"licenseKey\":\"${API_KEY}\"}")
TOKEN=$(echo "$AUTH" | jq -r '.accessToken')
CREDITS=$(echo "$AUTH" | jq -r '.creditBalance')
echo "Authenticated. Credits available: $CREDITS"
If accessToken is missing or error_code is 4010/4011, tell the user their API key is invalid and link to https://animateoldphotos.org/profile/interface-key.
If credits < 3, tell the user to purchase more at https://animateoldphotos.org/pricing and stop.
Get a presigned upload URL, then PUT the image binary to cloud storage.
IMAGE_PATH="photo.jpg"
FILE_SIZE=$(stat -f%z "$IMAGE_PATH" 2>/dev/null || stat -c%s "$IMAGE_PATH" 2>/dev/null)
CONTENT_TYPE="image/jpeg" # use image/png for .png files
UPLOAD=$(curl -s -X POST https://animateoldphotos.org/api/extension/upload-token \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d "{\"fileName\":\"$(basename "$IMAGE_PATH")\",\"contentType\":\"${CONTENT_TYPE}\",\"fileSize\":${FILE_SIZE}}")
UPLOAD_URL=$(echo "$UPLOAD" | jq -r '.uploadUrl')
KEY=$(echo "$UPLOAD" | jq -r '.key')
PUBLIC_URL=$(echo "$UPLOAD" | jq -r '.publicUrl')
curl -s -X PUT "$UPLOAD_URL" \
-H "Content-Type: ${CONTENT_TYPE}" \
--data-binary "@${IMAGE_PATH}"
echo "Image uploaded."
Confirm the upload and receive the encrypted payload needed for task submission.
FINALIZE=$(curl -s -X POST https://animateoldphotos.org/api/extension/upload-finalize \
-H "Authorization: Bearer $TOKEN" \
-F "key=${KEY}" \
-F "publicUrl=${PUBLIC_URL}")
IMAGE_URL=$(echo "$FINALIZE" | jq -r '.url')
SS_MESSAGE=$(echo "$FINALIZE" | jq -r '.message')
DNT=$(echo "$FINALIZE" | jq -r '.dnt')
echo "Upload finalized."
Submit the animation job. The Ss header must contain the message value from Step 3.
PROMPT="" # optional user prompt
TASK=$(curl -s -X POST https://animateoldphotos.org/api/extension/animate \
-H "Authorization: Bearer $TOKEN" \
-H "Ss: ${SS_MESSAGE}" \
-F "prompt=${PROMPT}" \
-F "input_image_url=${IMAGE_URL}" \
-F "dnt=${DNT}" \
-F "type=m2v_img2video" \
-F "duration=5" \
-F "public=false")
TASK_ID=$(echo "$TASK" | jq -r '.taskId')
TASK_DNT=$(echo "$TASK" | jq -r '.dnt')
TASK_DID=$(echo "$TASK" | jq -r '.did')
echo "Task submitted (ID: $TASK_ID). Polling for result..."
If the response contains error_code 999990 or 10009, the user has insufficient credits — link to https://animateoldphotos.org/pricing.
Poll every 30 seconds. Typical completion time is 2–5 minutes.
OUTPUT="output.mp4"
while true; do
sleep 30
STATUS=$(curl -s -G "https://animateoldphotos.org/api/extension/animate" \
--data-urlencode "taskId=${TASK_ID}" \
--data-urlencode "dnt=${TASK_DNT}" \
--data-urlencode "did=${TASK_DID}" \
--data-urlencode "type=m2v_img2video" \
-H "Authorization: Bearer $TOKEN")
ERR_MSG=$(echo "$STATUS" | jq -r '.message // empty')
if [ -n "$ERR_MSG" ]; then
echo "Task failed: $ERR_MSG"
break
fi
S=$(echo "$STATUS" | jq -r '.status')
RESOURCE=$(echo "$STATUS" | jq -r '.resource // empty')
if [ "$S" -ge 99 ] 2>/dev/null && [ -n "$RESOURCE" ]; then
curl -s -o "$OUTPUT" "$RESOURCE"
echo "Video saved to $OUTPUT"
break
fi
echo "Still processing (status: $S)..."
done
Report the saved video path to the user when done.
You can run the full pipeline with the bundled script:
bash scripts/animate.sh <API_KEY> <IMAGE_PATH> [PROMPT] [OUTPUT_PATH]
See scripts/animate.sh for details.
| error_code | Meaning | Action |
|---|---|---|
4010 | Invalid API key | Direct user to get a key |
4011 | API key expired | Direct user to renew key |
999998 | Access token invalid | Re-run Step 1 to get a new token |
999990 | Insufficient credits | Direct user to buy credits |
10009 | Insufficient credits | Direct user to buy credits |
For network errors, retry up to 3 times with exponential backoff (2s, 4s, 8s).
AOP_API_KEY not set), image path, and optional prompt.{output_path}."For the complete API reference, see animate-old-photos-api.md.