All Products
Search
Document Center

Intelligent Media Services:Edit multiple short videos at a time

Last Updated:Dec 15, 2025

This topic describes how to use the SubmitMediaProducingJob API to edit multiple short videos at a time. If you want to edit and produce videos in a more intelligent and efficient manner, use Batch video production.

Background

In the 5G era, a growing number of businesses are using short-form video platforms for marketing and promotion. A common strategy is to create a single ad and distribute it across multiple key opinion leader (KOL) or marketing accounts. However, major short-form video platforms have de-duplication mechanisms to prevent content theft. As a result, identical marketing videos are often flagged and their visibility suppressed. This requires that videos posted to different accounts have variations in their content and structure.

Prerequisites

The Intelligent Media Services (IMS) server SDK is installed. For more information, see Preparations.

Edit multiple videos at a time

By using a timeline-based approach, you can achieve fine-grained control over your video edits.

Input: Voiceover script

View sample code

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;

import java.util.*;

// The output video is hosted at the following URL:
// http://oushu-test-shanghai.oss-cn-shanghai.aliyuncs.com/ice_output/46b29eb5775f4f758846171ab79bfca7.mp4

/**
 *  Add the following dependencies:
 *   <dependency>
 *      <groupId>com.aliyun</groupId>
 *      <artifactId>ice20201109</artifactId>
 *      <version>2.1.0</version>
 *  </dependency>
 *  <dependency>
 *      <groupId>com.alibaba</groupId>
 *      <artifactId>fastjson</artifactId>
 *      <version>1.2.9</version>
 *  </dependency>
 */
public class BatchProduceAlignment {

    static final String regionId = "cn-shanghai";
    static final String bucket = "<your-bucket>";
    private Client iceClient;

    public static void main(String[] args) throws Exception {
        BatchProduceAlignment batchProduce = new BatchProduceAlignment();
        batchProduce.initClient();
        batchProduce.run();
    }

    public void initClient() throws Exception {
        // The AccessKey pair of an Alibaba Cloud account has access permissions on all API operations. We recommend that you use the AccessKey pair of a Resource Access Management (RAM) user to call API operations or perform routine O&M operations. 
        // In this example, the AccessKey ID and AccessKey secret are obtained from the environment variables. For information about how to configure environment variables to store the AccessKey ID and AccessKey secret, visit https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials
        com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
        Config config = new Config();
        config.setCredential(credentialClient);

        // To hard-code your AccessKey ID and AccessKey secret, use the following lines. However, we recommend that you do not save the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of resources within your account may be compromised.
        // config.accessKeyId = <AccessKey ID created in the second step>;
        // config.accessKeySecret = <AccessKey Secret created in the second step>;
        config.endpoint = "ice." + regionId + ".aliyuncs.com";
        config.regionId = regionId;
        iceClient = new Client(config);
    }

    public void run() throws Exception {
        // Text material
        String text = "People may describe life as a mixture of five flavors, because flavors are associated with feelings and tastes of life deep in their hearts. This era sees lots of bitterness and sweetness in each individual. Many people leave bitter feelings silent inside and let yummy foods on tables speak for their sweet feelings throughout passing seasons.";
        // Video material
        String[] videoArray = new String[]{
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f1.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f2.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f3.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f4.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f5.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f6.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f7.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f8.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f9.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f10.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f11.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f12.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f13.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f14.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f15.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f16.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f17.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f18.mp4"
        };
        // Background music
        String[] bgMusicArray = new String[]{
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m1.wav",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m2.wav",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m3.wav"
        };
        // Video title
        String title = "Tasty Bites";
        // Specify the number of videos to produce.
        int produceCount = 2;

        // Submit tasks.
        List<String> jobIds = new ArrayList<String>();
        for (int i = 0; i < produceCount; i++) {
            String jobId = produceSingleVideo(title, text, videoArray, bgMusicArray);
            jobIds.add(jobId);
        }
        // Query the status of the tasks in a round-robin manner until all tasks are complete.
        System.out.println("waiting job finished...");
        while (true) {
            Thread.sleep(3000);
            boolean allFinished = true;
            for (int i = 0; i < jobIds.size(); i++) {
                String jobId = jobIds.get(i);
                GetMediaProducingJobRequest req = new GetMediaProducingJobRequest();
                req.setJobId(jobId);
                GetMediaProducingJobResponse response = iceClient.getMediaProducingJob(req);
                GetMediaProducingJobResponseBody.GetMediaProducingJobResponseBodyMediaProducingJob mediaProducingJob = response.getBody().getMediaProducingJob();
                String status = mediaProducingJob.getStatus();
                System.out.println("jobId: " + mediaProducingJob.getJobId() + ", status:" + status);
                if ("Failed".equalsIgnoreCase(status)) {
                    System.out.println("jobfailed. jobInfo: " + JSONObject.toJSONString(mediaProducingJob));
                    throw new Exception("Produce failed. jobid: " + mediaProducingJob.getJobId());
                }
                if (!"Success".equalsIgnoreCase(status)) {
                    allFinished = false;
                    break;
                }
            }
            if (allFinished) {
                System.out.println("all job finished.");
                break;
            }
        }
    }

