播单型导播台API应用实战

本文介绍通过调用播单型导播台API实现直播场景。超快捷聚合多个点播视频,创建播单型导播台类型直播间,帮助各合作伙伴丰富其视频场景和内容形态,解决直播场次不固定、内容少、用户不稳定的问题。同时可实时或定时自动插入广告,促进商业变现。

方案概览

image

使用播单型导播台API实现直播场景大致分为4步,如下:

  1. 启用点播系统Bucket:开通视频点播服务后,不同的服务地域会默认分配一个独立的存储Bucket(类型为点播系统Bucket),通过启用该Bucket,无需其他配置即可进行上传和媒体资源管理。

  2. 上传音视频文件:将需要进行直播的视频文件(例如A、B、C三个视频文件)按照顺序依次上传至视频点播(VOD)控制台存储。

  3. 添加播流域名:观众端用于观看直播的地址。观众可以通过播放地址来观看直播内容。

  4. 调用API完成播单型导播台配置:通过调用播单型导播台API,对单个视频的播放次数和播单循环次数分别进行配置。例如文件A播放一遍,文件B播放两遍,文件C播放三遍。配置完成,查询整个节目单播放列表信息并开启播放。

前提条件

  • 您已注册阿里云账号并完成账号实名认证。

  • 依次开通视频点播服务、视频直播服务、云导播服务。具体操作,请参见开通视频点播开通与购买视频直播开通云导播服务

    说明

    目前导播台仅在上海(华东2)、北京(华北2)、亚太东南1(新加坡)、印度尼西亚(雅加达)中心开放,后续将会扩展至其他中心。

  • 已准备好播流域名。为了快速体验,建议直播中心选择海外且加速区域采用海外及港澳台加速,此时域名无需备案。

  • 已添加AliyunFCFullAccessAliyunLiveFullAccessAliyunVODFullAccess系统权限策略。具体操作,请参见创建RAM用户并授权

1.启用点播系统Bucket

视频点播控制台配置管理 > 媒资管理配置 > 存储管理页面中,单击点播系统Bucket所在行的启用

说明

启用存储地址需要一段时间,请您耐心等待。当系统提示存储地址启用成功,且存储地址的状态为正常后,方可使用该存储地址。

image

2.上传音视频文件

  1. 在点播控制台的媒资库 > 音/视频页面,单击上传音/视频

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

    image

  3. 添加音/视频弹框中,选择本地上传,将本地准备好的三个视频文件依次上传,单击开始上传

    image

  4. 成功后,可在音/视频页面查看并记录资源ID。然后单击操作列的更多 > 用于直播导播,播放内容可以实时在视频直播的导播台中关联显示。导播台功能说明,请参见功能区介绍

    image

3.添加播流域名

  1. 视频直播控制台推/播流域名管理 页面中,单击添加域名

  2. 根据实际需求配置域名详情。单击下一步。配置参数的具体说明请参见添加加速域名

    image

  3. 记录生成的CNAME记录值,供下一步使用。

    image

  4. 云解析DNS控制台域名解析页面,单击待设置的域名操作列的解析设置

  5. 单击添加记录,完成CNAME配置,单击确认。更多详细信息,请参见配置域名的CNAME解析

    image

