All Products
Search
Document Center

ApsaraVideo VOD:Media processing

Last Updated:Feb 27, 2026

Java SDK examples for submitting transcoding jobs, submitting snapshot jobs, querying snapshot data, and preprocessing videos in the production studio.

Prerequisites

Before you begin, make sure that you have:

  • An Alibaba Cloud account with ApsaraVideo VOD activated

  • An AccessKey pair (AccessKey ID and AccessKey secret) configured as environment variables

  • A Resource Access Management (RAM) user with the required ApsaraVideo VOD permissions

  • The ApsaraVideo VOD SDK for Java added to your project dependencies

For API operations not covered here, visit OpenAPI Explorer. Select an API operation, configure the parameters on the Parameters tab, and click Initiate Call. Download the generated code from the SDK Sample Code tab.

Initialize a client

Before calling any API operation, initialize a client instance. For setup instructions, see Initialization.

Submit a transcoding job

Call the SubmitTranscodeJobs operation to submit a transcoding job. The following example shows how to:

  • Set the video ID and transcoding template group ID

  • Override watermark parameters (optional)

  • Configure HTTP Live Streaming (HLS) encryption (optional)

  • Extract the job ID from the response

Only videos in the Uploaded, Normal, or Reviewing state can be transcoded. Configure callback settings to receive FileUploadComplete or ImageUploadComplete event notifications, then submit transcoding jobs after upload completes. To receive transcoding results, subscribe to the StreamTranscodeComplete or TranscodeComplete event. For details, see Configure callback settings.
import com.aliyuncs.vod.model.v20170321.SubmitTranscodeJobsRequest;
import com.aliyuncs.vod.model.v20170321.SubmitTranscodeJobsResponse;

/**
 * Submit a transcoding job with optional watermark overrides and HLS encryption.
 */
public static SubmitTranscodeJobsResponse submitTranscodeJobs(DefaultAcsClient client) throws Exception {
    SubmitTranscodeJobsRequest request = new SubmitTranscodeJobsRequest();

    // TODO: Replace with your video ID
    request.setVideoId("34a6ca54f5c140eece85a289****");

    // TODO: Replace with your transcoding template group ID
    request.setTemplateGroupId("e8aa925a9798c630d30cd****");

    // Override watermark parameters (optional). Required only to change watermark content at submission time.
    JSONObject overrideParams = buildOverrideParams();
    request.setOverrideParams(overrideParams.toJSONString());

    // Configure HLS encryption (optional). Required only for HLS-encrypted outputs.
    JSONObject encryptConfig = buildEncryptConfig(client);
    request.setEncryptConfig(encryptConfig.toJSONString());

    return client.getAcsResponse(request);
}

/**
 * Entry point for the transcoding job example.
 */
public static void main(String[] args) throws ClientException {
    // Initialize the client. See the Initialization topic for details.
    DefaultAcsClient client = initVodClient();
    SubmitTranscodeJobsResponse response = new SubmitTranscodeJobsResponse();
    try {
        response = submitTranscodeJobs(client);
        // Extract the job ID for tracking
        System.out.println("JobId = " + response.getTranscodeJobs().get(0).getJobId());
    } catch (Exception e) {
        System.out.println("ErrorMessage = " + e.getLocalizedMessage());
    }
    // The request ID is useful for troubleshooting with Alibaba Cloud support
    System.out.println("RequestId = " + response.getRequestId());
}

For complete API details, see SubmitTranscodeJobs in OpenAPI Explorer.

Override watermark parameters

Override the URL of an image watermark or the content of a text watermark at job submission time. Each watermark is identified by a WatermarkId associated with the transcoding template specified by TemplateGroupId.

The watermark file and the video must be stored on the same origin server.
/**
 * Build watermark override parameters.
 *
 * Overridable fields:
 * - Image watermark: FileUrl (the OSS URL of the replacement image)
 * - Text watermark: Content (the replacement text)
 *
 * The WatermarkId must be associated with the transcoding template in use.
 */
public static JSONObject buildOverrideParams() {
    JSONObject overrideParams = new JSONObject();
    JSONArray watermarks = new JSONArray();

    // Override an image watermark URL
    JSONObject watermark1 = new JSONObject();
    // TODO: Replace with your image watermark ID (must be associated with the transcoding template)
    watermark1.put("WatermarkId", "2ea587477c5a1bc8b57****");
    // TODO: Replace with the Object Storage Service (OSS) URL of the new watermark image
    watermark1.put("FileUrl", "http://developer.aliyundoc.com/image/image.png");
    watermarks.add(watermark1);

    // Override a text watermark
    JSONObject watermark2 = new JSONObject();
    // TODO: Replace with your text watermark ID (must be associated with the transcoding template)
    watermark2.put("WatermarkId", "d297ba31ac5242d207****");
    // TODO: Replace with the new text content for the watermark
    watermark2.put("Content", "User ID: 6****");
    watermarks.add(watermark2);

    overrideParams.put("Watermarks", watermarks);
    return overrideParams;
}

Configure HLS encryption

Generate a Key Management Service (KMS) data key and build the encryption configuration for HLS output. DecryptKeyUri specifies your decryption service endpoint. ApsaraVideo VOD calls this endpoint during playback to retrieve the decryption key.

import com.aliyuncs.vod.model.v20170321.GenerateKMSDataKeyRequest;
import com.aliyuncs.vod.model.v20170321.GenerateKMSDataKeyResponse;