    public String produceSingleVideo(String title, String text, String[] videoArray, String[] bgMusicArray) throws Exception {
        text = text.replace(",", "。");
        text = text.replace("\n", "。");
        String[] sentenceArray = text.split("。");

        JSONArray videoClipArray = new JSONArray();
        JSONArray audioClipArray = new JSONArray();

        List<String> videoList = Arrays.asList(videoArray);
        Collections.shuffle(videoList);

        for (int i = 0; i < sentenceArray.length; i++) {
            String sentence = sentenceArray[i];
            String clipId = "clip" + i;
            String videoUrl = videoList.get(i);
            String videoClip = "{\"MediaURL\":\""+videoUrl+"\",\"ReferenceClipId\":\""+clipId+"\",\"Effects\":[{\"Type\":\"Background\",\"SubType\":\"Blur\",\"Radius\":0.1}]}";
            videoClipArray.add(JSONObject.parseObject(videoClip));
            String audioClip = "{\"Type\":\"AI_TTS\",\"Content\":\"" + sentence + "\",\"Voice\":\"zhichu\",\"ClipId\":\""+clipId+"\",\"Effects\":[{\"Type\":\"AI_ASR\",\"Font\":\"Alibaba PuHuiTi\",\"Alignment\":\"TopCenter\",\"Y\":0.75,\"FontSize\":55,\"FontColor\":\"#ffffff\",\"AdaptMode\":\"AutoWrap\",\"TextWidth\":0.8,\"Outline\":2,\"OutlineColour\":\"#000000\"}]}";
            audioClipArray.add(JSONObject.parseObject(audioClip));
        }

        String subtitleTrack = "{\"SubtitleTrackClips\":[{\"Type\":\"Text\",\"Font\":\"HappyZcool-2016\",\"Content\":\""+title+"\",\"FontSize\":80,\"FontColor\":\"#ffffff\",\"Y\":0.15,\"Alignment\":\"TopCenter\",\"EffectColorStyle\":\"CS0004-000005\",\"FontFace\":{\"Bold\":true,\"Italic\":false,\"Underline\":false}}]}";

        int bgMusicIndex = (int)(Math.random() * bgMusicArray.length);
        String bgMusicUrl = bgMusicArray[bgMusicIndex];
        String timeline = "{\"VideoTracks\":[{\"VideoTrackClips\":"+videoClipArray.toJSONString()+"}],\"AudioTracks\":[{\"AudioTrackClips\":"+audioClipArray.toJSONString()+"},{\"AudioTrackClips\":[{\"MediaURL\":\""+bgMusicUrl+"\"}]}],\"SubtitleTracks\":[" + subtitleTrack + "]}";

        //
        String targetFileName = UUID.randomUUID().toString().replace("-", "");
        String outputMediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/ice_output/" + targetFileName + ".mp4";
        int width = 720;
        int height = 1280;
        String outputMediaConfig = "{\"MediaURL\":\"" + outputMediaUrl + "\",\"Width\":"+width+",\"Height\":"+height+"}";

        SubmitMediaProducingJobRequest request = new SubmitMediaProducingJobRequest();
        request.setTimeline(timeline);
        request.setOutputMediaConfig(outputMediaConfig);
        SubmitMediaProducingJobResponse response = iceClient.submitMediaProducingJob(request);
        System.out.println("start job. jobid: " + response.getBody().getJobId() + ", outputMediaUrl: " + outputMediaUrl);
        return response.getBody().getJobId();
    }

}

Input: Voiceover audio

View sample code

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.*;
import com.aliyun.teaopenapi.models.Config;

import java.util.*;

/**
 *  Add the following dependencies:
 *   <dependency>
 *      <groupId>com.aliyun</groupId>
 *      <artifactId>ice20201109</artifactId>
 *      <version>2.1.0</version>
 *  </dependency>
 *  <dependency>
 *      <groupId>com.alibaba</groupId>
 *      <artifactId>fastjson</artifactId>
 *      <version>1.2.9</version>
 *  </dependency>
 */
