視頻上傳到ApsaraVideo for VOD中時,若指定了視頻封面則會使用指定的圖片作為視頻封面,如果不指定,則會自動截取並選擇一張視頻截圖作為視頻封面,上傳完成後也可以對視頻封面進行更新。
概述
上傳到ApsaraVideo for VOD中的每一個視頻都存在視頻封面。
上傳視頻時,如果指定了視頻封面,則視頻上傳完成後,會使用您指定的圖片作為視頻封面;若上傳時未指定視頻封面,則點播會預設對上傳的視頻進行視頻截圖,截取1~8張圖,並選取中間的一張截圖作為視頻封面,更多資訊,請參見視頻截圖。視頻上傳完成之後,也可以對視頻封面進行更新。
前提條件
已經開通了ApsaraVideo for VOD服務。開通步驟請參見開通ApsaraVideo for VOD。
為了您的帳號和資源的安全,建議您使用RAM使用者或RAM角色進行操作,並請確保RAM使用者或RAM角色已授予ApsaraVideo for VOD的相關許可權。具體操作,請參見建立RAM使用者並授權。
如果您已經配置了ApsaraVideo for VOD的加速網域名稱,則該網域名稱需要配置認證後,才能設定封面。具體操作,請參見HTTPS安全加速設定。
上傳視頻時設定封面
ApsaraVideo for VOD提供了多種上傳視頻的方式,詳細資料,請參見上傳方式。其中,僅開發上傳方式即通過API/SDK方式上傳視頻時,支援指定視頻封面上傳。具體設定如下:
CoverURL支援設定任意地址,ApsaraVideo for VOD不對該地址作處理,僅儲存該地址,在使用者請求時返回,您需要自行保證該CoverURL是否可以訪問。
調用CreateUploadVideo - 擷取音視頻上傳地址和憑證介面時,可以傳入CoverURL(自訂視頻封面URL地址)參數指定視頻封面。
調用UploadMediaByURL - URL批量拉取上傳介面時,在UploadMetadata中傳入CoverURL(自訂視頻封面URL地址)參數指定視頻封面。
視頻上傳後更新封面
當視頻上傳到ApsaraVideo for VOD之後,可以通過下述方式更新視頻封面。
設定普通封面
控制台方式
當視頻上傳到ApsaraVideo for VOD之後,可以直接在ApsaraVideo for VOD控制台更新視頻封面。支援設定本地圖片和視頻截圖為視頻封面。
在左側導覽列選擇媒資庫 > 音/視頻,進入到音視頻列表頁面。
選擇需要更新封面的視頻,單擊管理。
在基礎資訊頁簽,單擊編輯視頻資訊。
可以從自動截取的多張視頻截圖裡選一張作為視頻封面。
也可以單擊上傳封面,選擇一張本地圖片作為視頻封面。
說明上傳封面的圖片僅支援JPG、PNG格式,最大1 MB,像素不超過1920Px × 1080Px。
單擊儲存,完成配置。
完成配置後,可以返迴音視頻列表頁面查看視頻封面是否已經更新成功。
OpenAPI方式
當視頻上傳到ApsaraVideo for VOD之後,可以調用下述介面更新視頻封面。支援設定任意可訪問的地址為視頻封面。
CoverURL支援設定任意地址,ApsaraVideo for VOD不對該地址作處理,僅儲存該地址,在使用者請求時返回,您需要自行保證該CoverURL是否可以訪問。
調用UpdateVideoInfo - 修改單個音視頻資訊介面,傳入
CoverURL
(自訂視頻封面URL地址)參數指定視頻封面。調用UpdateVideoInfos - 批量修改音視頻資訊介面,在
UpdateContent
中傳入CoverURL
參數(自訂視頻封面URL地址)指定視頻封面。如果視頻已儲存到OSS自有Bucket中,當將OSS自有Bucket接入到ApsaraVideo for VOD中,調用RegisterMedia - 註冊媒資資訊介面註冊媒資資訊時,在
RegisterMetadata
裡面傳入CoverURL
(自訂視頻封面URL地址)參數指定視頻封面。
案例示範-設定視頻首幀截圖為視頻封面
配置流程
建立截取視頻首幀的截圖模板。
發起截取視頻首幀的截圖任務。
修改視頻封面為視頻首幀截圖。
配置方法
控制台方式配置
建立截取視頻首幀的截圖模板。
在左側導覽列選擇組態管理 > ApsaraVideo for Media Processing配置 > 截圖模板,進入到截圖模板頁面。
單擊添加截圖模板,配置截取視頻首幀截圖的模板參數。
模板名稱請自訂設定,截圖方式選擇普通截圖,起始時間點設定為00:00:00,截圖數量設定為1,其餘參數請按需配置,有關截圖模板的參數解釋,詳情請參見截圖模板。
單擊儲存,完成截圖模板的建立。
發起截取視頻首幀的截圖任務。
情境一:上傳視頻時截圖
在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻。
單擊上傳音/視頻,單擊添加音/視頻。
按需設定上傳方式、儲存地址並添加上傳的視頻後,選擇用工作流程處理,並選擇預先建立的包含首幀截圖任務的工作流程。
單擊開始上傳。
情境二:上傳視頻後截圖
在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻。
在音/視頻列表頁面,單擊目標視頻所在行的ApsaraVideo for Media Processing。
處理類型選擇用工作流程處理,工作流程選擇預先建立的包含首幀截圖任務的工作流程。
單擊確定。
擷取截圖結果
如果您已經配置了ApsaraVideo for VOD的視頻截圖完成的事件通知,您可以從回調事件中擷取到截圖任務的狀態及截取的圖片地址等資訊。
如果您未配置事件通知,您可以使用輪詢的方式調用ListSnapshots - 查詢視頻截圖資料介面來查詢截圖任務的狀態及截取的圖片地址等資訊。
修改視頻封面為視頻首幀截圖。
說明通過控制台方式修改視頻封面,只支援在視頻上傳完成後對視頻封面進行更新。您需要先將步驟2中截圖任務截取到的視頻首幀截圖儲存到本地以便修改封面時上傳。
在ApsaraVideo for VOD控制台,從左側導覽列選擇媒資庫 > 音/視頻。
在音/視頻列表頁面,單擊目標視頻所在行的管理。
在基礎資訊頁簽,單擊編輯視頻資訊。
單擊上傳封面,選擇預先儲存到本地的視頻首幀截圖,單擊開啟。
單擊儲存,完成視頻封面設定。
設定完成後,您可以在音/視頻列表頁面查看視頻封面是否更新成功。
OpenAPI方式配置
本文以使用Java語言的阿里雲 SDK方式調用ApsaraVideo for VOD的OpenAPI為例進行舉例說明。
操作步驟
建立截取視頻首幀的截圖模板。
調用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. 推薦使用ApsaraVideo for VOD控制台建立截圖模板,更加方便快捷。 */ 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; } }
發起截取視頻首幀的截圖任務。
調用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); } }
修改視頻封面為視頻首幀截圖。
此處以視頻上傳完成後,修改單個視頻封面的情境為例進行說明,其他情境的實現,請參見上傳視頻時設定封面、視頻上傳後更新封面。
通過調用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;
}
}