All Products
Search
Document Center

Object Storage Service:Video to Animated Image

Last Updated:Mar 20, 2026

Convert a video stored in an OSS bucket into a GIF or WebP animated image using the asynchronous processing API.

How it works

zhuandongtu

The conversion uses the video/animation action, submitted as an asynchronous job via the x-oss-async-process request header. OSS calls Intelligent Media Management (IMM) to process the video and saves the output to a path you specify. Optionally, IMM sends a completion notification through Message Service (MNS).

Only asynchronous processing is supported. Anonymous access is denied.

Choose an output format

FormatBrowser supportBest for
GIFUniversalMaximum compatibility; works in all clients and email
WebPMost modern browsersSmaller file size than GIF at similar quality

Use cases

  • Social media clips: Extract short moments from a video and share them as animated images on social platforms.

  • Tutorials and demos: Capture step-by-step software operations as looping animated images that readers can follow without playing a video.

  • Stickers and reactions: Turn video moments into animated stickers for messaging apps.

  • Event highlights: Clip key moments from live streams, competitions, or presentations and share them instantly.

Prerequisites

Before you begin, ensure that you have:

Convert a video to an animated image

Only the Java, Python, and Go SDKs support asynchronous processing for video-to-animated-image conversion.

All examples use the x-oss-async-process header to submit an asynchronous conversion job. The processing string follows this structure:

video/animation,<params>|sys/saveas,b_<base64-bucket>,o_<base64-object>/notify,topic_<base64-topic>

The bucket name, output object name, and notification topic must be Base64-encoded (URL-safe, no padding).

Python

Requires Python SDK version 2.18.4 or later.

# -*- coding: utf-8 -*-
import base64
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

def main():
    # Read credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    # Set the endpoint for the region where your bucket is located.
    endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
    # Set the region ID that matches the endpoint.
    region = 'cn-hangzhou'

    bucket = oss2.Bucket(auth, endpoint, 'examplebucket', region=region)

    # Set the source video file name and the output file name.
    source_key = 'src.mp4'
    target_key = 'example.gif'

    # Define the conversion parameters: output format GIF, 100x100 px, 1-second frame interval.
    animation_style = 'video/animation,f_gif,w_100,h_100,inter_1000'

    # Base64-encode the bucket name and output object name (URL-safe, no padding).
    bucket_name_encoded = base64.urlsafe_b64encode('examplebucket'.encode()).decode().rstrip('=')
    target_key_encoded = base64.urlsafe_b64encode(target_key.encode()).decode().rstrip('=')

    # Assemble the full processing string, including save path and MNS notification topic.
    process = f"{animation_style}|sys/saveas,b_{bucket_name_encoded},o_{target_key_encoded}/notify,topic_QXVkaW9Db252ZXJ0"

    try:
        # Submit the asynchronous job.
        result = bucket.async_process_object(source_key, process)
        print(f"EventId: {result.event_id}")
        print(f"RequestId: {result.request_id}")
        print(f"TaskId: {result.task_id}")
    except Exception as e:
        print(f"Error: {e}")


if __name__ == "__main__":
    main()

Java

Requires Java SDK version 3.17.4 or later.

import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.AsyncProcessObjectRequest;
import com.aliyun.oss.model.AsyncProcessObjectResult;
import com.aliyuncs.exceptions.ClientException;

import java.util.Base64;

public class Demo {
    public static void main(String[] args) throws ClientException {
        // Set the endpoint for the region where your bucket is located.
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // Set the region ID that matches the endpoint.
        String region = "cn-hangzhou";
        // Read credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // Set the bucket name.
        String bucketName = "examplebucket";
        // Set the name of the source video file.
        String sourceKey = "src.mp4";
        // Set the output file name.
        String targetKey = "dest.gif";

        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(endpoint)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();

        try {
            // Define the conversion parameters: output format GIF, 100x100 px, 1-second frame interval.
            String style = "video/animation,f_gif,w_100,h_100,inter_1000";

            // Base64-encode the bucket name and output object name (URL-safe, no padding).
            String bucketEncoded = Base64.getUrlEncoder().withoutPadding().encodeToString(bucketName.getBytes());
            String targetEncoded = Base64.getUrlEncoder().withoutPadding().encodeToString(targetKey.getBytes());

            // Assemble the full processing string, including save path and MNS notification topic.
            String process = String.format("%s|sys/saveas,b_%s,o_%s/notify,topic_QXVkaW9Db252ZXJ0", style, bucketEncoded, targetEncoded);

            // Submit the asynchronous job.
            AsyncProcessObjectRequest request = new AsyncProcessObjectRequest(bucketName, sourceKey, process);
            AsyncProcessObjectResult response = ossClient.asyncProcessObject(request);
            System.out.println("EventId: " + response.getEventId());
            System.out.println("RequestId: " + response.getRequestId());
            System.out.println("TaskId: " + response.getTaskId());

        } finally {
            ossClient.shutdown();
        }
    }
}

Go

Requires Go SDK version 3.0.2 or later.

package main

