设置视频封面

视频上传到视频点播中时,若指定了视频封面则会使用指定的图片作为视频封面,如果不指定,则会自动截取并选择一张视频截图作为视频封面,上传完成后也可以对视频封面进行更新。

概述

上传到视频点播中的每一个视频都存在视频封面。

上传视频时,如果指定了视频封面,则视频上传完成后,会使用您指定的图片作为视频封面;若上传时未指定视频封面,则点播会默认对上传的视频进行视频截图,截取1~8张图,并选取中间的一张截图作为视频封面,更多信息,请参见视频截图。视频上传完成之后,也可以对视频封面进行更新。

视频点播支持设置普通封面和智能封面。其中,智能封面需要单独申请开通,更多信息,请参见智能封面产品页

  • 普通封面:人为的自定义指定视频封面。封面图来源于本地图片或视频截图或任意可访问的链接地址(支持静态图片封面、动图封面、视频封面等形式)。

  • 智能封面:系统通过对视频内容的理解,结合画面美学分析,选出最优的关键帧或关键片段作为视频封面。封面图来源于视频本身,支持提取静态图片封面、动图封面两种形式。

使用场景

支持设置的封面类型

支持的设置方式

相关文档

上传视频时设置封面

普通封面

OpenAPI

上传视频时设置封面

视频上传后更新封面

普通封面

  • 控制台

  • OpenAPI

视频上传后更新封面

智能封面

OpenAPI

前提条件

  • 已经开通了视频点播服务。开通步骤请参见开通视频点播

  • 为了您的账号和资源的安全,建议您使用RAM用户或RAM角色进行操作,并请确保RAM用户或RAM角色已授予视频点播的相关权限。具体操作,请参见创建RAM用户并授权

  • 如果您已经配置了视频点播的加速域名,则该域名需要配置证书后,才能设置封面。具体操作,请参见HTTPS安全加速设置

上传视频时设置封面

视频点播提供了多种上传视频的方式,详细信息,请参见上传方式。其中,仅开发上传方式即通过API/SDK方式上传视频时,支持指定视频封面上传。具体设置如下:

重要

CoverURL支持设置任意地址,视频点播不对该地址作处理,仅保存该地址,在用户请求时返回,您需要自行保证该CoverURL是否可以访问。

视频上传后更新封面

当视频上传到视频点播之后,可以通过下述方式更新视频封面。

设置普通封面

控制台方式

当视频上传到视频点播之后,可以直接在视频点播控制台更新视频封面。支持设置本地图片和视频截图为视频封面。

  1. 登录视频点播控制台

  2. 在左侧导航栏选择媒资库 > 音/视频,进入到音视频列表页面。

  3. 选择需要更新封面的视频,单击管理

  4. 基础信息页签,单击编辑视频信息

    • 可以从自动截取的多张视频截图里选一张作为视频封面。

    • 也可以单击上传封面,选择一张本地图片作为视频封面。

      说明

      上传封面的图片仅支持JPG、PNG格式,最大1 MB,像素不超过1920Px × 1080Px。

      设置智能封面2
  5. 单击保存,完成配置。

    完成配置后,可以返回音视频列表页面查看视频封面是否已经更新成功。

OpenAPI方式

当视频上传到视频点播之后,可以调用下述接口更新视频封面。支持设置任意可访问的地址为视频封面。

重要

CoverURL支持设置任意地址,视频点播不对该地址作处理,仅保存该地址,在用户请求时返回,您需要自行保证该CoverURL是否可以访问。

设置智能封面

视频智能封面,是通过对视频内容的理解,结合画面美学和海量生产数据,选出最优的关键帧或关键片段作为视频封面,提升视频点击转化及用户体验。

说明

视频点播现仅支持封面图片和封面动图,暂不支持封面视频。

案例演示-设置视频首帧截图为视频封面

配置流程

  1. 创建截取视频首帧的截图模板。

  2. 发起截取视频首帧的截图任务。

  3. 修改视频封面为视频首帧截图。

配置方法

