Extract GIF or WebP animated images from videos to create previews, social media content, or thumbnails.
Use cases
-
E-commerce: Show product features without full videos.
-
Marketing: Extract highlights from promotional videos.
-
News: Showcase key moments from events.
Supported formats
|
Format |
File Size |
Browser Support |
When to Use |
|
GIF |
Larger |
Universal |
Maximum compatibility |
|
WebP |
30-70% smaller |
Modern browsers (not IE, iOS Safari <14) |
Mobile apps, bandwidth-sensitive sites |
WebP is not supported in IE, iOS Safari 3.2-13.7, and KaiOS Browser.
Prerequisites
Before you begin, ensure that you have:
-
An ApsaraVideo VOD account.
-
At least one video uploaded to VOD.
-
(Optional) Event notifications configured.
Workflow
-
Create a template (format, frame rate, dimensions, time range).
-
Submit a task via workflow or API.
-
Receive an event notification.
-
Retrieve the animated image URL.
Step 1: Create a template
Console
-
Log in to the ApsaraVideo VOD console.
-
Click Create Frame Animation Template.
-
Configure the template:
Parameter
Description
Example
Template Name
Unique identifier (4-64 characters)
social-media-previewOutput Format
giforwebpwebpFrame Rate
Frames per second (1-60)
15Dimensions
Width × Height (optional)
640×360Time Range
Duration: Start + length
Trim End: Start to (length - trim)Duration
Start Time
Extraction start (seconds)
5.0Duration
Length (seconds, for Duration mode)
3.0Trim from End
Exclude from end (seconds, for Trim mode)
N/A
Set as Cover
Use as video thumbnail
Disabled
Example: 3-second WebP, 15 fps, 640×360, starts at 5 seconds.
-
Click OK.
Note the Template ID for Step 3.
API
Call AddVodTemplate with TemplateType=DynamicImage:
{
"TemplateType": "DynamicImage",
"Name": "social-media-preview",
"TemplateConfig": {
"Format": "webp",
"Fps": "15",
"Width": "640",
"Height": "360",
"TimeSpan": {
"Seek": "5",
"Duration": "3"
}
}
}
Response includes VodTemplateId.
Step 2 (Optional): Configure event notifications
-
Set up callbacks:
Configure event notifications . -
Subscribe to
DynamicImageComplete .
Callback includes: URL, format, file size, dimensions, status, errors (if failed).
Step 3: Submit a task
Console (workflow)
Create workflow
-
Create a workflow that includes the Frame Animation Template node.
-
In the workflow, add the Frame Animation Template node and set the animated image template to the one created in Step 1.
-
For more information about how to create workflows, see Workflows.
Submit during upload
-
Go to Media Files > Audio/Video.
-
Click Upload Audio/Video.
-
Select Use Workflow > Workflow > your workflow.
-
Click Upload.
Submit for existing videos
-
Go to Media Files > Audio/Video.
-
Find video, click Processing.
-
Select workflow.
-
Click OK.
API
During upload: Set WorkflowId when calling:
For existing videos: Call SubmitDynamicImageJob:
{
"VideoId": "ca570defc72f4057b54ea7fc41a****",
"DynamicImageTemplateId": "5d0d68xxx****"
}
Step 4: Retrieve the result
Method 1: Event notification (Recommended)
{
"EventType": "DynamicImageComplete",
"VideoId": "ca570defc72f4057b54ea7fc41a****",
"JobId": "d7d1a82a51f44a0b9c2e2a7e3a****",
"DynamicImageUrl": "https://example.oss-cn-hangzhou.aliyuncs.com/animated/preview.webp",
"Width": 640,
"Height": 360,
"FileSize": 1048576,
"Format": "webp",
"Status": "success"
}
Method 2: API
Call ListDynamicImage. Response includes DynamicImageList.
Method 3: Console
-
Go to Media Files > Audio/Video.
-
Find video, click Manage.
-
Check Animated Images tab.
Method 4: Cover image
If Set as Cover enabled, call GetVideoInfo and check CoverURL.
Best practices
Optimize file size
|
Practice |
Impact |
|
Use WebP vs GIF |
30-70% smaller |
|
Set 10-15 fps |
Sufficient, smaller file |
|
Limit to 3-5 seconds |
Balance quality/size |
|
Match display size |
Don't use source resolution |
Extraction time ranges
|
Content |
Recommendation |
|
Product demos |
Show features in action |
|
Highlights |
Capture engaging moments |
|
Static |
Avoid credits, black screens |
Format selection
|
Use Case |
Format |
Why |
|
Max compatibility |
GIF |
All browsers |
|
Min file size |
WebP |
30-70% smaller |
|
Mobile apps |
WebP |
Check iOS Safari ≥14 |
|
Modern web |
WebP + fallback |
Browser detection |
Code examples
Python
from aliyunsdkcore.client import AcsClient
from aliyunsdkvod.request.v20170321 import SubmitDynamicImageJobRequest
import os
client = AcsClient(
os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_ID'),
os.environ.get('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
'cn-shanghai'
)
request = SubmitDynamicImageJobRequest.SubmitDynamicImageJobRequest()
request.set_VideoId('ca570defc72f4057b54ea7fc41a****')
request.set_DynamicImageTemplateId('5d0d68xxx****')
print(client.do_action_with_exception(request))
Java
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.vod.model.v20170321.*;
import com.aliyuncs.profile.DefaultProfile;
public class AnimatedImage {
public static void main(String[] args) throws Exception {
DefaultProfile profile = DefaultProfile.getProfile(
"cn-shanghai",
System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"),
System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")
);
DefaultAcsClient client = new DefaultAcsClient(profile);
SubmitDynamicImageJobRequest request = new SubmitDynamicImageJobRequest();
request.setVideoId("ca570defc72f4057b54ea7fc41a****");
request.setDynamicImageTemplateId("5d0d68xxx****");
SubmitDynamicImageJobResponse response = client.getAcsResponse(request);
System.out.println("Job ID: " + response.getDynamicImageJob().getJobId());
}
}
Node.js
const Core = require('@alicloud/pop-core');
const client = new Core({
accessKeyId: process.env.ALIBABA_CLOUD_ACCESS_KEY_ID,
accessKeySecret: process.env.ALIBABA_CLOUD_ACCESS_KEY_SECRET,
endpoint: 'https://vod.cn-shanghai.aliyuncs.com',
apiVersion: '2017-03-21'
});
client.request('SubmitDynamicImageJob', {
VideoId: 'ca570defc72f4057b54ea7fc41a****',
DynamicImageTemplateId: '5d0d68xxx****'
}, { method: 'POST' })
.then(result => console.log('Job ID:', result.DynamicImageJob.JobId))
.catch(error => console.error('Error:', error));
Troubleshooting
"InvalidVideoFormat" error
Cause: No video stream or corrupted container.
Fix:
-
Verify file contains video stream.
-
Check corruption (play locally).
-
Re-upload if needed.
-
Inspect:
ffmpeg -i video.mp4.
Blank/corrupted image
Cause: Invalid time range.
Fix:
-
Check duration: ListDynamicImage.
-
Ensure
StartTime< duration. -
Verify
StartTime + Duration≤ duration. -
For Trim: verify
StartTime + (duration - TrimEnd)is valid.
File too large
Cause: High fps, long duration, large dimensions.
Fix:
-
Lower to 10-15 fps.
-
Limit to 3-5 seconds.
-
Resize to display size (e.g., 640×360).
-
Use WebP vs GIF.
WebP not displaying
Cause: Browser doesn't support WebP.
Fix: Implement fallback:
function supportsWebP() {
const canvas = document.createElement('canvas');
return canvas.getContext && canvas.getContext('2d') &&
canvas.toDataURL('image/webp').indexOf('data:image/webp') === 0;
}
const format = supportsWebP() ? 'webp' : 'gif';
document.getElementById('preview').src = `https://example.com/preview.${format}`;
Pricing
Billed as video transcoding by resolution and duration. See Billing for basic services.
Limitations
-
Audio-only or corrupted files cannot generate images.
-
Processing time varies by video size, duration, extraction length.
-
Tasks run asynchronously—use events or ListDynamicImage.