試看指讓使用者在觀看視頻或者音頻等內容時,只能觀看或收聽指定時間長度的內容,通常用於付費課程、付費短劇等付費業務情境。本文介紹如何開啟ApsaraVideo for VOD的試看功能並擷取試看地址。
工作原理
阿里雲ApsaraVideo for VOD提供完整的試看解決方案。您可以通過ApsaraVideo for VOD播放服務(調用服務端GetPlayInfo - 擷取音視頻播放地址介面)設定試看時間長度後擷取試看地址或者自行拼接含有試看資訊的試看地址(URL鑒權地址)。
重要 如果設定的試看時間長度超過原視頻總時間長度,使用者可憑藉點播返回的試看地址播放完整視頻。
阿里雲ApsaraVideo for VOD試看功能基於阿里雲CDN加速實現。試看的基本原理是:播放端攜帶含有指定試看時間長度資訊的試看地址(CDN加速地址)訪問服務,雲端對試看地址鑒權。鑒權通過則返回指定的檔案內容,否則拒絕訪問並返回403。下圖展示了點播試看的實現流程:
點播使用者配置CDN加速網域名稱並開啟試看功能。
重要 網域名稱配置和開啟試看功能是使用試看功能的前提。詳細操作請參見開啟試看功能。
點播使用者的播放端向ApsaraVideo for VOD發起試看請求。
ApsaraVideo for VOD根據網域名稱配置及試看請求中的試看時間長度配置產生試看地址。
點播使用者的播放端通過播放地址向CDN請求播放視頻(試看)。
使用限制
目前試看功能支援的檔案格式為MP4、HLS。其中,MP4視頻的Meta資訊必須在檔案頭部,不支援Meta資訊在尾部的MP4視頻。通過ApsaraVideo for VOD服務轉碼封裝格式為MP4的時候,會將Meta資訊放置在檔案頭部。
試看時間與主要畫面格存在依賴(點播轉碼輸出檔案預設10秒一個主要畫面格),因此短視頻不建議使用試看,長視頻試看時間建議至少設定為30秒。
說明 主要畫面格時間長度可通過轉碼模板修改。修改方法請參見轉碼模板。
HLS檔案試看精度為ts分段時間長度,具體可能存在誤差,試看時間長度採用最大化原則。以10秒一個ts為標準,如果試看時間長度設定為15秒,實際返回資料為20秒。
開啟試看功能
無論您調用點播介面擷取試看地址還是手動拼接試看地址,都必須提前佈建網域名並開啟試看功能。詳細配置及操作指引如下:
配置CDN加速網域名稱。操作指引請參見添加加速網域名稱。
重要 只有配置CDN加速網域名稱的網域名稱才支援試看功能。
為網域名稱開啟URL鑒權,開啟過程中開啟試看功能。操作指引請參見URL鑒權。
重要 如果網域名稱沒有開啟試看,請求點播時不能攜帶試看參數,返回的地址不能訪問。因此,在開啟URL鑒權功能時必須同時開啟支援試看按鈕。
開啟試看功能控制台介面截圖參考如下:
說明 如需手動拼接試看連結,需要傳入privateKey參數用於計算鑒權值。其取值為控制台操作時產生或輸入的主Key或備Key值。請根據需求記錄上述值為後續使用做準備。
為網域名稱開啟Range回源和拖拽播放。操作指引請參見配置Range回源及拖拽播放。
調用介面擷取試看地址
ApsaraVideo for VOD提供擷取視頻播放地址的介面。介面詳情請參見GetPlayInfo - 擷取音視頻播放地址。使用者可整合服務端SDK,通過SDK調用該介面擷取試看地址。具體步驟如下:
重要 調用介面前請確保已開啟試看功能。操作指引請參見開啟試看功能。
根據業務需求整合服務端SDK。整合步驟請參考ApsaraVideo for VODSDK快速入門。
通過SDK調用GetPlayInfo - 擷取音視頻播放地址介面。調用介面時佈建要求參數PlayConfig中的PreviewTime指定試看時間長度。服務端會根據試看時間長度設定返回試看地址。PlayConfig參數描述請參見PlayConfig。
展開查看擷取試看地址範例程式碼(Java)
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoRequest;
import com.aliyuncs.vod.model.v20170321.GetPlayInfoResponse;
/**
* @date 2021/12/30
*/
public class VodPreviewTest {
public static void main(String[] args) throws ClientException {
//請根據點播服務接入地區填寫,更多資訊,請參見點播地區標識。
String regionId = "cn-shanghai";
// 阿里雲帳號AccessKey擁有所有API的存取權限,建議您使用RAM使用者進行API訪問或日常營運。
// 強烈建議不要把AccessKey ID和AccessKey Secret儲存到工程代碼裡,否則可能導致AccessKey泄露,威脅您帳號下所有資源的安全。
// 本樣本通過從環境變數中讀取AccessKey,來實現API訪問的身分識別驗證。運行程式碼範例前,請配置環境變數ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
//您的AccessKeyId
String accessKeyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
//您的AccessKeySecret
String accessKeySecret = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
//視頻ID。樣本:533606af570e4db4961248d0978b****。通過控制台上傳的視頻,可登入點播控制台,選擇媒資庫 > 音/視頻查看視頻ID。通過CreateUploadVideo介面上傳的視頻,視頻ID為返回參數VideoId的值。
String videoId = "<your videoId>";
DefaultAcsClient client = InitVodClient(regionId, accessKeyId, accessKeySecret);
GetPlayInfoResponse response = null;
try {
response = getPlayInfo(client, videoId);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("response = " + JSONObject.toJSONString(response));
}
/**
* 初始化Client
*
* @param regionId
* @param accessKeyId
* @param accessKeySecret
* @return
* @throws ClientException
*/
public static DefaultAcsClient InitVodClient(String regionId, String accessKeyId, String accessKeySecret) throws ClientException {
DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
return client;
}
/**
* 擷取視頻播放地址
*
* @param client
* @param videoId
* @return
* @throws Exception
*/
public static GetPlayInfoResponse getPlayInfo(DefaultAcsClient client, String videoId) throws Exception {
GetPlayInfoRequest request = new GetPlayInfoRequest();
request.setVideoId(videoId);
//設定到期時間,單位秒,不設定,預設3600s
request.setAuthTimeout(3600L);
request.setFormats("mp4");
JSONObject playConfig = new JSONObject();
//ApsaraVideo for VOD試看時間長度,單位為秒。最小值1
playConfig.put("PreviewTime", "30");
request.setPlayConfig(playConfig.toJSONString());
return client.getAcsResponse(request);
}
}
手動拼接試看地址
ApsaraVideo for VOD支援手動拼接帶試看資訊的URL鑒權地址。操作步驟如下:
重要 拼接試看地址前請確保已開啟試看功能。操作指引請參見開啟試看功能。
手動拼接加入試看參數的鑒權URL地址。與完整觀看時URL鑒權地址拼接不同的是,拼接試看地址在計算md5hash時要帶上試看時間長度參數previewTime
,即在原來URL鑒權md5hash計算方式的基礎上,加入試看時間長度的計算。
完整視頻地址md5hash計算 | 試看地址md5hash計算 |
MD5(uri-timestamp-rand-uid-PrivateKey)
| MD5(uri-timestamp-rand-uid-PrivateKey-previewTime)
|
說明 md5hash計算的參數描述及手動拼接鑒權URL的方法請參考配置URL鑒權。如果需要看完整視頻,不設定試看參數即可。
在拼接完成的鑒權URL末尾加上&end=
,&end=
後添加試看參數previewTime
,產生完整的試看地址。
展開查看手動拼接Jar包需要的依賴(Java)
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
展開查看手動拼接試看地址範例程式碼(Java)
import java.util.UUID;
import java.net.URL;
import org.apache.commons.lang3.StringUtils;
private String generateRand() {
return UUID.randomUUID().toString().replaceAll("-", "");
}
private String md5(String str) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(str.getBytes("UTF-8"));
return bytesToHex(md5.digest());
} catch (Exception e) {
e.printStackTrace();
}
}
public String genAuthKey(String object, String privateKey, Long expireTime, Long previewTime) {
String rand = "0";
String uid = "0";
if (StringUtils.isBlank(privateKey)) {
return "";
}
rand = generateRand();
long timestamp = System.currentTimeMillis() / 1000 + (expireTime == null ? 0 : expireTime);
String authStr = timestamp + "-" + rand + "-" + uid;
String md5Str = object + "-" + authStr + "-" + privateKey;
if(previewTime!=0)
md5Str = md5Str + "-" + previewTime;
String auth_key = authStr + "-" + this.md5(md5Str);
return auth_key;
}
public void previewTest() throws Exception {
try {
String key = "<Your PrivateKey>";//控制台配置的主Key或備Key。如何擷取請參見開啟試看功能。
String fileUrl = "<Your File URL>";//檔案地址,樣本:http://example.aliyundoc.com/test/bee21427ca3346848835c1bd786054c5-19bd8528c1d51576cd726cf86471ca0****.mp4
URL url = new URL(fileUrl);
String file = url.getFile();
Long previewTime = 120L;//試看時間長度。
Long expireTime = 1800L;
String auth_key =genAuthKey(file, key, expireTime, previewTime);
fileUrl = fileUrl + "?auth_key=" + auth_key;
if(previewTime != 0)
fileUrl = fileUrl + "&end=" + previewTime;
System.out.println(fileUrl);
} catch (Exception e) {
e.printStackTrace();
}
}