控制台方式配置

  1. 创建截取视频首帧的截图模板。

    1. 登录视频点播控制台

    2. 在左侧导航栏选择配置管理 > 媒体处理配置 > 截图模板,进入到截图模板页面。

    3. 单击添加截图模板,配置截取视频首帧截图的模板参数。

      模板名称请自定义设置,截图方式选择普通截图起始时间点设置为00:00:00,截图数量设置为1,其余参数请按需配置,有关截图模板的参数解释,详情请参见截图模板首帧截图1.png

    4. 单击保存,完成截图模板的创建。

  2. 发起截取视频首帧的截图任务。

    说明
    • 通过控制台方式发起截图任务时,只能通过工作流的方式发起,因此,您需要先创建一个包含视频首帧截图任务的工作流(即在工作流中添加视频截图节点,并设置截图模板为上一步创建的首帧截图模板)。工作流的创建方法,请参见工作流管理

    • 建议您发起截图任务之前,配置视频点播的事件通知,通过设置视频截图完成的事件通知,以便在截图任务完成后,能获取到截图任务的状态及截取的图片地址等信息。事件通知的配置方法,请参见回调设置

    • 场景一:上传视频时截图

      1. 在视频点播控制台,从左侧导航栏选择媒资库 > 音/视频

      2. 单击上传音/视频,单击添加音/视频

      3. 按需设置上传方式、存储地址并添加上传的视频后,选择用工作流处理,并选择预先创建的包含首帧截图任务的工作流。

      4. 单击开始上传

    • 场景二:上传视频后截图

      1. 在视频点播控制台,从左侧导航栏选择媒资库 > 音/视频

      2. 在音/视频列表页面,单击目标视频所在行的媒体处理

      3. 处理类型选择用工作流处理工作流选择预先创建的包含首帧截图任务的工作流。

      4. 单击确定

    • 获取截图结果

      • 如果您已经配置了视频点播的视频截图完成的事件通知,您可以从回调事件中获取到截图任务的状态及截取的图片地址等信息。

      • 如果您未配置事件通知,您可以使用轮询的方式调用ListSnapshots - 查询截图数据接口来查询截图任务的状态及截取的图片地址等信息。

  3. 修改视频封面为视频首帧截图。

    说明

    通过控制台方式修改视频封面,只支持在视频上传完成后对视频封面进行更新。您需要先将步骤2中截图任务截取到的视频首帧截图保存到本地以便修改封面时上传。

    1. 在视频点播控制台,从左侧导航栏选择媒资库 > 音/视频

    2. 在音/视频列表页面,单击目标视频所在行的管理

    3. 基础信息页签,单击编辑视频信息

    4. 单击上传封面,选择预先保存到本地的视频首帧截图,单击打开

    5. 单击保存,完成视频封面设置。

      设置完成后,您可以在音/视频列表页面查看视频封面是否更新成功。

OpenAPI方式配置

说明

本文以使用Java语言的阿里云 SDK方式调用视频点播的OpenAPI为例进行举例说明。