public class BatchProduce {

    static final String regionId = "cn-shanghai";
    static final String bucket = "<your-bucket>";
    private Client iceClient;

    public static void main(String[] args) throws Exception {
        BatchProduce batchProduce = new BatchProduce();
        batchProduce.initClient();
        batchProduce.run();
    }

    public void initClient() throws Exception {
        // The AccessKey pair of an Alibaba Cloud account has access permissions on all API operations. We recommend that you use the AccessKey pair of a Resource Access Management (RAM) user to call API operations or perform routine O&M operations. 
        // In this example, the AccessKey ID and AccessKey secret are obtained from the environment variables. For information about how to configure environment variables to store the AccessKey ID and AccessKey secret, visit https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials
        com.aliyun.credentials.Client credentialClient = new com.aliyun.credentials.Client();
        Config config = new Config();
        config.setCredential(credentialClient);

        // To hard-code your AccessKey ID and AccessKey secret, use the following lines. However, we recommend that you do not save the AccessKey ID and AccessKey secret in your project code. Otherwise, the AccessKey pair may be leaked and the security of resources within your account may be compromised.
        // config.accessKeyId = <AccessKey ID created in the second step>;
        // config.accessKeySecret = <AccessKey Secret created in the second step>;
        config.endpoint = "ice." + regionId + ".aliyuncs.com";
        config.regionId = regionId;
        iceClient = new Client(config);
    }

    public void run() throws Exception {

        // Voiceover material
        String inputSpeechAudio = "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/food_speech.mp3";
        // Video material
        String[] videoArray = new String[]{
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f1.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f2.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f3.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f4.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f5.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f6.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f7.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f8.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f9.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f10.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f11.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f12.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f13.mp4",
            "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f14.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f15.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f16.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f17.mp4",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/food/f18.mp4"
        };
        // Background music
        String[] bgMusicArray = new String[]{
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m1.wav",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m2.wav",
                "https://ice-document-materials.oss-cn-shanghai.aliyuncs.com/test_media/music/m3.wav"
        };
        // Video title
        String title = "Tasty Bites";
        // Specify the number of videos to produce.
        int produceCount = 2;

        // Start producing the video.
        // Step 1: Perform ASR on the voiceover audio.
        SubmitASRJobRequest asrJobRequest = new SubmitASRJobRequest();
        asrJobRequest.setInputFile(inputSpeechAudio);
        SubmitASRJobResponse asrJobResponse = iceClient.submitASRJob(asrJobRequest);
        String asrJobId = asrJobResponse.getBody().getJobId();
        String asrResult = null;
        for (int i = 0; i < 10000; i++) {
            Thread.sleep(3000);
            GetSmartHandleJobRequest getSmartHandleJobRequest = new GetSmartHandleJobRequest();
            getSmartHandleJobRequest.setJobId(asrJobId);
            GetSmartHandleJobResponse asrResponse = iceClient.getSmartHandleJob(getSmartHandleJobRequest);
            String jobStatus = asrResponse.getBody().getState();
            System.out.println("asrJobId: " + asrJobId + ", status: " + jobStatus);
            if ("Failed".equalsIgnoreCase(jobStatus)) {
                System.out.println("asr job failed.");
                return;
            }
            if ("Finished".equalsIgnoreCase(jobStatus)) {
                asrResult = asrResponse.getBody().getJobResult().getAiResult();
                break;
            }
        }
        System.out.println("asr job finished. asr result: " + asrResult);

        // Step 2: Submit tasks.
        List<String> jobIds = new ArrayList<String>();
        for (int i = 0; i < produceCount; i++) {
            String jobId = produceSingleVideo(title, inputSpeechAudio, asrResult, videoArray, bgMusicArray);
            jobIds.add(jobId);
        }

        // Step 3: Query the status of the tasks in a round-robin manner until all tasks are complete.
        System.out.println("waiting job finished...");
        while (true) {
            Thread.sleep(3000);
            boolean allFinished = true;
            for (int i = 0; i < jobIds.size(); i++) {
                String jobId = jobIds.get(i);
                GetMediaProducingJobRequest req = new GetMediaProducingJobRequest();
                req.setJobId(jobId);
                GetMediaProducingJobResponse response = iceClient.getMediaProducingJob(req);
                GetMediaProducingJobResponseBody.GetMediaProducingJobResponseBodyMediaProducingJob mediaProducingJob = response.getBody().getMediaProducingJob();
                String status = mediaProducingJob.getStatus();
                System.out.println("jobId: " + mediaProducingJob.getJobId() + ", status:" + status);
                if ("Failed".equalsIgnoreCase(status)) {
                    System.out.println("jobfailed. jobInfo: " + JSONObject.toJSONString(mediaProducingJob));
                    throw new Exception("Produce failed. jobid: " + mediaProducingJob.getJobId());
                }
                if (!"Success".equalsIgnoreCase(status)) {
                    allFinished = false;
                    break;
                }
            }
            if (allFinished) {
                System.out.println("all job finished.");
                break;
            }
        }
    }

