試看視頻
試看指讓用戶在觀看視頻或者音頻等內(nèi)容時(shí),只能觀看或收聽(tīng)指定時(shí)長(zhǎng)的內(nèi)容,通常用于付費(fèi)課程、付費(fèi)短劇等付費(fèi)業(yè)務(wù)場(chǎng)景。本文介紹如何開(kāi)啟視頻點(diǎn)播的試看功能并獲取試看地址。
工作原理
阿里云視頻點(diǎn)播提供完整的試看解決方案。您可以通過(guò)視頻點(diǎn)播播放服務(wù)(調(diào)用服務(wù)端GetPlayInfo - 獲取音視頻播放地址接口)設(shè)置試看時(shí)長(zhǎng)后獲取試看地址或者自行拼接含有試看信息的試看地址(URL鑒權(quán)地址)。
如果設(shè)置的試看時(shí)長(zhǎng)超過(guò)原視頻總時(shí)長(zhǎng),用戶可憑借點(diǎn)播返回的試看地址播放完整視頻。
阿里云視頻點(diǎn)播試看功能基于阿里云CDN加速實(shí)現(xiàn)。試看的基本原理是:播放端攜帶含有指定試看時(shí)長(zhǎng)信息的試看地址(CDN加速地址)訪問(wèn)服務(wù),云端對(duì)試看地址鑒權(quán)。鑒權(quán)通過(guò)則返回指定的文件內(nèi)容,否則拒絕訪問(wèn)并返回403。下圖展示了點(diǎn)播試看的實(shí)現(xiàn)流程:
點(diǎn)播用戶配置CDN加速域名并開(kāi)啟試看功能。
重要域名配置和開(kāi)啟試看功能是使用試看功能的前提。詳細(xì)操作請(qǐng)參見(jiàn)開(kāi)啟試看功能。
點(diǎn)播用戶的播放端向視頻點(diǎn)播發(fā)起試看請(qǐng)求。
視頻點(diǎn)播根據(jù)域名配置及試看請(qǐng)求中的試看時(shí)長(zhǎng)配置生成試看地址。
說(shuō)明點(diǎn)播支持調(diào)用服務(wù)端接口生成試看地址,也支持用戶自行拼接試看地址。詳情請(qǐng)參見(jiàn)調(diào)用接口獲取試看地址或手動(dòng)拼接試看地址。
點(diǎn)播用戶的播放端通過(guò)播放地址向CDN請(qǐng)求播放視頻(試看)。
使用限制
目前試看功能支持的文件格式為MP4、HLS。其中,MP4視頻的Meta信息必須在文件頭部,不支持Meta信息在尾部的MP4視頻。通過(guò)視頻點(diǎn)播服務(wù)轉(zhuǎn)碼封裝格式為MP4的時(shí)候,會(huì)將Meta信息放置在文件頭部。
試看時(shí)間與關(guān)鍵幀存在依賴(點(diǎn)播轉(zhuǎn)碼輸出文件默認(rèn)10秒一個(gè)關(guān)鍵幀),因此短視頻不建議使用試看,長(zhǎng)視頻試看時(shí)間建議至少設(shè)置為30秒。
說(shuō)明關(guān)鍵幀時(shí)長(zhǎng)可通過(guò)轉(zhuǎn)碼模板修改。修改方法請(qǐng)參見(jiàn)配置普通轉(zhuǎn)碼模板。
HLS文件試看精度為ts分段時(shí)長(zhǎng),具體可能存在誤差,試看時(shí)長(zhǎng)采用最大化原則。以10秒一個(gè)ts為標(biāo)準(zhǔn),如果試看時(shí)長(zhǎng)設(shè)置為15秒,實(shí)際返回?cái)?shù)據(jù)為20秒。
開(kāi)啟試看功能
無(wú)論您調(diào)用點(diǎn)播接口獲取試看地址還是手動(dòng)拼接試看地址,都必須提前配置域名并開(kāi)啟試看功能。詳細(xì)配置及操作指引如下:
配置CDN加速域名。操作指引請(qǐng)參見(jiàn)添加加速域名。
重要只有配置CDN加速域名的域名才支持試看功能。
為域名開(kāi)啟URL鑒權(quán),開(kāi)啟過(guò)程中打開(kāi)試看功能。操作指引請(qǐng)參見(jiàn)URL鑒權(quán)。
重要如果域名沒(méi)有開(kāi)啟試看,請(qǐng)求點(diǎn)播時(shí)不能攜帶試看參數(shù),返回的地址不能訪問(wèn)。因此,在開(kāi)啟URL鑒權(quán)功能時(shí)必須同時(shí)打開(kāi)支持試看按鈕。
開(kāi)啟試看功能控制臺(tái)界面截圖參考如下:
說(shuō)明如需手動(dòng)拼接試看鏈接,需要傳入privateKey參數(shù)用于計(jì)算鑒權(quán)值。其取值為控制臺(tái)操作時(shí)生成或輸入的主Key或備Key值。請(qǐng)根據(jù)需求記錄上述值為后續(xù)使用做準(zhǔn)備。
調(diào)用接口獲取試看地址
視頻點(diǎn)播提供獲取視頻播放地址的接口。接口詳情請(qǐng)參見(jiàn)GetPlayInfo - 獲取音視頻播放地址。用戶可集成服務(wù)端SDK,通過(guò)SDK調(diào)用該接口獲取試看地址。具體步驟如下:
調(diào)用接口前請(qǐng)確保已開(kāi)啟試看功能。操作指引請(qǐng)參見(jiàn)開(kāi)啟試看功能。
根據(jù)業(yè)務(wù)需求集成服務(wù)端SDK。集成步驟請(qǐng)參考視頻點(diǎn)播SDK快速入門。
通過(guò)SDK調(diào)用GetPlayInfo - 獲取音視頻播放地址接口。調(diào)用接口時(shí)設(shè)置請(qǐng)求參數(shù)PlayConfig中的PreviewTime指定試看時(shí)長(zhǎng)。服務(wù)端會(huì)根據(jù)試看時(shí)長(zhǎng)設(shè)置返回試看地址。PlayConfig參數(shù)描述請(qǐng)參見(jiàn)PlayConfig。
更多語(yǔ)言示例代碼請(qǐng)參見(jiàn)OpenAPI。
調(diào)用服務(wù)端接口需要使用AccessKey完成身份驗(yàn)證,請(qǐng)?zhí)崆矮@取AccessKey。獲取方法請(qǐng)參見(jiàn)創(chuàng)建AccessKey。
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 {
//請(qǐng)根據(jù)點(diǎn)播服務(wù)接入?yún)^(qū)域填寫,更多信息,請(qǐng)參見(jiàn)點(diǎn)播地域標(biāo)識(shí)。
String regionId = "cn-shanghai";
// 阿里云賬號(hào)AccessKey擁有所有API的訪問(wèn)權(quán)限,建議您使用RAM用戶進(jìn)行API訪問(wèn)或日常運(yùn)維。
// 強(qiáng)烈建議不要把AccessKey ID和AccessKey Secret保存到工程代碼里,否則可能導(dǎo)致AccessKey泄露,威脅您賬號(hào)下所有資源的安全。
// 本示例通過(guò)從環(huán)境變量中讀取AccessKey,來(lái)實(shí)現(xiàn)API訪問(wèn)的身份驗(yàn)證。運(yùn)行代碼示例前,請(qǐng)配置環(huán)境變量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****。通過(guò)控制臺(tái)上傳的視頻,可登錄點(diǎn)播控制臺(tái),選擇媒資庫(kù) > 音/視頻查看視頻ID。通過(guò)CreateUploadVideo接口上傳的視頻,視頻ID為返回參數(shù)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);
//設(shè)置過(guò)期時(shí)間,單位秒,不設(shè)置,默認(rèn)3600s
request.setAuthTimeout(3600L);
request.setFormats("mp4");
JSONObject playConfig = new JSONObject();
//視頻點(diǎn)播試看時(shí)長(zhǎng),單位為秒。最小值1
playConfig.put("PreviewTime", "30");
request.setPlayConfig(playConfig.toJSONString());
return client.getAcsResponse(request);
}
}
手動(dòng)拼接試看地址
視頻點(diǎn)播支持手動(dòng)拼接帶試看信息的URL鑒權(quán)地址。操作步驟如下:
拼接試看地址前請(qǐng)確保已開(kāi)啟試看功能。操作指引請(qǐng)參見(jiàn)開(kāi)啟試看功能。
手動(dòng)拼接加入試看參數(shù)的鑒權(quán)URL地址。與完整觀看時(shí)URL鑒權(quán)地址拼接不同的是,拼接試看地址在計(jì)算md5hash時(shí)要帶上試看時(shí)長(zhǎng)參數(shù)
previewTime
,即在原來(lái)URL鑒權(quán)md5hash計(jì)算方式的基礎(chǔ)上,加入試看時(shí)長(zhǎng)的計(jì)算。完整視頻地址md5hash計(jì)算
試看地址md5hash計(jì)算
MD5(uri-timestamp-rand-uid-PrivateKey)
MD5(uri-timestamp-rand-uid-PrivateKey-previewTime)
說(shuō)明md5hash計(jì)算的參數(shù)描述及手動(dòng)拼接鑒權(quán)URL的方法請(qǐng)參考配置URL鑒權(quán)。如果需要看完整視頻,不設(shè)置試看參數(shù)即可。
在拼接完成的鑒權(quán)URL末尾加上
&end=
,&end=
后添加試看參數(shù)previewTime
,生成完整的試看地址。
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
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>";//控制臺(tái)配置的主Key或備Key。如何獲取請(qǐng)參見(jiàn)開(kāi)啟試看功能。
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;//試看時(shí)長(zhǎng)。
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();
}
}