短视频批量混剪-制作卡点相册

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 随着短视频生态的发展,视频生产的质量和效率已经越来越重要,本篇介绍如何用一段音乐和多张图片,快速自动生成一段卡点相册视频。

随着短视频生态的发展,视频生产的质量和效率已经越来越重要,本篇介绍如何用一段音乐和多张图片,快速自动生成一段卡点相册视频。

概述

背景

卡点视频是短视频生产中常用的效果,将素材的开始结束时间卡在音乐的节奏点上,能够带动观众的感官和气氛。本篇介绍如何用一段音乐和多张图片,快速自动生成一段卡点相册视频。

本文基于智能媒体服务IMS,用户通过组装Timeline,即可对云端的音视频素材进行剪辑,最后附有示例代码,帮助大家更快速上手。

目标读者

有短视频批量制作的商家,或视频批量生产工具的开发者。

方案介绍

先来看成片示例

生产此视频的素材是一段音乐和一批图片。

整体流程:整体流程 1、调用智能生产接口识别音乐的节奏点信息。

2、根据节奏点信息封装Timeline。

3、调用剪辑合成接口,传入Timeline,合成最终成片。

其中,Timeline格式参考Timeline配置说明,根据音乐节奏点信息,可以很方便的生成Timeline:节奏转timeline

如果要为图片添加转场,需要为每张图片的时长加上转场时长:timeline加转场

本文示例中还为图片增加了背景模糊效果,具体见代码示例。

还可以为视频增加字幕、贴图、特效,可参考短视频常用功能

方案实施

接口说明

提供文字转语音、人声识别、节奏检测等能力

输入Timeline和成片地址,提交剪辑合成作业,返回剪辑作业JobId

示例代码

package com.aliyun.ice.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.ice20201109.Client;
import com.aliyun.ice20201109.models.GetMediaProducingJobRequest;
import com.aliyun.ice20201109.models.GetMediaProducingJobResponse;
import com.aliyun.ice20201109.models.SubmitMediaProducingJobRequest;
import com.aliyun.ice20201109.models.SubmitMediaProducingJobResponse;
import com.aliyun.mts20140618.models.QueryIProductionJobRequest;
import com.aliyun.mts20140618.models.QueryIProductionJobResponse;
import com.aliyun.mts20140618.models.SubmitIProductionJobRequest;
import com.aliyun.mts20140618.models.SubmitIProductionJobResponse;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.teaopenapi.models.Config;
import com.google.common.io.CharStreams;
import org.apache.commons.io.Charsets;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Create by oushu
 * Date 2022/07/11 上午11:57
 */
public class BatchProduceBeatMusicRelease {

    private String accessKeyId;
    private String accessKeySecret;
    private String bucket;
    private String regionId;
    private OSS ossClient;
    private Client iceClient;
    private com.aliyun.mts20140618.Client mpsClient;

    public void initClient() throws Exception {
        accessKeyId = "your ak";
        accessKeySecret = "your sk";
        bucket = "your-bucket";
        regionId = "cn-shanghai";
        iceClient = createIceClient();
        ossClient = createOssClient();
        mpsClient = createMpsClient();
    }

    public static void main(String[] args) throws Exception {
        BatchProduceBeatMusicRelease batchProduceVideo = new BatchProduceBeatMusicRelease();
        batchProduceVideo.initClient();
        batchProduceVideo.batchProduceVideo();
    }

    public void batchProduceVideo() throws Exception {
        String musicUrl = "https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-music.mp3";

        List<String> mediaUrls = new ArrayList();
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-image1.jpg");
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-image2.jpg");
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-image3.jpg");
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-movie1.mp4");
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-movie2.mp4");
        mediaUrls.add("https://your-bucket.oss-cn-shanghai.aliyuncs.com/your-movie3.mp4");

        int targetCount = 1;
        for (int i = 0; i < targetCount; i++) {
            Collections.shuffle(mediaUrls);
            List<String> subImageUrls = mediaUrls.subList(0, 15);
            produceSingleVideo(musicUrl, subImageUrls);
        }
    }


