授權播放與跑馬燈
螢幕錄影是最難防範的一種影片盜版方式,保利威播放器提供的防錄影跑馬燈功能,透過設定文字內容(通常是觀眾的身份ID資訊)在影片上不規則滾動,以此來警示盜版者,達到影片版權保護的效果。
另外在使用者網站中,除了透過登入資訊(cookies)驗證觀眾是否有權限存取影片播放頁面外,還可以透過保利威播放器驗證觀眾是否有播放某一個影片的權限,從而實現對觀眾權限的雙重驗證。
防錄影跑馬燈的影片介紹:防錄影神器–跑馬燈(影片)。
實作流程

實作步驟
一、管理後台設定
登入雲端點播管理後台,點選 【設定】 → 【影片設定】,進入影片設定頁面。
在授權播放與防錄影跑馬燈介面設定欄中,填寫業務方的介面服務URL。

播放器在請求授權介面時,會自動適應以下情況:
- 當填寫的是完整的URL時,播放器會直接請求,例如:http://mywebsite.com/interface/validate。
- 當填寫的是不帶協定頭的介面位址時,播放器會根據目前頁面的請求協定自動補全。例如填寫的是://mywebsite.com/interface/validate,目前頁面使用https協定存取,那麼實際請求的是:https://mywebsite.com/interface/validate。
- 當填寫的是不帶協定頭和HOST的介面位址時,播放器會根據目前頁面的請求協定和HOST自動補全。例如填寫的是:/interface/validate 或 interface/validate,目前頁面的網域名稱是mywebsite2.com,且頁面使用http協定存取,那麼實際請求的是:http://mywebsite2.com/interface/validate。
二、業務方伺服器端實作
1、播放器端請求
當管理後台設定授權播放與跑馬燈介面後,Polyv播放器在播放影片時會首先請求後台設定的介面,請求的方式為GET,並且會附帶vid、code、t、callback這四個參數,例如:https://www.mywebsite.com/validate?vid=e2e84a73837363106d8d257f60e55c4c_e&code=&t=1457938821973&callback=polyvObject16209048491895664483_1457938783908&_=1457938784101。
其中code為播放器嵌入程式碼中的參數,值可以自訂;t為播放器產生的隨機數。播放器範例程式碼如下:
<script src='https://player.polyv.net/script/player.js'></script>
<div id='player'></div>
<script>
var player = polyvPlayer({
wrap: '#player',
width: 800,
height: 533,
vid: '88083abbf5bcf1356e05d39666be527a_8',
code: 'myCodeValue' // 用户可自定义参数值,也可以不设置此参数,那么在请求接口时该参数值为空。参数值为中文时需要做base64URLSafe。
});
</script>
由於H5播放器透過Ajax方式請求使用者介面,需要跨域請求,因此需要callback參數。而Flash播放器是透過跨域檔案實現跨域,所以不需要callback參數,請求介面時只會提交vid、code和t三個參數。Flash播放器實現跨域請參考跨域存取設定。
2、伺服器端介面實作
業務方伺服器端介面如果只需實現授權驗證的功能,只需回傳 status、username、sign三個參數給播放器驗證即可。
伺服器端實作的PHP範例如下:
// validate.php
<?php
$username = "elvis"; // 用户昵称, 若值为中文需要urlencode('张三'),可从session获取
$secretkey = "secretkey"; // 登录保利威管理后台,点击 【设置】 → 【API接口】获取
$vid=$_GET["vid"];
$t = $_GET["t"];
$code = $_GET["code"];
if($username=="elvis"){
$status = 1; // 业务方可自定义授权验证逻辑
}else {
$status = 2;
}
if(!empty($_GET["callback"])){
$callback = $_GET["callback"];
}else{
$callback = '';
}
$sign=md5("vid=$vid&secretkey=$secretkey&username=$username&code=$code&status=$status&t=$t");
$array=Array("status"=>$status,"username"=>$username,"sign"=>$sign);
$Json = json_encode($array);
if($callback!=''){ //PC H5播放器会提交callback参数
echo $callback."(".$Json.")";
} else{ //Flash播放器不提交callback参数
echo "(".$Json.")";
}
?>
Java SpringMvc範例如下:
@ResponseBody
@RequestMapping("/player-auth")
public String playerAuth(String vid, long t, String code, String callback) {
String username = "elvis";
String secretKey = "secretkey";
int status;
// 业务方可自定义授权验证逻辑
if ("elvis".equals(username)) {
status = 1;
} else {
status = 2;
}
// md5签名,自行选择md5库
String plain = "vid=" + vid + "&secretkey=" + secretKey + "&username=" + username + "&code=" + code + "&status=" + status + "&t=" + t;
String sign = md5Hex(plain);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("username", username);
resultMap.put("status", status);
resultMap.put("sign", sign);
// json序列化
ObjectMapper objectMapper = new ObjectMapper();
String resultJson = "";
try {
resultJson = objectMapper.writeValueAsString(resultMap);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
if (callback != null && !"".equals(callback)) {
return callback + "(" + resultJson + ")";
} else {
return resultJson;
}
}
其中,sign的計算規則為:拼接vid、secretkey、username、code、status、t參數做MD5計算:
Plain ="vid=" + vid + "&secretkey=" + secretKey + "&username=" + username + "&code=" + code + "&status=" +status + "&t=" + t
sign = MD5.hash(Plain);
以下為介面回傳範例:
polyvObject16208229674372271079_1478765178186({
"status":1,
"username":"elvis",
"sign":"1cca74bd55c6076091ed84807065e5b7"
})
// 不提交callback参数时
{
"status":1,
"username":"elvis",
"sign":"2c2bfb00314da7d768d50a7d1e93bd9f"
}
如果除了授權驗證,還需實現跑馬燈功能,則介面需要回傳跑馬燈相關的參數。
伺服器端實作的PHP範例如下:
// validate.php
<?php
$username = "elvis"; // 用户昵称, 若值为中文需要urlencode('张三'),可从session获取
$secretkey = "secretkey"; // 登录保利威管理后台,点击 【设置】 → 【API接口】获取
$vid=$_GET["vid"];
$t = $_GET["t"];
$code = $_GET["code"];
$fontSize="40";
$fontColor="0xFFE900";
$speed="200";
$filter="on";
$setting="3";
$alpha="1";
$filterAlpha="1";
$filterColor="0x3914AF";
$blurX="2";
$blurY="2";
$tweenTime="1";
$interval="5";
$lifeTime="3";
$strength="4";
$show="on";
$msg="Errormessage!";
if($username=="elvis"){ // 业务方可自定义授权验证逻辑
$status = 1;
}else {
$status = 2;
}
if(!empty($_GET["callback"])){
$callback = $_GET["callback"];
}else{
$callback = '';
}
$sign=md5("vid=$vid&secretkey=$secretkey&username=$username&code=$code&status=$status&t=$t&msg=$msg&fontSize=$fontSize&fontColor=$fontColor&speed=$speed&filter=$filter&setting=$setting&alpha=$alpha&filterAlpha=$filterAlpha&filterColor=$filterColor&blurX=$blurX&blurY=$blurY&interval=$interval&lifeTime=$lifeTime&tweenTime=$tweenTime&strength=$strength&show=$show");
$array = Array("status"=>$status,"username"=>$username,"sign"=>$sign,"msg"=>$msg,"fontSize"=>$fontSize,"fontColor"=>$fontColor,"speed"=>$speed,"filter"=>$filter,"setting"=>$setting,"alpha"=>$alpha,"filterAlpha"=>$filterAlpha,"filterColor"=>$filterColor,"blurX"=>$blurX,"blurY"=>$blurY,"tweenTime"=>$tweenTime,"interval"=>$interval,"lifeTime"=>$lifeTime,"strength"=>$strength,"show"=>$show,);
$Json = json_encode($array);
if($callback!=''){
echo $callback."(".$Json.")";
} else{
echo $Json;
}
?>
Java SpringMvc範例如下:
@ResponseBody
@RequestMapping("/player-auth-marquee")
public String playerAuthMarquee(String vid, long t, String code, String callback) {
String username = "suki";
String secretKey = "AiDQw1mAmi";
String fontSize = "40", fontColor = "0xFFE900", speed = "200",
filter = "on", setting = "3", alpha = "1", filterAlpha = "1",
filterColor = "0x3914AF", blurX = "2", blurY = "2", tweenTime = "1",
interval = "5", lifeTime = "3", strength = "4", show = "on", msg = "Errormessage!";
int status;
// 业务方可自定义授权验证逻辑
if ("suki".equals(username)) {
status = 1;
} else {
status = 2;
}
code = code == null?"":code;
// md5签名,自行选择md5库
String plain = "vid=" + vid + "&secretkey=" + secretKey + "&username=" + username + "&code=" + code + "&status=" + status + "&t=" + t +
"&msg=" + msg + "&fontSize=" + fontSize + "&fontColor=" + fontColor + "&speed=" + speed + "&filter=" + filter + "&setting=" + setting +
"&alpha=" + alpha + "&filterAlpha=" + filterAlpha + "&filterColor=" + filterColor + "&blurX=" + blurX + "&blurY=" + blurY +
"&interval=" + interval + "&lifeTime=" + lifeTime + "&tweenTime=" + tweenTime + "&strength=" + strength + "&show=" + show;
String sign = md5Hex(plain);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("username", username);
resultMap.put("status", status);
resultMap.put("sign", sign);
resultMap.put("msg", msg);
resultMap.put("fontSize", fontSize);
resultMap.put("fontColor", fontColor);
resultMap.put("speed", speed);
resultMap.put("filter", filter);
resultMap.put("setting", setting);
resultMap.put("alpha", alpha);
resultMap.put("filterAlpha", filterAlpha);
resultMap.put("filterColor", filterColor);
resultMap.put("blurX", blurX);
resultMap.put("blurY", blurY);
resultMap.put("tweenTime", tweenTime);
resultMap.put("interval", interval);
resultMap.put("lifeTime", lifeTime);
resultMap.put("strength", strength);
resultMap.put("show", show);
// json序列化,可自行选择json序列化库
ObjectMapper objectMapper = new ObjectMapper();
String resultJson = "";
try {
resultJson = objectMapper.writeValueAsString(resultMap);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
if (callback != null && !"".equals(callback)) {
return callback + "(" + resultJson + ")";
} else {
return resultJson;
}
}
其中,sign的計算規則為(參數必須按照範例中的順序拼接):
Plain = "vid=" + vid + "&secretkey=" + secretKey + "&username=" + username + "&code=" + code + "&status=" + status + "&t=" + t +
"&msg=" + msg + "&fontSize=" + fontSize + "&fontColor=" + fontColor + "&speed=" + speed +"&filter=" +filter + "&setting=" + setting +
"&alpha=" + alpha + "&filterAlpha=" + filterAlpha + "&filterColor=" + filterColor + "&blurX=" + blurX + "&blurY=" + blurY +
"&interval=" + interval + "&lifeTime=" + lifeTime + "&tweenTime=" + tweenTime + "&strength=" + strength + "&show=" +show;
sign = MD5.hash(Plain);
例如:當
vid="8f8482aaab11dd5f45f183a9192a04c5_8",secretkey="AiDQw1mAmi",username="suki",code="abc",status="1",t="143020010115550947",msg="Errormessage!",fontSize="40",fontColor="0xFFE900",speed="200",filter="on",setting="3",alpha="1",filterAlpha="1",filterColor="0x3914AF",blurX="2",blurY="2",interval="5",lifeTime="3",tweenTime="1",strength="4",show="on"
時,拼湊起來去MD5計算的字串為:
vid=8f8482aaab11dd5f45f183a9192a04c5_8&secretkey=AiDQw1mAmi&username=suki&code=abc&status=1&t=143020010115550947&msg=Errormessage!&fontSize=40&fontColor=0xFFE900&speed=200&filter=on&setting=3&alpha=1&filterAlpha=1&filterColor=0x3914AF&blurX=2&blurY=2&interval=5&lifeTime=3&tweenTime=1&strength=4&show=on
則sign為MD5計算後32位小寫的值:3b07f56f29b7fd728bf20020442338e7
以下為介面回傳範例:
{
"status":1,
"username":"elvis",
"sign":"6ab63590797e513d1b6c46b407413478",
"msg":"Errormessage!",
"fontSize":"40",
"fontColor":"0xFFE900",
"speed":"200",
"filter":"on",
"setting":"3",
"alpha":"1",
"filterAlpha":"1",
"filterColor":"0x3914AF",
"blurX":"2",
"blurY":"2",
"tweenTime":"1",
"interval":"5",
"lifeTime":"3",
"strength":"4",
"show":"on"
}
三、介面回傳參數說明
| 參數名 | 類型 | 必填 | 預設值 | 說明 |
|---|---|---|---|---|
| status | Integer | 是 | / | 是否允許播放:1 允許 2 禁止 |
| username | String | 是 | / | 觀眾名稱,也會用於跑馬燈顯示的文字內容 |
| sign | String | 是 | / | 介面簽名,用於校驗回傳內容是否被篡改 |
| show | String | 是 | off | 當參數值為“on”時表示顯示跑馬燈,預設不顯示 |
| setting | Integer | 是 | 1 | 跑馬燈滾動的樣式:1 從右到左滾動 2 隨機位置閃爍 3 從右到左閃爍滾動 |
| speed | Integer | 是 | 200 | 跑馬燈文字從右側移至左側所需時間,單位:1/10秒,僅對setting(1、3)生效 |
| lifeTime | Integer | 是 | 3 | 跑馬燈文字顯示時間,單位:秒,僅對setting(2)生效 |
| interval | Integer | 是 | 5 | 跑馬燈文字隱藏間隔時間,單位:秒, 僅對setting(2、3)生效, |
| tweenTime | Integer | 是 | 1 | 跑馬燈文字漸隱漸現時間,單位:秒 (已廢棄) |
| fontSize | Integer | 是 | 30 | 跑馬燈文字的字型大小 |
| fontColor | String | 是 | 0x000000 | 跑馬燈文字顏色,使用十六進位顏色值表示,如0xFF0000,預設為黑色 |
| alpha | Float | 是 | 1 | 跑馬燈文字透明度,取值範圍0.01~1,參數值不能小於0.01 |
| filter | String | 是 | off | 跑馬燈文字是否描邊,on 描邊 off 不描邊 |
| filterAlpha | Float | 是 | 1 | 文字描邊透明度,取值範圍0~1 |
| filterColor | String | 是 | 0x000000 | 文字描邊顏色,使用十六進位顏色值表示,如0xFF0000,預設為黑色 |
| strength | Integer | 是 | 4 | 描邊強度,取值範圍0~255 |
| blurX | Integer | 是 | 2 | 描邊水平模糊量,取值範圍0~255 |
| blurY | Integer | 是 | 2 | 描邊垂直模糊量,取值範圍0~255 |
| msg | String | 是 | / | 自訂錯誤提示資訊 |
- setting(1): 跑馬燈由右向左滾動,
speed/10秒完成滾動,間隔2秒後進行下一次滾動 - setting(2): 跑馬燈在隨機位置交替顯示隱藏,每次顯示
lifeTime秒後隱藏interval秒,然後下一次循環開始 - setting(3): 跑馬燈由右向左滾動,
speed/10秒完成滾動,間隔speed/10 + interval秒後進行下一次滾動, 滾動期間每3秒隱藏一次,隱藏3秒後顯示
- 當介面只做授權驗證用途時,只需回傳 status、username和sign三個參數,跑馬燈相關參數可不回傳。
- 請確保介面回傳資料是utf-8編碼,注意 status參數是整型,不能是字串類型。
- 目前跑馬燈功能不支援在行動端H5播放器上使用(1.0不支援,建議使用2.0)。
- 請盡量不要對播放器樣式或<video>標籤進行修改