4.调用API完成播单型导播台配置

  1. 打开Intellij IDEA创建Maven项目,在pom.xml中新建 <dependencies></dependencies>标签,并添加如下依赖。

     <dependency>
        <groupId>com.aliyun</groupId>
        <artifactId>live20161101</artifactId>
        <version>2.0.0</version>
     </dependency>
     <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.76</version>
     </dependency>
    
  2. 在项目src/main/java目录下,右键单击java,创建Java类。例如命名为bodan。

  3. 配置如下示例代码相关参数并运行。

    package com.alibaba.aliyundebug.common;
    
    import com.alibaba.fastjson.JSON;
    import com.alibaba.fastjson.JSONArray;
    import com.alibaba.fastjson.JSONObject;
    import com.aliyun.live20161101.Client;
    import com.aliyun.live20161101.models.*;
    import com.aliyun.teaopenapi.models.Config;
    import org.apache.commons.codec.digest.DigestUtils;
    
    import java.util.List;
    import java.util.Random;
    import java.util.UUID;
    
    public class Bodan {
        private final static String ACCESS_KEY_ID = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        private final static String ACCESS_KEY_SECRET = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
    
        private static class LiveClient {
            private static volatile Client instance;
    
            private LiveClient() {
            }
    
            public static Client getInstance(String endpoint, String accessKeyId, String accessKeySecret) {
                if (instance == null) {
                    synchronized (LiveClient.class) {
                        if (instance == null) {
                            try {
                                Config config = new Config();
                                config.setEndpoint(endpoint);
                                config.setAccessKeyId(accessKeyId);
                                config.setAccessKeySecret(accessKeySecret);
                                instance = new Client(config);
                            } catch (Exception e) {
                                throw new RuntimeException("Live client initialization failed: " + e.getMessage(), e);
                            }
                        }
                    }
                }
                return instance;
            }
        }
    
        private static CreateCasterResponse createCaster(Client client) throws Exception {
            CreateCasterRequest request = new CreateCasterRequest();
    
            Random random = new Random();
            int i = random.nextInt(100000);
            request.setCasterName("casterName" + i);
    
            UUID uuid = UUID.randomUUID();
            String token = "thisIsaToken";
            String clientToken = DigestUtils.sha256Hex(token + uuid);
            request.setClientToken(clientToken);
    
            // 节目单可以只用创建播单型即可。
            request.setNormType(6);
            request.setChargeType("PostPaid");
    
            CreateCasterResponse response = client.createCaster(request);
    
            System.out.println("创建导播台成功,返回值: " + JSON.toJSONString(response));
            return response;
        }
    
        private static void setCasterConfig(Client client, String casterId,String domainName) throws Exception {
            SetCasterConfigRequest request = new SetCasterConfigRequest();
            request.setCasterId(casterId);
    
            // 配置域名
            request.setDomainName(domainName);
            JSONObject transcodeConfig = new JSONObject();
            JSONArray liveTemplate = new JSONArray();
            //配置导播台模板
            liveTemplate.add("lld");
            transcodeConfig.put("LiveTemplate", liveTemplate);
            //配置转码模板
            transcodeConfig.put("CasterTemplate", "lp_sd");
            request.setTranscodeConfig(transcodeConfig.toJSONString());
    
            SetCasterConfigResponse response = client.setCasterConfig(request);
            System.out.println("添加导播台配置成功:response: " + JSON.toJSONString(response));
        }
    
        private static StartCasterResponse startCaster(Client client, String casterId) throws Exception {
            StartCasterRequest startCasterRequest = new StartCasterRequest();
            startCasterRequest.setCasterId(casterId);
            StartCasterResponse acsResponse = client.startCaster(startCasterRequest);
            System.out.println("开启导播台成功");
            return acsResponse;
        }
    
        private static StopCasterResponse stopCaster(Client client, String casterId) throws Exception {
            StopCasterRequest stopCasterRequest = new StopCasterRequest();
            stopCasterRequest.setCasterId(casterId);
            StopCasterResponse acsResponse = client.stopCaster(stopCasterRequest);
            System.out.println("停止导播台成功");
            return acsResponse;
        }
    
        private static AddShowIntoShowListResponse addShowIntoShowList(Client client, String showName, String resourceId, String resourceUrl,
                                                                       String resourceType, Integer spot, Integer repeatTimes,
                                                                       String casterId, Long duration) throws Exception {
            AddShowIntoShowListRequest addShowIntoShowListRequest = new AddShowIntoShowListRequest();
    
            if (casterId == null || resourceType == null) {
                return null;
            }
            if (resourceId == null && resourceUrl == null) {
                return null;
            }
            addShowIntoShowListRequest.setCasterId(casterId);
            addShowIntoShowListRequest.setResourceType(resourceType);
            if (showName != null) {
                addShowIntoShowListRequest.setShowName(showName);
            }
            if (resourceUrl != null) {
                addShowIntoShowListRequest.setResourceUrl(resourceUrl);
            }
            if (resourceId != null) {
                addShowIntoShowListRequest.setResourceId(resourceId);
            }
            if (spot != null) {
                addShowIntoShowListRequest.setSpot(spot);
            }
            if (repeatTimes != null) {
                addShowIntoShowListRequest.setRepeatTimes(repeatTimes);
            }
            if (duration != null) {
                addShowIntoShowListRequest.setDuration(duration);
            }
            return client.addShowIntoShowList(addShowIntoShowListRequest);
        }
    
        private static void removeShowFromShowList(Client client, String casterId, String showId) throws Exception {
            RemoveShowFromShowListRequest removeShowFromShowList = new RemoveShowFromShowListRequest();
            removeShowFromShowList.setShowId(showId);
            removeShowFromShowList.setCasterId(casterId);
            RemoveShowFromShowListResponse removeShowFromShowListFromShowListResponse = client.removeShowFromShowList(removeShowFromShowList);
            System.out.println("删除导播台节目,removeShowFromShowListFromShowListResponse:" + JSON.toJSONString(removeShowFromShowListFromShowListResponse));
        }
    
        private static void modifyShowList(Client client, String casterId, String showId, Integer repeatTimes, Integer spot,
                                                             String highPriorityShowId, String highPriorityShowStartTime) throws Exception {
            ModifyShowListRequest modifyShowListRequest = new ModifyShowListRequest();
            if (casterId != null) {
                modifyShowListRequest.setCasterId(casterId);
            }
            if (showId != null) {
                modifyShowListRequest.setShowId(showId);
            }
            if (repeatTimes != null) {
                modifyShowListRequest.setRepeatTimes(repeatTimes);
            }
            if (spot != null) {
                modifyShowListRequest.setSpot(spot);
            }
            if (highPriorityShowId != null) {
                modifyShowListRequest.setHighPriorityShowId(highPriorityShowId);
            }
            if (highPriorityShowStartTime != null) {
                modifyShowListRequest.setHighPriorityShowStartTime(highPriorityShowStartTime);
            }
            ModifyShowListResponse modifyShowListResponse = client.modifyShowList(modifyShowListRequest);
            System.out.println("修改showList成功,返回值:" + JSON.toJSONString(modifyShowListResponse));
        }
    
        private static void describeShowList(Client client, String casterId) throws Exception {
            DescribeShowListRequest describeShowListRequest = new DescribeShowListRequest();
            if (casterId != null) {
                describeShowListRequest.setCasterId(casterId);
            }
            DescribeShowListResponse describeShowListRequestResponse = client.describeShowList(describeShowListRequest);
            System.out.println("查询showList成功,返回值:" + JSON.toJSONString(describeShowListRequestResponse));
    
            DescribeShowListResponseBody showListBody = describeShowListRequestResponse.getBody();
            JSONObject showList = JSON.parseObject(showListBody.getShowList());
            JSONArray shows = showList.getJSONArray("Shows");
            //打印播放节目单
            for (int i = 0; i < shows.size(); i++) {
                JSONObject show = (JSONObject) shows.get(i);
                String showId = show.getString("ShowId");
                String resourceType = show.getString("ResourceType");
                String resourceInfo = show.getString("ResourceInfo");
                Integer repeatTimes = show.getInteger("RepeatTimes");
                Long duration = show.getLong("Duration");
                String showInfo = String.format("show%d: showId: %s \n resourceType: %s  \n  resourceInfo: %s \n RepeatTimes: %d \n Duration: %d",
                        i + 1, showId, resourceType, resourceInfo, repeatTimes, duration);
                System.out.println(showInfo);
            }
        }
    
        private static void playChoosenShow(Client client, String casterId, String showId) throws Exception {
            PlayChoosenShowRequest playChoosenShow = new PlayChoosenShowRequest();
            playChoosenShow.setCasterId(casterId);
            playChoosenShow.setShowId(showId);
            PlayChoosenShowResponse playChoosenShowResponse = client.playChoosenShow(playChoosenShow);
            System.out.println("手动切换showId: " + showId + " 成功");
        }
    
        private static List<DescribeCasterStreamUrlResponseBody.DescribeCasterStreamUrlResponseBodyCasterStreamsCasterStream> describeCasterStreamUrl(Client client, String casterId) throws Exception {
            DescribeCasterStreamUrlRequest describeCasterStreamUrlRequest = new DescribeCasterStreamUrlRequest();
            describeCasterStreamUrlRequest.setCasterId(casterId);
            DescribeCasterStreamUrlResponse response = client.describeCasterStreamUrl(describeCasterStreamUrlRequest);
            return response.getBody().getCasterStreams().getCasterStream();
        }
    
    
        public static void main(String[] args) throws Exception {
            Client client = LiveClient.getInstance("live.aliyuncs.com", ACCESS_KEY_ID, ACCESS_KEY_SECRET);
            //创建导播台
            CreateCasterResponse caster = createCaster(client);
            String casterId = caster.getBody().getCasterId();
            //设置导播台
            String domainName = "example.aliyundoc.com"; // 设置域名
            setCasterConfig(client, casterId,domainName);
    
            //添加三个点播文件,让第一个文件播一遍,第二个文件播两遍,第三个文件播三遍
            String[] resourceIds = new String[]{"698d2b23581f476ea71107703e64****", "9c97e83e211a435b9f797e4e20ee****", "76c6addaa41c438985666a8a964f****"};
            for (int i = 0; i < resourceIds.length; i++) {
                String showName = "ShowName#" + i;
                Integer repeatTimes = i;
                addShowIntoShowList(client, showName, resourceIds[i], null, "vod", null, repeatTimes, casterId, null);
            }
            modifyShowList(client, casterId, null, 10, null, null, null);
            describeShowList(client, casterId);
            startCaster(client, casterId);
    
            Thread.sleep(500000);
    
            stopCaster(client, casterId);
        }
    
    }
    

    参数配置信息说明:

    参数配置信息

    说明

    private final static String ACCESS_KEY_ID = "AccessKey ID";
    private final static String ACCESS_KEY_SECRET = "AccessKey Secret";

    您需要使用AccessKey完成身份验证。AccessKey包括AccessKey IDAccessKey Secret。具体如下:

    • AccessKey ID:用于标识用户。

    • AccessKey Secret:用于验证用户的密钥。AccessKey Secret必须保密。

    更多信息,请参见创建AccessKey

    request.setDomainName("example.aliyundoc.com");

    播流域名。

    String[] resourceIds = new String[]{"698d2b23581f476ea71107703e64****", "9c97e83e211a435b9f797e4e20ee****", "76c6addaa41c438985666a8a964f****"};

    资源ID。请参见2.上传音视频文件获取。

  4. 查看运行结果。

    image

  5. 云导播台页面,可查看已创建的导播台,单击操作列的进入,即可看到三个点播文件按照顺序依次添加到节目单中,并按照相关配置进行播放。

    image

    image

后续操作

如果需要播放,您可以单击云导播台的播放地址并复制,通过VLC播放器、直播Demo或播放器SDK进行播放。具体操作,请参见直播播放

image