ApsaraVideo VOD provides multiple methods to migrate video resources from third-party platforms, Object Storage Service (OSS), or across Alibaba Cloud accounts.
Migration methods
Choose a migration method based on your source resource location and requirements:
Source | Migration method | When to use | Tool |
Third-party platform (AWS S3, Azure Blob, etc.) | URL-based batch upload (Recommended) | Resources are publicly accessible via URLs | ApsaraVideo VOD console or API |
Third-party platform | SDK/API upload | Require real-time upload feedback | Upload SDK or API |
OSS within same Alibaba Cloud account | OSS bucket registration (Recommended) | No need to move data physically | RegisterMedia API |
OSS within same Alibaba Cloud account | URL-based batch upload | Need VOD-specific processing | ApsaraVideo VOD API |
OSS across Alibaba Cloud accounts | URL-based batch upload | Resources in different accounts | Upload SDK or API |
VOD across Alibaba Cloud accounts | URL-based batch upload | Migrate between VOD instances | Upload SDK or API |
Key differences:
URL-based upload: Best for batch migration of publicly accessible resources. Async process, may take hours to days.
SDK upload: Best for real-time uploads requiring immediate feedback. Sync process, faster execution.
OSS bucket registration: Best for OSS-to-VOD migration within the same account. No data transfer needed.
Prerequisites
Before you begin, ensure that you have:
An active ApsaraVideo VOD service account
An AccessKey pair (AccessKey ID and AccessKey Secret) for API authentication
(For RAM users) A RAM user with the required VOD permissions (Create a RAM user)
Source resource URLs (if using URL-based upload) that remain valid during migration
(For OSS migration) Source OSS buckets and objects
Method 1: URL-based batch upload (Recommended)
When to use
Use URL-based batch upload when:
Resources are stored remotely (not on local devices) and publicly accessible
You need to migrate a large number of files efficiently
Resources are in supported regions: China (Shanghai), China (Beijing), China (Shenzhen), Singapore, or US (Silicon Valley)
For other regions, use Method 2 (SDK upload) instead.
Usage notes
Asynchronous processing: Batch upload jobs run asynchronously. Large migrations may take hours or days to complete.
New media IDs: Each upload creates a new media ID in VOD.
UploadMediaByURLdoes not support specifying a target video ID, so you cannot overwrite an existing or deleted video ID, and the source file of a deleted video cannot be restored through migration. Track the mapping between source file addresses and media IDs for reference.Deleted videos: If a video has been deleted from VOD, migration cannot restore it. Source files removed by calling
DeleteMezzaninescannot be recovered either. Before migrating, confirm the status of the source file. To manage or remove videos that were uploaded by mistake, see Delete media files.URL requirements: URLs must include file names with extensions (e.g.,
https://example.com/video.mp4)URL signing: If your source enables URL signing, ensure URLs remain valid throughout the migration period.
Original file stream visibility: If you don't set the
TemplateGroupIdparameter (the defaultVOD_NO_TRANSCODEmode), the migrated video's playback addresses show only the "Original quality" stream. To also expose an "Original file" stream, specify aTemplateGroupIdfor a transcoding template group other thanVOD_NO_TRANSCODE.
Procedure
Step 1: Install the VOD SDK
This example uses the ApsaraVideo VOD SDK for Java. For other languages, see VOD SDK overview.
Requirements:
JDK 8 or later
Maven 3.x or Gradle
Add the dependency to your pom.xml:
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-vod</artifactId>
<version>2.16.11</version>
</dependency>
Step 2: Prepare source resource URLs
Create a list of all resources to migrate:
Collect download URLs for all files
Ensure URLs include file names and extensions:
Correct:
https://example.com/videos/intro.mp4Incorrect:
https://example.com/download?id=12345(no file extension)
For signed URLs, verify they remain valid during migration
Test a few URLs to confirm they're accessible
Step 3: Submit batch upload jobs
Call the UploadMediaByURL operation to submit upload jobs. You can test this API using OpenAPI Explorer.
Java example:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.UploadMediaByURLRequest;
import com.aliyuncs.vod.model.v20170321.UploadMediaByURLResponse;
public class UploadByURL {
public static void main(String[] args) {
// Read credentials from environment variables
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
String regionId = "cn-shanghai"; // Region where VOD service is activated
// Initialize VOD client
DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
// Create upload request
UploadMediaByURLRequest request = new UploadMediaByURLRequest();
// Specify source URLs (comma-separated for multiple files)
request.setUploadURLs("https://example.com/video1.mp4,https://example.com/video2.mp4");
// Optional: Specify a transcoding template group. If you don't set this parameter,
// VOD transcodes the uploaded file using the destination account's default
// transcoding template group, which may replace the mezzanine file with a
// transcoded output instead of preserving the original file.
request.setTemplateGroupId("");
// Optional: Set metadata for uploaded videos
request.setUploadMetadatas("[{\"Title\":\"Video 1\"},{\"Title\":\"Video 2\"}]");
try {
UploadMediaByURLResponse response = client.getAcsResponse(request);
System.out.println("Request ID: " + response.getRequestId());
System.out.println("Upload jobs created:");
for (UploadMediaByURLResponse.UploadJob job : response.getUploadJobs()) {
System.out.println("- Job ID: " + job.getJobId());
System.out.println(" Source URL: " + job.getSourceURL());
}
} catch (Exception e) {
System.err.println("Upload failed: " + e.getMessage());
}
}
}
You can use the TemplateGroupId parameter to specify the transcoding template group that controls how the uploaded file is processed after the upload. By default, VOD_NO_TRANSCODE (no transcoding) is used, and the file is displayed as the mezzanine (OD) quality.
Before running the code:
Set environment variables:
export ALIBABA_CLOUD_ACCESS_KEY_ID="<your-access-key-id>" export ALIBABA_CLOUD_ACCESS_KEY_SECRET="<your-access-key-secret>"Replace placeholders:
<your-access-key-id>: Your AccessKey ID<your-access-key-secret>: Your AccessKey SecretUpdate
regionIdto your VOD service regionReplace example URLs with your actual source URLs
Compile and run:
mvn compile exec:java -Dexec.mainClass="UploadByURL"
Step 4: Monitor upload progress
Choose one of the following methods to track upload job status:
Method 1: Event notifications (Recommended)
Configure event notifications to receive callbacks when uploads complete:
Set up HTTP or MNS callbacks in the VOD console (see Event notification overview)
Listen for
UploadByURLCompleteeventsParse the callback payload to check upload status
Success callback example:
{
"Status": "success",
"EventTime": "2026-03-10T09:15:00Z",
"EventType": "UploadByURLComplete",
"VideoId": "43q9fjdun3f2a5b",
"JobId": "4c815bjs83j1d8f",
"SourceURL": "https://example.com/video.mp4",
"Size": "123456789"
}
Failure callback example:
{
"Status": "fail",
"EventTime": "2026-03-10T09:15:00Z",
"EventType": "UploadByURLComplete",
"ErrorCode": "URLInvalidError",
"ErrorMessage": "Download video failed by the URL, please check it",
"JobId": "4c815bjsued1f9a",
"SourceURL": "https://example.com/invalid-video.mp4"
}
Method 2: API polling
Call the GetURLUploadInfos operation periodically to query job status:
GetURLUploadInfosRequest request = new GetURLUploadInfosRequest();
request.setJobIds("job-id-1,job-id-2"); // Comma-separated job IDs
GetURLUploadInfosResponse response = client.getAcsResponse(request);
for (GetURLUploadInfosResponse.UrlUploadJobInfo job : response.getURLUploadInfoList()) {
System.out.println("Job ID: " + job.getJobId());
System.out.println("Status: " + job.getStatus()); // NotStarted/Uploading/Success/Failed
if ("Success".equals(job.getStatus())) {
System.out.println("Video ID: " + job.getVideoId());
}
}
For more information, see GetURLUploadInfos.
Verify
After uploads complete:
Check upload job status: Verify all jobs show "Success" status
Confirm video IDs: Ensure each uploaded resource has a corresponding video ID
Test playback: Play sample videos to confirm successful migration
Map source to destination: Record the mapping between source URLs and VOD video IDs for reference
Method 2: SDK upload with self-built service
Use this method when:
URL-based upload is not supported in your region
You require real-time upload feedback
You need to download resources locally before uploading
Scenario A: Upload over internal network
When to use: Your ECS instance and source OSS bucket are in the same region.
Benefits: Faster upload speed, no public network traffic costs.
Prerequisites
An ECS instance deployed in the same region as the source OSS bucket
Network connectivity between ECS and OSS/VOD services
Procedure
Step 1: Obtain internal network addresses
For OSS resources:
List objects in your OSS bucket (see List objects)
Get the OSS address for each object
Convert to internal network address by adding
-internalafter the region:OSS address:
outin-xxx.oss-cn-shanghai.aliyuncs.com/video.mp4Internal address:
outin-xxx.oss-cn-shanghai-internal.aliyuncs.com/video.mp4
For VOD resources:
Call
GetMezzanineInfowithOutputType=ossto get OSS addresses (see GetMezzanineInfo)Convert to internal network addresses using the same method above
Internal network address conversion:
OSS Address | Internal Network Address |
|
|
|
|
For more information about internal endpoints, see Access OSS resources from ECS instances by using the internal endpoint of OSS.
Step 2: Deploy upload service on ECS
Deploy your upload service on an ECS instance in the same region as your source resources. Set the regionId parameter to match the ECS region. The upload SDK automatically uses internal network endpoints when the regions match.
Example upload code (Java):
import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadStreamRequest;
import com.aliyun.vod.upload.resp.UploadStreamResponse;
import java.io.InputStream;
import java.net.URL;
public class InternalNetworkUpload {
public static void main(String[] args) throws Exception {
// Read credentials from environment variables
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Internal network URL (obtained in Step 1)
String internalUrl = "https://bucket.oss-cn-shanghai-internal.aliyuncs.com/video.mp4";
// Download from internal network URL
InputStream inputStream = new URL(internalUrl).openStream();
// Create upload request
UploadStreamRequest request = new UploadStreamRequest(
accessKeyId,
accessKeySecret,
"Video Title", // Video title
"video.mp4", // File name with extension
inputStream
);
// Set region (must match ECS region for internal network)
request.setApiRegionId("cn-shanghai");
request.setEcsRegionId("cn-shanghai");
// Optional: Specify a transcoding template group. If you don't set this parameter,
// VOD transcodes the uploaded file using the destination account's default
// transcoding template group, which may replace the mezzanine file with a
// transcoded output instead of preserving the original file.
request.setTemplateGroupId("");
// Upload
UploadVideoImpl uploader = new UploadVideoImpl();
UploadStreamResponse response = uploader.uploadStream(request);
if (response.isSuccess()) {
System.out.println("Upload successful");
System.out.println("Video ID: " + response.getVideoId());
} else {
System.err.println("Upload failed: " + response.getMessage());
}
}
}
For more upload SDK examples, see Upload SDK for Java.
Step 3: Execute batch upload
Run your upload service to migrate all resources using internal network addresses.
Scenario B: Upload over Internet
When to use:
You don't have an ECS instance, or your ECS instance is in a different region from source resources
Source resources are on third-party platforms (AWS S3, Azure Blob, personal websites, etc.)
Procedure
Step 1: Prepare source file addresses
For VOD resources:
Call
SearchMediato query video IDs (see SearchMedia)Call
GetMezzanineInfoto get source file addresses (see GetMezzanineInfo)
For OSS resources:
List objects in your OSS bucket (see List objects)
Get public URLs for each object
For third-party resources:
Collect download URLs from your source platform
Step 2: Deploy upload service
Set up your upload service using the upload SDK. Example code:
import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadStreamRequest;
import com.aliyun.vod.upload.resp.UploadStreamResponse;
import java.io.InputStream;
import java.net.URL;
public class InternetUpload {
public static void main(String[] args) throws Exception {
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
// Public URL
String sourceUrl = "https://example.com/video.mp4";
// Download from source
InputStream inputStream = new URL(sourceUrl).openStream();
// Create upload request
UploadStreamRequest request = new UploadStreamRequest(
accessKeyId,
accessKeySecret,
"Video Title",
"video.mp4",
inputStream
);
request.setApiRegionId("cn-shanghai"); // VOD service region
// Upload
UploadVideoImpl uploader = new UploadVideoImpl();
UploadStreamResponse response = uploader.uploadStream(request);
if (response.isSuccess()) {
System.out.println("Video ID: " + response.getVideoId());
}
}
}
Step 3: Track source-to-destination mappings (Recommended)
To manage videos after migration, record mappings between source URLs and VOD video IDs. You can:
Write mappings to a database
Store mappings in logs
Include source URLs in video metadata using the
UserDataparameter during upload
Step 4: Organize migrated resources (Optional)
After migration, organize your videos based on the mappings. Use VOD APIs to:
Update video titles and descriptions
Add tags and categories
Set thumbnails and cover images
For more information, see UpdateVideoInfo.
Method 3: Register OSS buckets (Same account only)
When to use
Use this method to migrate OSS resources to VOD within the same Alibaba Cloud account without physically moving data. This is the fastest and most cost-effective method for same-account migration.
Limitations
Storage class: Only Standard OSS buckets are supported
Bucket quota: Maximum 10 OSS buckets per region can be added to VOD
Account restriction: Source OSS and destination VOD must belong to the same Alibaba Cloud account
Procedure
Step 1: Add OSS bucket to VOD
Add the source OSS bucket to your VOD service:
Log on to the ApsaraVideo VOD console
In the left-side navigation pane, choose Configuration Management > Media Management > Storage
Click Add Storage
Select your OSS bucket and configure permissions
Click OK
For detailed steps, see Manage VOD storage.
Step 2: Register media resources
Register OSS objects as VOD media assets using the RegisterMedia API:
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.RegisterMediaRequest;
import com.aliyuncs.vod.model.v20170321.RegisterMediaResponse;
public class RegisterOSSMedia {
public static void main(String[] args) throws Exception {
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
RegisterMediaRequest request = new RegisterMediaRequest();
// Specify OSS file URL (must include OSS domain name)
request.setRegisterMetadatas(
"[{\"FileURL\":\"https://bucket-name.oss-cn-hangzhou.aliyuncs.com/video/example.mp4\"," +
"\"Title\":\"Example Video\"}]"
);
RegisterMediaResponse response = client.getAcsResponse(request);
System.out.println("Registered video IDs:");
for (RegisterMediaResponse.RegisteredMedia media : response.getRegisteredMediaList()) {
System.out.println("- " + media.getMediaId());
}
}
}
Key parameters:
FileURL: Full OSS path including domain name (e.g.,https://bucket.oss-cn-hangzhou.aliyuncs.com/path/to/video.mp4)Title: Video title in VOD
For more information, see RegisterMedia.
Verify
After registration:
Check media library: Verify registered videos appear in the VOD console
Test playback: Play registered videos to confirm they're accessible
Verify metadata: Check video titles and attributes match your expectations
Best practices
Migration planning
Estimate migration time: URL-based batch upload is asynchronous. Large migrations (1000+ files) may take hours to days.
Batch size: Split large migrations into batches of 100-500 files for better tracking and error recovery.
Network bandwidth: Consider your network bandwidth when choosing between internal network and Internet upload.
Cost optimization
Use internal network: When migrating OSS resources in the same region, use internal network addresses to avoid public network traffic costs.
Register instead of upload: For same-account OSS-to-VOD migration, use bucket registration (Method 3) to avoid upload costs and time.
Resource management
Track mappings: Always record the mapping between source URLs and VOD video IDs for future reference.
Metadata migration: Include video metadata (title, tags, description) during upload to avoid manual updates later.
Cleanup: After verifying successful migration, delete source resources to reduce storage costs (if no longer needed).
Error handling
URL validity: Ensure signed URLs remain valid throughout the migration period.
Retry failed jobs: Monitor upload job status and retry failed uploads with corrected URLs.
Validation: Test upload with a small sample before migrating large volumes.
Troubleshooting
URL-based upload fails
Symptom: Upload job status shows "Failed" in the callback or API response.
Common causes:
URL not accessible: Source URL returns 403/404 error
Solution: Verify the URL is publicly accessible. If using signed URLs, check the signature hasn't expired.
Invalid URL format: URL doesn't include file name or extension
Solution: Ensure URLs follow the format
https://domain.com/path/file.mp4
Region not supported: Source region doesn't support URL-based upload
Solution: Use Method 2 (SDK upload) instead
SDK upload performance is slow
Symptom: Upload takes longer than expected.
Common causes:
Network bandwidth limitation: Limited upload bandwidth
Solution: Use internal network upload (Scenario A) if ECS and source are in the same region
File size: Large video files take longer to upload
Solution: Consider compressing videos before upload, or use multipart upload for files over 100 MB
RegisterMedia fails
Symptom: API returns error when registering OSS objects.
Common causes:
OSS bucket not added: Bucket hasn't been added to VOD
Solution: Complete Step 1 to add the OSS bucket to VOD first
Invalid FileURL: URL format is incorrect
Solution: Ensure FileURL includes the full OSS domain name (e.g.,
https://bucket.oss-cn-hangzhou.aliyuncs.com/video.mp4)
Permission denied: VOD doesn't have permission to access the OSS bucket
Solution: Grant VOD read permission to your OSS bucket in the VOD console
Next steps
Configure transcoding templates: Process uploaded videos with different resolutions and formats
Enable CDN acceleration: Improve video playback performance
Set up event notifications: Monitor video processing status