此示例使用的是腾讯云的云直播接口。本签名方法为v3,此封装方法简单、易用。无需引入任何文件。
视频格式参考文档:腾讯云直播文档
namespace app\home\controller;
class LiveController extends PortControllerBase
{
const secretId = '换成你自己的secretId ';
const secretKey = '换成你自己的secretKey ';
const pushKey = '推流鉴权key';//在推流域名->推流配置中查看
const pushUrl = '推流域名';
const playKey = '拉流鉴权key';//如果拉流域名没有开启拉流鉴权,则不需要使用此参数
const playUrl = '拉流域名';
/**
* 获取推/拉流地址
* @return String url
*/
public function getLiveUrl(){
static $streamName = 'star';//流名称
$params = vae_get_param();
if( empty($params['type']) ){
return $this->port( 1 , '参数异常' );
}
if( $params['type'] == 'push' ){
$domain = self::pushUrl;
} else {
$domain = self::playUrl;
}
//这里过期时间默认设置为1天
$time = date( "Y-m-d H:i:s" , strtotime( '+1 day') );
$txTime = strtoupper(base_convert(strtotime($time),10,16));
//这里的 self::pushKey 默认使用的是推流鉴权key,生成拉流地址时需要使用拉流key
$txSecret = md5(self::pushKey.$streamName.$txTime);
$ext_str = "?".http_build_query(array(
"txSecret"=> $txSecret,
"txTime"=> $txTime
));
//这里的地址推流地址前缀都为 "rtmp://" ,拉流地址前缀会根据你想要的视频格式而不同,具体参考上方的腾讯云文档
return "rtmp://".$domain."/live/".$streamName . (isset($ext_str) ? $ext_str : "");
}
//查询某个直播状态
public function getLiveStatus(){
$params = vae_get_param();
if( !intval($params['teacher_id']) ){
return $this->port( 1 , '参数异常' );
}
//参数说明可参考腾讯云直播查询直播状态接口文档
$data = [
'AppName' => 'live',
'DomainName' => self::playUrl,//播放域名
'StreamName' => 'star'
];
//生成签名并调用接口
$request = self::requestWithResult( 'DescribeLiveStreamState' , '' , 'POST' , self::ArrToJson($data) );
$request = self::JsonToArr( $request );
if( !isset($request['Response']['Error']) ) {
$message = '';
switch ($request['Response']['StreamState']){
case 'active':
$message = '直播中';
break;
case 'inactive':
$message = '未开播';
break;
case 'forbid':
$message = '禁播';
break;
}
return $this->port( 0 , $message );
} else {
return $this->port( 1 , '获取失败' );
}
}
/***
* 生成签名并调用接口
* @param string $action 请求的方法名称
* @param string $region 地域参数
* @param string $method 请求方式
* @param string $payLoad 请求携带的参数
* @return Json 返回调用结果
*/
private static function requestWithResult( $action , $region = '' , $method = 'POST' , $payLoad = "{}" ){
//请求时间
$time = time();
//签名参数
$data = [
'time' => $time,
'credentialScope' => gmdate("Y-m-d", $time)."/live/tc3_request",
'host' => "live.tencentcloudapi.com",
'secretKey' => self::secretKey,
];
//请求参数
$params = [
'HTTPRequestMethod' => $method,//HTTP 请求方式
'CanonicalURI' => "/",//URI 参数,API 3.0 固定为正斜杠(/)
'CanonicalQueryString' => $method == 'GET' ? http_build_query( $payLoad ) : '',
'CanonicalHeaders' => "content-type:application/json\nhost:" . $data['host'] . "\n",//参与签名的头部信息,至少包含 host 和 content-type 两个头部
'SignedHeaders' => 'content-type;host',//参与签名的头部信息,说明此次请求有哪些头部参与了签名
'HashedRequestPayload' => hash( 'SHA256' , $payLoad ),//请求正文
];
//公共头部参数
$headers = [
'Content-Type:application/json',
'X-TC-Action:' . $action,
'X-TC-Timestamp:' . $data['time'],
'X-TC-Version:2018-08-01',
'X-TC-Language: zh-CN',
'Host:'.$data['host']
];
if( !empty($region) ){
$headers[] = 'X-TC-Region:' . $region;
}
//拼接请求串
$canonicalRequest = implode( "\n" , array_values( $params ) );
//拼接待签名字符串
$stringToSign = "TC3-HMAC-SHA256\n" .
$data['time']. "\n" .
$data['credentialScope']. "\n" .
hash( 'SHA256' , $canonicalRequest );
// print_r( $canonicalRequest );die;
//计算签名
$secretDate = hash_hmac("SHA256", gmdate("Y-m-d", $data['time']), "TC3".self::secretKey, true);
$secretService = hash_hmac("SHA256", "live", $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
$headers[] = 'Authorization:TC3-HMAC-SHA256 Credential=' . self::secretId . '/' . $data['credentialScope'] . ', SignedHeaders=content-type;host, Signature=' . $signature;
return curlRequest( 'https://' . $data['host'] , $payLoad , $headers );
}
//数组转json
private static function ArrToJson( $arr = [] ){
if( empty($arr) ){
return "{}";
}
return json_encode( $arr , 256 );
}
//json转数组
private static function JsonToArr( $json ){
if( empty($json) ){
return [];
}
return json_decode( $json , true );
}
}