操作步骤

  1. 创建截取视频首帧的截图模板。

    调用AddVodTemplate - 添加截图模板接口,创建截取视频首帧的截图模板。调用示例如下:

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.AddVodTemplateRequest;
    import com.aliyuncs.vod.model.v20170321.AddVodTemplateResponse;
    
    
    /**
     * 说明:
     * 1. 本Demo为创建首帧截图模板示例,截图输出为 1 张图片。
     * 2. 推荐使用视频点播控制台创建截图模板,更加方便快捷。
     */
    public class AddSnapshotTemplate {
    
        // 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
        // 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
        // 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。运行代码示例前,请配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                AddVodTemplateResponse response = addSnapshotTemplate(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
                System.out.println("TemplateId is:" + response.getVodTemplateId());
            }catch (Exception e){
    
            }
        }
    
        public static AddVodTemplateResponse addSnapshotTemplate(DefaultAcsClient vodClient) throws ClientException {
            AddVodTemplateRequest request = new AddVodTemplateRequest();
            request.setName("首帧截图模板");
            request.setTemplateType("Snapshot");
            request.setTemplateConfig("{\"SnapshotType\":\"NormalSnapshot\",\"SnapshotConfig\":{\"FrameType\":\"normal\",\"Count\":1,\"Interval\":1,\"SpecifiedOffsetTime\":0}}");
    
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 点播服务接入区域
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
    
            return client;
        }
    }
    
  2. 发起截取视频首帧的截图任务。

    调用SubmitSnapshotJob - 提交媒体截图作业接口,发起截图任务。调用示例如下:

    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.*;
    
    /**
     * 说明:
     * 1. 本Demo为创建首帧截图模板后,提交首帧截图任务。
     * 2. 对于新上传的视频,建议该步骤放在【音视频分析完成】事件成功之后,对于存量且状态正常的视频,可自行设计。
     * 3. 截图为异步任务,需要等到【视频截图完成】事件成功之后(推荐),可获取截图地址。
     * 4. 根据回调事件中的SnapshotRegular,可推测出截图输出地址。详情请参见【视频截图完成】文档中的截图地址生成规则说明。
     * 5. 若您暂无回调服务,也可以通过ListSnapshots接口主动查询,该接口默认只返回最新一次的截图结果。详情请参见ListSnapshots接口文档。
     */
    public class SubmitSnapshotJob {
    
        // 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
        // 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
        // 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。运行代码示例前,请配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                SubmitSnapshotJobResponse response = submitSnapshotJob(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
                System.out.println("JobId is:" + response.getSnapshotJob().getJobId());
            }catch (Exception e){
    
            }
        }
    
        public static SubmitSnapshotJobResponse submitSnapshotJob(DefaultAcsClient vodClient) throws ClientException {
            SubmitSnapshotJobRequest request = new SubmitSnapshotJobRequest();
            request.setVideoId("a42b**********633b79f0102");
            request.setSnapshotTemplateId("1f27a7**********eba2756");
            //自定义透传参数,回调时可用,非必须,用于区分封面首帧截图
            request.setUserData("{\"Extend\":{\"SnapshotType\":\"FirstFrame\",\"VideoId\":\"a42bf540********33b79f0102\"}}");
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 点播服务接入区域
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
    
            return client;
        }
    
        //ListSnapshots 查询截图
        public static ListSnapshotsResponse listSnapshots(DefaultAcsClient vodClient) throws ClientException {
            ListSnapshotsRequest request = new ListSnapshotsRequest();
            request.setVideoId("a42bf540b1b371ed804a6633b79****");
            request.setSnapshotType("NormalSnapshot");
    
            ListSnapshotsResponse response = vodClient.getAcsResponse(request);
            System.out.println("RequestId is:" + response.getRequestId());
            System.out.println("SnapshotUrl is:" + response.getMediaSnapshot().getSnapshots().get(0).getUrl());
            return vodClient.getAcsResponse(request);
        }
    
    }
    
  3. 修改视频封面为视频首帧截图。

    此处以视频上传完成后,修改单个视频封面的场景为例进行说明,其他场景的实现,请参见上传视频时设置封面视频上传后更新封面

    通过调用UpdateVideoInfo - 修改单个音视频信息接口,传入CoverURL参数指定视频封面。调用示例如下:

    package com.alibaba.bltest.transcode;
    
    import com.aliyuncs.DefaultAcsClient;
    import com.aliyuncs.exceptions.ClientException;
    import com.aliyuncs.profile.DefaultProfile;
    import com.aliyuncs.vod.model.v20170321.UpdateVideoInfoRequest;
    import com.aliyuncs.vod.model.v20170321.UpdateVideoInfoResponse;
    
    /**
     * 说明:
     * 1. 本Demo为修改单个视频封面,如需修改其他视频参数,请参见UpdateVideoInfo的接口文档。
     * 2. 对于修改封面的场景,请确保您使用的图片地址是有效的。
     */
    public class UpdateVideoInfo {
    
        // 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
        // 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
        // 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。运行代码示例前,请配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
        public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        public static void main(String[] args) {
    
            try{
                DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
                UpdateVideoInfoResponse response = updateVideoInfo(vodClient);
                System.out.println("RequestId is:" + response.getRequestId());
            }catch (Exception e){
    
            }
        }
    
        public static UpdateVideoInfoResponse updateVideoInfo(DefaultAcsClient vodClient) throws ClientException {
            UpdateVideoInfoRequest request = new UpdateVideoInfoRequest();
            request.setVideoId("a42b***********33b79f0102");
            //设置首帧封面时,CoverURL为首帧截图任务成功后输出的图片地址
            request.setCoverURL("http://demo.aliyuncdn.com/a42bf5******40b1b37/snapshots/normal/41B7AF54-18672BB301D-1748-0984-309-112420****.jpg");
    
            return vodClient.getAcsResponse(request);
        }
    
        public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
            // 点播服务接入区域
            String regionId = "cn-shanghai";  
            DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
            DefaultAcsClient client = new DefaultAcsClient(profile);
            return client;
        }
    }
    

完整实例

package com.alibaba.bltest.transcode;


import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.*;
import org.apache.commons.lang3.StringUtils;

/**
 * 说明:
 * 1. 本Demo为完整截图+修改封面逻辑设计,部分代码需要根据自己业务逻辑自行修改。
 * 2. 本Demo非直接可用,部分逻辑需要自行补充。
 * 3. 本Demo仅供实现参考,不代表唯一实现方式。
 */
public class SnapshotAndUpdateCover {

    // 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
    // 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
    // 本示例通过从环境变量中读取AccessKey,来实现API访问的身份验证。运行代码示例前,请配置环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
    public static String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
    public static String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");