import (
    "encoding/base64"
    "fmt"
    "os"
    "log"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // Read credentials from environment variables OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET.
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Create an OSSClient. Set the endpoint and region for the bucket's location.
    client, err := oss.New("https://oss-cn-hangzhou.aliyuncs.com", "", "",
        oss.SetCredentialsProvider(&provider),
        oss.AuthVersion(oss.AuthV4),
        oss.Region("cn-hangzhou"))
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Set the bucket name.
    bucketName := "examplebucket"
    bucket, err := client.Bucket(bucketName)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // Set the source video file name and the output file name.
    sourceKey := "src.mp4"
    targetKey := "destexample.gif"

    // Define the conversion parameters: output format GIF, 100x100 px, 1-second frame interval.
    animationStyle := "video/animation,f_gif,w_100,h_100,inter_1000"

    // Base64-encode the bucket name and output object name (URL-safe, no padding).
    bucketNameEncoded := base64.URLEncoding.EncodeToString([]byte(bucketName))
    targetKeyEncoded := base64.URLEncoding.EncodeToString([]byte(targetKey))

    // Assemble the full processing string, including save path and MNS notification topic.
    process := fmt.Sprintf("%s|sys/saveas,b_%v,o_%v/notify,topic_QXVkaW9Db252ZXJ0", animationStyle, bucketNameEncoded, targetKeyEncoded)

    // Submit the asynchronous job.
    result, err := bucket.AsyncProcessObject(sourceKey, process)
    if err != nil {
        log.Fatalf("Failed to async process object: %s", err)
    }

    fmt.Printf("EventId: %s\n", result.EventId)
    fmt.Printf("RequestId: %s\n", result.RequestId)
    fmt.Printf("TaskId: %s\n", result.TaskId)
}

Parameters

Action: video/animation

ParameterTypeRequiredDefaultDescription
fstringYesOutput format. Valid values: gif, webp
ssintNo0Start time in milliseconds. 0 starts from the beginning; any positive value starts from that millisecond.
numintNoNo limitMaximum number of frames to extract. If the video is shorter than expected, fewer frames are extracted.
interintNoAll framesFrame extraction interval in milliseconds. If set below the source video's frame interval, the source frame interval is used instead.
fpsfloatNoReciprocal of interPlayback frame rate of the output animated image. Valid values: [0, 240]. Values above the default speed up playback; values below slow it down.
wintNoSource video widthOutput width in pixels. Valid values: [32, 4096]
hintNoSource video heightOutput height in pixels. Valid values: [32, 4096]
scaletypestringNostretchScaling method. Valid values: crop (scale and crop), stretch (stretch to fill), fill (scale with black borders), fit (scale proportionally, no black borders)

How `inter`, `fps`, and `num` interact:

  • inter controls how often a frame is sampled from the source (in milliseconds).

  • fps controls the playback speed of the output. By default it equals 1000 / inter, so playback matches the source rate.

  • num sets an upper limit on total frames extracted. Use it to cap output size for long videos.

  • Setting both inter and fps independently lets you decouple sampling rate from playback speed. For example, sample every 500 ms (inter_500) but play at 25 fps (fps_25) to produce a time-lapse effect.

The sys/saveas and notify parameters are used in the processing string. For details, see Save as and Message notification.

API examples

GIF, 100x100 px, 1-second interval

Converts example.mkv to a 100x100 px GIF, sampling one frame per second.

POST /example.mkv?x-oss-async-process HTTP/1.1
Host: video-demo.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 28 Oct 2022 06:40:10 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e

x-oss-async-process=video/animation,f_gif,w_100,h_100,inter_1000|sys/saveas,b_b3V0YnVja2V0,o_b3V0b2JqcHJlZml4LnthdXRvZXh0fQ/notify,topic_QXVkaW9Db252ZXJ0
ParameterValueEncoded value
Output bucketoutbucketb_b3V0YnVja2V0
Output objectoutobjprefix.{autoext}o_b3V0b2JqcHJlZml4LnthdXRvZXh0fQ
Notification topicAudioConverttopic_QXVkaW9Db252ZXJ0

WebP, quarter size, starting from 5 seconds

Converts example.mkv to WebP starting at the 5-second mark, at 25% of the original dimensions, with a 0.5-second frame interval and 25 fps playback.

POST /example.mkv?x-oss-async-process HTTP/1.1
Host: video-demo.oss-cn-hangzhou.aliyuncs.com
Date: Fri, 28 Oct 2022 06:40:10 GMT
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20250417/cn-hangzhou/oss/aliyun_v4_request,Signature=a7c3554c729d71929e0b84489addee6b2e8d5cb48595adfc51868c299c0c218e

x-oss-async-process=video/animation,ss_5000,f_webp,pw_25,ph_25,fps_25,inter_500|sys/saveas,b_b3V0YnVja2V0,o_b3V0b2JqcHJlZml4LnthdXRvZXh0fQ/notify,topic_QXVkaW9Db252ZXJ0

Billing

Converting a video to an animated image triggers billing on both the OSS side and the IMM side.

Important

Starting from 11:00 on July 28, 2025 (UTC+8), the IMM video-to-animated-image conversion service changed from free to paid. The billing item is MediaAnimation, charged based on the number of frames in the output animated image. For details, see the IMM billing adjustment announcement.

OSS billing

For detailed pricing, see OSS pricing.

APIBilling itemBasis
GetObjectGET requestsPer successful request
GetObject (public or acceleration endpoint)Outbound Internet trafficData size
GetObject (Infrequent Access objects)Infrequent Access data retrievalRetrieved data size
GetObject (Archive objects with real-time access enabled)Archive data retrievalRetrieved data size
GetObject (transfer acceleration endpoint)Transfer accelerationData size
PutObjectPUT requestsPer successful request
PutObjectStorage feesStorage class, data size, and storage duration
HeadObjectGET requestsPer successful request

IMM billing

For detailed pricing, see IMM billing items.

APIBilling itemBasis
CreateMediaConvertTaskMediaAnimationNumber of frames in the output animated image

Usage notes

  • Video to animated image conversion supports only asynchronous processing (x-oss-async-process).

  • Anonymous access is denied.