    public void produceSingleVideo(String musicUrl, List<String> imageUrls) throws Exception {
        System.out.println("Start produce!!!!");

        // 提交节奏检测任务
        String input = musicUrl;
        SubmitIProductionJobRequest submitIProductionJobRequest = new SubmitIProductionJobRequest();
        submitIProductionJobRequest.setFunctionName("AudioBeatDetection");
        submitIProductionJobRequest.setInput(input);
        submitIProductionJobRequest.setOutput("oss://" + bucket + ".oss-" + regionId + ".aliyuncs.com/iproduction/{source}-{timestamp}.txt");
        SubmitIProductionJobResponse submitIProductionJobResponse = mpsClient.submitIProductionJob(submitIProductionJobRequest);
        // 等待任务完成
        String jobId = submitIProductionJobResponse.body.jobId;
        String result;
        while (true) {
            QueryIProductionJobRequest queryIProductionJobRequest = new QueryIProductionJobRequest();
            queryIProductionJobRequest.setJobId(jobId);
            QueryIProductionJobResponse queryIProductionJobResponse = mpsClient.queryIProductionJob(queryIProductionJobRequest);
            System.out.println("IProductionJob Info : " + JSONObject.toJSONString(queryIProductionJobResponse.body));
            if ("Success".equals(queryIProductionJobResponse.body.state)) {
                result = queryIProductionJobResponse.body.result;
                break;
            }
            Thread.sleep(5000);
        }

        // 获取节奏检测任务结果
        String file = JSONObject.parseObject(JSONObject.parseObject(result).getString("Data")).getJSONArray("result").getJSONObject(0).getString("file");
        System.out.println("result file : " + file);
        String resultContent = getObjectContent(file);
        System.out.println("result content : " + resultContent);
        JSONArray beatList = JSONObject.parseObject(resultContent).getJSONArray("BeatList");
        // 封装时间线
        JSONArray videoTrackClips = new JSONArray();
        float transitionDur = 0.3f;
        float lastBeat = 0;
        for (int i = 0; i < imageUrls.size(); i++) {
            float beat = Float.parseFloat(beatList.getString(i));
            float beatDuration = beat - lastBeat;

            float duration = beatDuration;
            String url = imageUrls.get(i);
            JSONObject clip = new JSONObject();
            clip.put("MediaURL", url);
            if (beatDuration > transitionDur) {
                clip.put("Effects", JSONArray.parse("[{\"Type\": \"Transition\",\"SubType\": \"linearblur\",\"Duration\": " + transitionDur + "},{\"Type\":\"Background\",\"SubType\":\"Blur\"}]"));
                duration += transitionDur;
            } else {
                clip.put("Effects", JSONArray.parse("[{\"Type\":\"Background\",\"SubType\":\"Blur\"}]"));
            }
            if (url.endsWith(".jpg")) {
                clip.put("Duration", duration);
                clip.put("Type", "Image");
            } else {
                clip.put("Out", duration);
            }
            videoTrackClips.add(clip);
            lastBeat = beat;
        }

        String timeline = "{\"VideoTracks\":[{\"VideoTrackClips\":" + videoTrackClips.toJSONString() + "}]," +
                "\"AudioTracks\":[{\"AudioTrackClips\":[{\"MediaURL\":\"" + musicUrl + "\"}]}]," +
                "}";
        System.out.println("timeline : " + timeline);

        // 提交合成任务
        SubmitMediaProducingJobRequest submitMediaProducingJobRequest = new SubmitMediaProducingJobRequest();
        submitMediaProducingJobRequest.setTimeline(timeline);
        String outputPath = IceUtil.getRandomOutputPath();
        String mediaURL = "https://" + bucket + ".oss-" + regionId + ".aliyuncs.com/" + outputPath + ".mp4";
        submitMediaProducingJobRequest.setOutputMediaConfig("{\"MediaURL\":\"" + mediaURL + "\",\"Width\":720,\"Height\":1280}");
        Client iceClient = TestClientInstance.getInstance().getIceClient();
        SubmitMediaProducingJobResponse submitMediaProducingJobResponse = iceClient.submitMediaProducingJob(submitMediaProducingJobRequest);
        System.out.println("job created, jobId : " + submitMediaProducingJobResponse.body.jobId + ", requestId : " + submitMediaProducingJobResponse.body.getRequestId() + ", mediaURL : " + mediaURL);
        // 等待合成任务完成
        while (true) {
            GetMediaProducingJobRequest getMediaProducingJobRequest = new GetMediaProducingJobRequest();
            getMediaProducingJobRequest.setJobId(submitMediaProducingJobResponse.body.jobId);
            GetMediaProducingJobResponse getMediaProducingJobResponse = iceClient.getMediaProducingJob(getMediaProducingJobRequest);
            System.out.println("GetMediaProducingJobResponse : " + JSONObject.toJSONString(getMediaProducingJobResponse.body));
            String status = getMediaProducingJobResponse.getBody().getMediaProducingJob().getStatus();
            if ("Success".equals(status)) {
                break;
            }
            Thread.sleep(5000);
        }
        System.out.println("Produce succeed : " + mediaURL);
    }