    public String produceSingleVideo(String title, String inputSpeechAudio, String asrResult, String[] videoArray, String[] bgMusicArray) throws Exception {
        JSONArray videoClipArray = new JSONArray();
        JSONArray subtitleClipArray = new JSONArray();

        List<String> videoList = Arrays.asList(videoArray);
        Collections.shuffle(videoList);

        JSONArray asrResultArray = JSONArray.parseArray(asrResult);
        for (int i = 0; i < asrResultArray.size(); i++) {
            JSONObject asrItem = asrResultArray.getJSONObject(i);
            String content = asrItem.getString("content");
            float from = asrItem.getFloat("from");
            float to = asrItem.getFloat("to");
            float duration = to - from;
            String videoUrl = videoList.get(i);
            String videoClip = "{\"MediaURL\":\"" + videoUrl + "\",\"Effects\":[{\"Type\":\"Background\",\"SubType\":\"Blur\",\"Radius\":0.1},{\"Type\":\"Clip\",\"SubType\":\"RandomClip\",\"ClipDuration\":" + duration + "}]}";
            videoClipArray.add(JSONObject.parseObject(videoClip));
            String subtitleClip = "{\"Content\":\"" + content + "\",\"TimelineIn\":" + from + ",\"TimelineOut\":" + to + ",\"Type\":\"Text\",\"Font\":\"Alibaba PuHuiTi\",\"Alignment\":\"TopCenter\",\"Y\":0.75,\"FontSize\":55,\"FontColor\":\"#ffffff\",\"AdaptMode\":\"AutoWrap\",\"TextWidth\":0.8,\"Outline\":2,\"OutlineColour\":\"#000000\"}";
            subtitleClipArray.add(JSONObject.parseObject(subtitleClip));
        }

        String titleTrack = "{\"SubtitleTrackClips\":[{\"Type\":\"Text\",\"Font\":\"HappyZcool-2016\",\"Content\":\""+title+"\",\"FontSize\":80,\"FontColor\":\"#ffffff\",\"Y\":0.15,\"Alignment\":\"TopCenter\",\"EffectColorStyle\":\"CS0004-000005\",\"FontFace\":{\"Bold\":true,\"Italic\":false,\"Underline\":false}}]}";
        String subtitleTrack = "{\"SubtitleTrackClips\":"+subtitleClipArray+"}";

        int bgMusicIndex = (int)(Math.random() * bgMusicArray.length);
        String bgMusicUrl = bgMusicArray[bgMusicIndex];
        String timeline = "{\"VideoTracks\":[{\"VideoTrackClips\":"+videoClipArray.toJSONString()+"}],\"AudioTracks\":[{\"AudioTrackClips\":[{\"MediaURL\":\""+inputSpeechAudio+"\"}]},{\"AudioTrackClips\":[{\"MediaURL\":\""+bgMusicUrl+"\"}]}],\"SubtitleTracks\":[" + titleTrack + "," + subtitleTrack + "]}";

        //
        String targetFileName = UUID.randomUUID().toString().replace("-", "");
        String outputMediaUrl = "http://" + bucket + ".oss-" + regionId + ".aliyuncs.com/ice_output/" + targetFileName + ".mp4";
        int width = 720;
        int height = 1280;
        String outputMediaConfig = "{\"MediaURL\":\"" + outputMediaUrl + "\",\"Width\":"+width+",\"Height\":"+height+"}";

        SubmitMediaProducingJobRequest request = new SubmitMediaProducingJobRequest();
        request.setTimeline(timeline);
        request.setOutputMediaConfig(outputMediaConfig);
        SubmitMediaProducingJobResponse response = iceClient.submitMediaProducingJob(request);
        System.out.println("start job. jobid: " + response.getBody().getJobId() + ", outputMediaUrl: " + outputMediaUrl);
        return response.getBody().getJobId();
    }

}

References