    public static void main(String[] args) {


        try{
            DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);
            //视频ID
            String videoId = "a42bf540b1b37*******b79f0102";

            //场景一:有回调服务 或 MNS
            //若是为新上传的视频设置封面,则需要先获取到音视频分析成功事件
            //若是为存量视频设置封面,则可以直接从此步骤开始提交截图任务
            submitSnapshotJob(vodClient,videoId);

            //获取到视频截图成功事件,判断截图类型,取得需要的图片URL
            JSONObject callBackMessage = new JSONObject();  //此处替换为回调服务收到的message
            String snapshotType = callBackMessage.getJSONObject("UserData").getJSONObject("Extend").getString("SnapshotType");
            if("FirstFrame".equals(snapshotType)){

                //这里的截图路径逻辑需要根据您自行定义的截图路径逻辑来替换
                String coverUrl = callBackMessage.getJSONArray("SnapshotInfos").getJSONObject(0).getString("SnapshotRegular").replace("{SnapshotCount}","00001");
                //修改视频封面
                updateVideoInfo(vodClient,videoId,coverUrl);
            }

            //场景二:无回调服务 或 MNS
            //若是为新上传的视频设置封面,则视频上传后,轮询视频状态
            String videoStatus = "";
            while(!"Normal".equals(videoStatus)){
                videoStatus = getVideoInfo(vodClient,videoId);
                Thread.sleep(1000);
            }

            //若是为存量视频设置封面,则可以直接从此步骤开始提交截图任务
            submitSnapshotJob(vodClient,videoId);

            //轮询截图结果
            String coverUrl = "";
            while(StringUtils.isBlank(coverUrl)){
                coverUrl = listSnapshots(vodClient,videoId);
                Thread.sleep(1000);
            }

            //修改视频封面
            updateVideoInfo(vodClient,videoId,coverUrl);
        }catch (Exception e){

        }
    }

    /**
     * 提交截图任务
     */
    public static SubmitSnapshotJobResponse submitSnapshotJob(DefaultAcsClient vodClient, String vid) throws ClientException {
        SubmitSnapshotJobRequest request = new SubmitSnapshotJobRequest();
        request.setVideoId(vid);
        request.setSnapshotTemplateId("1f27a7f*********70eba2756");
        //自定义透传参数,回调时可用,非必须,用于区分封面首帧截图
        request.setUserData("{\"Extend\":{\"SnapshotType\":\"FirstFrame\",\"VideoId\":\"a42bf540********33b79f0102\"}}");

        return vodClient.getAcsResponse(request);
    }

    /**
     * 修改视频封面
     */
    public static UpdateVideoInfoResponse updateVideoInfo(DefaultAcsClient vodClient, String vid, String coverUrl) throws ClientException {
        UpdateVideoInfoRequest request = new UpdateVideoInfoRequest();
        request.setVideoId(vid);
        //设置首帧封面时,CoverURL为首帧截图任务成功后输出的图片地址
        request.setCoverURL(coverUrl);

        return vodClient.getAcsResponse(request);
    }

    /**
     * 初始化sdk实例
     */
    public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {
        // 点播服务接入区域
        String regionId = "cn-shanghai";  
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
        DefaultAcsClient client = new DefaultAcsClient(profile);

        return client;
    }

    /**
     * 查询截图
     */
    public static String listSnapshots(DefaultAcsClient vodClient, String vid) throws ClientException {
        ListSnapshotsRequest request = new ListSnapshotsRequest();
        request.setVideoId(vid);
        request.setSnapshotType("NormalSnapshot");

        ListSnapshotsResponse response = vodClient.getAcsResponse(request);
        String coverUrl = "";
        System.out.println("RequestId is:" + response.getRequestId());
        try{
            coverUrl = response.getMediaSnapshot().getSnapshots().get(0).getUrl();
            System.out.println("SnapshotUrl is:" + response.getMediaSnapshot().getSnapshots().get(0).getUrl());
        }catch (NullPointerException e){

        }
        return coverUrl;
    }

    /**
     * 查询单个视频
     */
    public static String getVideoInfo(DefaultAcsClient vodClient, String vid) throws ClientException {
        GetVideoInfoRequest request = new GetVideoInfoRequest();
        request.setVideoId(vid);

        GetVideoInfoResponse response = vodClient.getAcsResponse(request);
        System.out.println("RequestId is:" + response.getRequestId());
        String videoStatus = "";
        try{
            videoStatus = response.getVideo().getStatus();
            System.out.println("Video Status is:" + response.getVideo().getStatus());
        }catch (NullPointerException e){

        }

        return videoStatus;
    }
}