    public com.aliyun.mts20140618.Client createMpsClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "mts." + regionId + ".aliyuncs.com";
        return new com.aliyun.mts20140618.Client(config);
    }

    public OSS createOssClient() throws Exception {
        String endpoint = "http://oss-" + regionId + ".aliyuncs.com";
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        return ossClient;
    }

    public String getObjectContent(String object) throws Exception {
        OSSObject obj = ossClient.getObject(bucket, object);
        InputStream stream = obj.getObjectContent();
        String result = CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
        ossClient.shutdown();
        return result;
    }

    public Client createIceClient() throws Exception {
        Config config = new Config()
                .setAccessKeyId(accessKeyId)
                .setAccessKeySecret(accessKeySecret);
        config.endpoint = "ice." + regionId + ".aliyuncs.com";
        return new Client(config);
    }
}

欢迎访问官方文档查看更多示例:

欢迎加入智能媒体生产ICE官方答疑群咨询交流。二维码

相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
目录
相关文章
批量生成海报 以及二维码
批量生成海报 以及二维码
免费制作属于自己的红包封面!附封面设计图下载
最近大家似乎对稀奇好看的红包封面已经见怪不怪了,很多人还每天到处找那些大企业发出来的红包封面。
177 0
|
7月前
|
存储 JSON 5G
短视频批量制作-常用功能
越来越多的产品选择使用短视频作为内容承载,通过对媒体素材进行简单的剪辑,即可进行使用和投放,本文基于智能媒体服务IMS,介绍短视频剪辑中的常用功能,通过对不同功能的组合,方便客户组装自己的剪辑场景,进行短视频批量合成。
234 0
短视频批量制作-常用功能
|
JavaScript 小程序 前端开发
微信小程序生成海报图片导出相册
小程序内通过静态模板和样式绘制 canvas ,导出图片,可用于生成分享图等场景
605 1
微信小程序生成海报图片导出相册
微博相册图片获取工具
下载微博相册,配合aria2工具,备份至阿里云盘
177 0
微博相册图片获取工具
|
存储 编解码
短视频app制作,做好音视频编码很重要
短视频app制作,做好音视频编码很重要
|
数据安全/隐私保护
哪里能找到免费的高清视频素材库?
作为一个剪辑人,素材真的是每天准备视频内容的一大问题。没有办法自己去拍摄,想直接在网上用素材,不是版权问题 就是带水印,或者画面太糊,每天最苦恼的就是找素材
323 0
哪里能找到免费的高清视频素材库?
|
前端开发 JavaScript PHP
jscanvas合成图片实现微信公众号海报功能
jscanvas合成图片实现微信公众号海报功能
171 0
|
存储 对象存储
利用阿里云智能媒体服务制作视频字幕
智能媒体服务IMS(Intelligent Media Services)生产制作中心支持多轨剪切拼接、混音、字幕、图片叠加、遮标、转场特效、智能字幕、绿幕抠图等一系列功能,本文主要介绍如何如何利用智能媒体服务制作视频字幕。
智能相册学习笔记
5天训练营打卡day3
249 0