本文介紹通過調用播單型導播台API實現直播情境。超快捷彙總多個點播視訊,建立播單型導播台類型直播間,協助各夥伴豐富其視頻情境和內容形態,解決直播場次不固定、內容少、使用者不穩定的問題。同時可即時或定時自動插入廣告,促進商業變現。
方案概覽
使用播單型導播台API實現直播情境大致分為4步,如下:
啟用點播系統Bucket:開通ApsaraVideo for VOD服務後,不同的服務地區會預設分配一個獨立的儲存Bucket(類型為點播系統Bucket),通過啟用該Bucket,無需其他配置即可進行上傳和媒體資源管理。
上傳音視頻檔案:將需要進行直播的視頻檔案(例如A、B、C三個視頻檔案)按照順序依次上傳至ApsaraVideo for VOD(VOD)控制台儲存。
添加播流網域名稱:觀眾端用於觀看直播的地址。觀眾可以通過播放地址來觀看直播內容。
調用API完成播單型導播台配置:通過調用播單型導播台API,對單個視頻的播放次數和播單迴圈次數分別進行配置。例如檔案A播放一遍,檔案B播放兩遍,檔案C播放三遍。配置完成,查詢整個節目單播放清單資訊並開啟播放。
前提條件
您登入阿里雲帳號並完成帳號實名認證。
依次開通ApsaraVideo for VOD服務、ApsaraVideo for Live服務、雲導播服務。具體操作,請參見開通ApsaraVideo for VOD、開通與購買ApsaraVideo for Live、開通雲導播服務。
說明目前置播台僅在上海(華東2)、北京(華北2)、亞太地區東南1(新加坡)、印尼(雅加達)中心開放,後續將會擴充至其他中心。
已準備好播流網域名稱。為了快速體驗,建議直播中心選擇海外且加速地區採用海外及港澳台加速,此時網域名稱無需備案。
已添加AliyunFCFullAccess、AliyunLiveFullAccess、AliyunVODFullAccess系統權限原則。具體操作,請參見建立RAM使用者並授權。
1.啟用點播系統Bucket
在ApsaraVideo for VOD控制台的組態管理 > 媒资管理配置 > 存储管理頁面中,單擊點播系統Bucket所在行的啟用。
啟用儲存地址需要一段時間,請您耐心等待。當系統提示存储地址启用成功,且儲存地址的狀態為正常後,方可使用該儲存地址。

2.上傳音視頻檔案
在ApsaraVideo for VOD控制台的頁面,單擊上传音/视频。
在上传音/视频頁面,單擊添加音/视频。

在添加音/视频彈框中,選擇本地上传,將本地準備好的三個視頻檔案依次上傳,單擊开始上传。

成功後,可在音/視頻頁面查看並記錄資源ID。然後單擊操作列的更多 > 用于直播导播,播放內容可以即時在ApsaraVideo for Live的導播台中關聯顯示。導播台功能說明,請參見功能區介紹。

3.添加播流網域名稱
在ApsaraVideo for Live控制台的推/播流網域名稱管理頁面中,單擊添加網域名稱。
根據實際需求佈建網域名詳情。單擊下一步。配置參數的具體說明請參見添加加速網域名稱。

記錄產生的CNAME記錄值,供下一步使用。

在Alibaba Cloud DNS-公網權威解析頁面,單擊待設定的網域名稱操作列的解析设置。
單擊添加记录,完成CNAME配置,單擊確認。更多詳細資料,請參見佈建網域名的CNAME解析。

4.調用API完成播單型導播台配置
開啟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>在專案
src/main/java目錄下,按右鍵java,建立Java類。例如命名為bodan。配置如下範例程式碼相關參數並運行。
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 ID和AccessKey Secret。具體如下:
AccessKey ID:用於標識使用者。
AccessKey Secret:用於驗證使用者的密鑰。AccessKey Secret必須保密。
更多資訊,請參見建立AccessKey。
request.setDomainName("example.aliyundoc.com");播流網域名稱。
String[] resourceIds = new String[]{"698d2b23581f476ea71107703e64****", "9c97e83e211a435b9f797e4e20ee****", "76c6addaa41c438985666a8a964f****"};資源ID。請參見2.上傳音視頻檔案擷取。
查看運行結果。

在雲導播台頁面,可查看已建立的導播台,單擊操作列的進入,即可看到三個點播檔案按照順序依次添加到節目單中,並按照相關配置進行播放。


後續操作
如果需要播放,您可以單擊雲導播台的播放地址並複製,通過VLC播放器、直播Demo或播放器SDK進行播放。具體操作,請參見直播播放。
