一:帮助文档:
移动云帮助中心https://ecloud.10086.cn/op-help-center/doc/category/753
二:准备工作:
1:进入移动云首页,点击【产品】>【视频服务】>【视频服务】>【视频直播】
点击【立即订购】,会跳转到视频直播购买页面进行购买
2:根据选择订购服务的区域,确认对应的API接入地址。
3:进入控制台,选择视频点播,点击API认证消息,获取uid、secretId、secretKey备用。
三:流程说明:
1:想要获取移动云的直播推拉流地址,首先需要有一个直播频道。
这个直播频道是调用API接口 /l2/live/createChannel创建时返回的channel_Id。
使用该频道id作为参数,再去请求推流和播流的API地址,就能获得对应的推拉流地址。
参考文档:移动云帮助中心https://ecloud.10086.cn/op-help-center/doc/article/40529
2:无论是创建直播频道还是获取推拉流地址,都需要携带token验证字符串,API接口在收到请求时,会验证token是否有效。
所以,生成token是所有请求的必经之路。
3:官方文档推荐使用v2.0版本进行鉴权,那么,接下来我们就讲解v2.0版本的鉴权token如何生成。参考文档:
移动云帮助中心https://ecloud.10086.cn/op-help-center/doc/article/40526
请注意:生成鉴权token时,需要根据每个业务接口文档的GET和POST请求方式不同而给签名body赋予不同的值。下面是官方文档中需要注意事项,特别之处已经标注出来。
四:代码实现:
/**
* 生成移动云鉴权token
* $business_arr 业务参数列表
* $request_type 请求方式 get/post 默认get
*/
function getEcloudToken($business_arr,$request_type='get'){
$rs=[];
$uid=;
$secretId=;
$secretKey=;
$apiId=200001;
$currentTimeStamp=getMillisecond();
$expired=$currentTimeStamp+12*60*60*1000;
$grant_type='v2.0';
$random=sprintf("%08d",rand(0,99999999));
$arr=[
'apiId'=>$apiId,
'body'=>'%5B%5D',
'currentTimeStamp'=>$currentTimeStamp,
'expired'=>$expired,
'grant_type'=>$grant_type,
'random'=>$random,
'secretId'=>$secretId,
'uid'=>$uid
];
if($request_type=='post'){
$body_str = rawurlencode(json_encode($business_arr));
$arr['body']=$body_str;
}else{
$arr=array_merge($arr,$business_arr);
}
//var_dump($request_type."参与token生成的参数");
//var_dump($arr);
//var_dump("业务参数");
//var_dump($business_arr);
ksort($arr);//按照字典排序参数数组
//var_dump("字典排序后的参数");
//var_dump($arr);
$sign = "";
foreach ($arr as $k => $v) {
$sign .= $k."=".$v."&";
}
$new_sign = mb_substr($sign, 0,mb_strlen($sign)-1);
//var_dump("拼接的字符串");
//var_dump($new_sign);
$token = hash_hmac('sha256', $new_sign, $secretKey);
//var_dump("生成的token");
//var_dump($token);
$rs=[];
unset($arr['body']);
$arr['token']=$token;
//拼接基础参数字符串
ksort($arr);//按照字典排序参数数组
$raw_sign = "";
foreach ($arr as $k => $v) {
$raw_sign .= $k."=".$v."&";
}
$new_raw_sign = mb_substr($raw_sign, 0,mb_strlen($raw_sign)-1);
$rs['raw_sign']=$new_raw_sign;
return $rs;
}
//生成毫秒级时间戳
function getMillisecond() {
list($s1, $s2) = explode(' ', microtime());
return (float)sprintf('%.0f', (floatval($s1) + floatval($s2)) * 1000);
}
//字符串中的中文转unicode
function chnToUnicode($str){
$unicode = '';
for ($i = 0; $i < mb_strlen($str); $i++){
$char = mb_substr($str, $i, 1);
if($char >=19968 && $char <=171941){
$unicode .= '\\u' . str_pad(bin2hex(iconv('UTF-8', 'UCS-2', $char)), 4, '0', STR_PAD_LEFT);
}else{
$unicode .= $char;
}
}
return $unicode;
}
//post提交
function curl_post($url,$params){
$rs=['code'=>0,'msg'=>'','info'=>[]];
$ch = curl_init(); // 启动一个CURL会话
curl_setopt($ch, CURLOPT_URL, $url); // 要访问的地址
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 对认证证书来源的检查 // https请求 不验证证书和hosts
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // 从证书中检查SSL加密算法是否存在
//curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
//curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
//curl_setopt($ch, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
curl_setopt($ch, CURLOPT_POST, true); // 发送一个常规的Post请求
curl_setopt($ch, CURLOPT_POSTFIELDS, $params); // Post提交的数据包
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // 设置超时限制防止死循环
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
$header=['Content-Type: application/json'];
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); // 设置请求头部信息
//curl_setopt($ch, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 获取的信息以文件流的形式返回
$result = curl_exec($ch);
//var_dump("POST请求的返回结果");
//var_dump($result);
if(curl_errno($ch)){
$rs['code']=1001;
$rs['msg']='请求失败';
return $rs;
}
if(!isJsonString($result)){
$rs['code']=1002;
$rs['msg']=$result;
return $rs;
}
$result_arr = json_decode($result,true);
if($result_arr['ret']==0 && $result_arr['msg']=='success'){
$rs['info'][0]=$result_arr['result'];
return $rs;
}else{
$rs['code']=1003;
$rs['msg']=$result;
return $rs;
}
curl_close($ch);
}
//get提交
function curl_get($url){
$rs=['code'=>0,'msg'=>'','info'=>[]];
$header = array(
'Content-Type: application/json',
);
$curl = curl_init();
//设置抓取的url
curl_setopt($curl, CURLOPT_URL, $url);
//设置头文件的信息作为数据流输出
curl_setopt($curl, CURLOPT_HEADER, 0);
// 超时设置,以秒为单位
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
// 超时设置,以毫秒为单位
// curl_setopt($curl, CURLOPT_TIMEOUT_MS, 500);
// 设置请求头
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
//设置获取的信息以文件流的形式返回,而不是直接输出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
//执行命令
$result = curl_exec($curl);
// 显示错误信息
if (curl_error($curl)) {
$rs['code']=1001;
$rs['msg']='请求失败';
return $rs;
}
//var_dump("GET请求的返回结果");
//var_dump($result);
if(!isJsonString($result)){
$rs['code']=1002;
$rs['msg']=$result;
return $rs;
}
$result_arr = json_decode($result,true);
if($result_arr['ret']==0 && $result_arr['msg']=='success'){
$rs['info'][0]=$result_arr['result'];
return $rs;
}else{
$rs['code']=1003;
$rs['msg']=$result;
return $rs;
}
curl_close($curl);
}
/**
* 校验json字符串
* @param string $stringData
* @return bool
*/
function isJsonString($stringData){
if (empty($stringData)) return false;
try{
//校验json格式
json_decode($stringData, true);
return JSON_ERROR_NONE === json_last_error();
}
catch (\Exception $e)
{
return false;
}
}
/**
* @desc 移动云推拉流地址
* @param string $stream 流名
* @param int $type 类型,0表示播流,1表示推流
*/
function PrivateKey_ecloud($stream,$type){
$api_url='https://api.migucloud.com'; //根据自己应用所在区域进行更换
$stream_arr = explode('_',$stream);
$liveuid=$stream_arr[0];
$starttime=$stream_arr[1];
//推流
if($type==1){
//1:创建直播
$param=[
'title'=>'用户'.$liveuid,
'startTime'=>date('Y-m-d H:i:s',$starttime),
'endTime'=>date('Y-m-d H:i:s',$starttime+30*24*60*60),
'subject'=>'用户'.$liveuid.'直播',
'record'=>0,
'playMode'=>0,
'cdnType'=>0,
];
//获取签名token
$result_arr = getEcloudToken($param,'post');
//var_dump("请求签名后返回的参数");
//var_dump($result_arr);
$createroom_method='/l2/live/createChannel';
//带基础参数
$request_url=$api_url.$createroom_method.'?'.$result_arr['raw_sign'];
//var_dump("请求创建直播接口的地址");
//var_dump($request_url);
$param['title']=chnToUnicode($param['title']);
$param['subject']=chnToUnicode($param['subject']);
//var_dump("进行POST请求时,传递的业务参数:");
//var_dump($param);
$result = curl_post($request_url,json_encode($param));
if($result['code'] !=0){
$url='';
return $url;
}
$channelId=$result['info'][0]['channelId'];
//var_dump("直播频道id");
//var_dump($channelId);
//2:获取推流地址
$param=[
'channel_id'=>$channelId
];
//获取签名token
$result_arr = getEcloudToken($param,'get');
$getpushurl_method='/l2/addr/getPushUrl';
//带基础参数
$request_url=$api_url.$getpushurl_method.'?'.$result_arr['raw_sign'];
//var_dump("请求获取推流接口的地址");
//var_dump($request_url);
$result = curl_get($request_url);
if($result['code'] !=0){
$url='';
return $url;
}
$push_url=$result['info'][0]['cameraList'][0]['url'];
//var_dump("推流地址");
//var_dump($push_url);
return ['channel_id'=>$channelId,'push_url'=>$push_url];
//播流
}else{
$channel_id=''; //创建直播接口返回的channelId
$param=[
'channel_id'=>$channel_id
];
//获取签名token
$result_arr = getEcloudToken($param,'get');
//var_dump("请求签名后返回的参数");
//var_dump($result_arr);
$getpullurl_method='/l2/addr/getPullUrl';
//带基础参数
$request_url=$api_url.$getpullurl_method.'?'.$result_arr['raw_sign'];
//var_dump("请求获取播流接口的地址");
//var_dump($request_url);
$result = curl_get($request_url);
if($result['code'] !=0){
$url='';
return $url;
}
$pull_url=$result['info'][0]['cameraList'][0]['transcodeList'][0]['urlRtmp'];
//var_dump("播流地址");
//var_dump($pull_url);
return $pull_url;
}
}
//删除直播
function removeChannel($channel_id){
$param=['id'=>$channel_id];
$result_arr = getEcloudToken($param,'post');
$removechannel_method='/l2/live/removeChannel';
$api_url='https://api.migucloud.com'; //根据自己应用所在地区替换
$request_url=$api_url.$removechannel_method.'?'.$result_arr['raw_sign'];
$result = curl_post($request_url,json_encode($param));
}
调用方法:
获取推流地址:
$stream='1001_1698291555';
PrivateKey_ecloud($stream,1);
返回创建开播参数截图:
截图中请求创建开播的API地址:
https://api.migucloud.com/l2/live/createChannel?apiId=200001¤tTimeStamp=1698460266645&expired=1698503466645&grant_type=v2.0&random=53415941&secretId=69a7c3a1fd52a584d8fd79a0118b8173&token=752556e89b8af7b572da0d701389d0eedb61df523a1b192a37bd608fd460b014&uid=800000234
返回获取推流地址截图:
截图中请求获取推流的API地址:
https://api.migucloud.com/l2/addr/getPushUrl?apiId=200001&channel_id=20231028103106_BNDEKC9U¤tTimeStamp=1698460266888&expired=1698503466888&grant_type=v2.0&random=08691557&secretId=69a7c3a1fd52a584d8fd79a0118b8173&token=6d9ddbab6dbc3d3d35afd051296448bddba90e2acf3ca7057c4c9bb6b3cabad9&uid=800000234
获取播流地址:
$stream='1001_1698291555';
PrivateKey_ecloud($stream,0);
返回获取播流地址截图:
截图中请求获取播流的API地址:
https://api.migucloud.com/l2/addr/getPullUrl?apiId=200001&channel_id=20231028103106_BNDEKC9U¤tTimeStamp=1698463713230&expired=1698506913230&grant_type=v2.0&random=62397059&secretId=69a7c3a1fd52a584d8fd79a0118b8173&token=b4b4a6a30621bfdc6f7f6c66a00ab1bc8588125c3b5861e430b9d21605b2c75e&uid=800000234
截图中返回的结果:
{"ret":"0","msg":"success","result":{"uid":"800000234","channelId":"20231028103106_BNDEKC9U","imgUrl":"","cdnType":0,"viewerNum":0,"urlTimeshift":null,"cameraList":[{"camIndex":"C0","transcodeList":[{"transType":"0","urlRtmp":"rtmp://devlivepull.migucloud.com/live/BNDEKC9U_C0","urlHls":"http://wshls.live.migucloud.com/live/BNDEKC9U_C0/playlist.m3u8","urlFlv":"http://devlivepull.migucloud.com/live/BNDEKC9U_C0.flv","transCode":"Wating","transDesc":"等待中"}]}]}}