/**
 * Build HLS encryption configuration using a KMS data key.
 */
public static JSONObject buildEncryptConfig(DefaultAcsClient client) throws ClientException {
    // Generate a KMS data key. The response contains both plaintext and ciphertext.
    // Only the ciphertext is passed to ApsaraVideo VOD.
    GenerateKMSDataKeyResponse response = generateDataKey(client);

    JSONObject encryptConfig = new JSONObject();

    // The URI of your decryption service. Concatenate the service URL with the ciphertext key.
    // The ciphertext is unique per video. The "Ciphertext" query parameter name is customizable.
    // TODO: Replace the base URL with your decryption service endpoint
    encryptConfig.put("DecryptKeyUri", "http://example.aliyundoc.com/decrypt?" +
            "Ciphertext=" + response.getCiphertextBlob());

    // Key service type. Only KMS is supported.
    encryptConfig.put("KeyServiceType", "KMS");

    // The ciphertext blob from the KMS GenerateDataKey response
    encryptConfig.put("CipherText", response.getCiphertextBlob());

    return encryptConfig;
}

/**
 * Generate a KMS data key for encryption.
 * The response contains the plaintext key (for internal use) and the ciphertext key
 * (passed to ApsaraVideo VOD for storage).
 */
public static GenerateKMSDataKeyResponse generateDataKey(DefaultAcsClient client) throws ClientException {
    GenerateKMSDataKeyRequest request = new GenerateKMSDataKeyRequest();
    return client.getAcsResponse(request);
}

Submit a snapshot job

Call the SubmitSnapshotJob operation to capture video frame snapshots and generate a sprite (image sprite).

To create a snapshot template, see AddVodTemplate.
import com.aliyuncs.vod.model.v20170321.SubmitSnapshotJobRequest;
import com.aliyuncs.vod.model.v20170321.SubmitSnapshotJobResponse;

/**
 * Submit a snapshot job with optional sprite configuration.
 */
public static SubmitSnapshotJobResponse submitSnapshotJob(DefaultAcsClient client) throws Exception {
    SubmitSnapshotJobRequest request = new SubmitSnapshotJobRequest();

    // TODO: Replace with the video ID to capture snapshots from
    request.setVideoId("4d237a8270084849bf4207876181****");

    // TODO: Replace with your snapshot template ID.
    // When SnapshotTemplateId is specified, the individual parameters below are ignored.
    request.setSnapshotTemplateId("5d745e6b8baadf589e0702426cfc6****");

    // The following parameters apply only when SnapshotTemplateId is not specified.
    request.setCount(50L);               // Total number of snapshots to capture
    request.setSpecifiedOffsetTime(0L);   // Start time in milliseconds
    request.setInterval(1L);              // Interval between snapshots in seconds
    request.setWidth("200");              // Snapshot width in pixels
    request.setHeight("200");             // Snapshot height in pixels

    // Configure sprite generation (optional)
    JSONObject spriteSnapshotConfig = buildSnapshotTemplateConfig();
    request.setSpriteSnapshotConfig(spriteSnapshotConfig.toJSONString());

    return client.getAcsResponse(request);
}

/**
 * Entry point for the snapshot job example.
 */
public static void main(String[] args) throws ClientException {
    DefaultAcsClient client = initVodClient();
    SubmitSnapshotJobResponse response = new SubmitSnapshotJobResponse();
    try {
        response = submitSnapshotJob(client);
        // Extract the snapshot job ID for tracking
        System.out.println("JobId = " + response.getSnapshotJob().getJobId());
    } catch (Exception e) {
        System.out.println("ErrorMessage = " + e.getLocalizedMessage());
    }
    System.out.println("RequestId = " + response.getRequestId());
}

For complete API details, see SubmitSnapshotJob in OpenAPI Explorer.

Configure a sprite

Build sprite configuration parameters to assemble individual snapshots into a grid image.

/**
 * Build sprite configuration.
 * A sprite arranges individual snapshots in a grid layout for efficient previewing.
 */
public static JSONObject buildSnapshotTemplateConfig() {
    JSONObject spriteSnapshotConfig = new JSONObject();
    spriteSnapshotConfig.put("CellWidth", "120");    // Width of each cell in pixels
    spriteSnapshotConfig.put("CellHeight", "68");     // Height of each cell in pixels
    spriteSnapshotConfig.put("Columns", "3");         // Number of columns in the grid
    spriteSnapshotConfig.put("Lines", "10");           // Number of rows in the grid
    spriteSnapshotConfig.put("Padding", "20");         // Padding between cells in pixels
    spriteSnapshotConfig.put("Margin", "50");          // Outer margin in pixels
    // Retain individual snapshot images after sprite generation.
    // Set to "keep" to preserve source images, or omit to discard them.
    spriteSnapshotConfig.put("KeepCellPic", "keep");
    spriteSnapshotConfig.put("Color", "tomato");       // Background color of the sprite
    return spriteSnapshotConfig;
}

Query snapshot data

Call the ListSnapshots operation to query snapshot data.

For complete API details and sample code, see ListSnapshots in OpenAPI Explorer.

Preprocess videos in the production studio

Call the SubmitPreprocessJobs operation to preprocess videos for the production studio.

For complete API details and sample code, see SubmitPreprocessJobs in OpenAPI Explorer.

What to do next