LiveingController.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888
  1. <?php
  2. // +—————————————————————————————————————————————————————————————————————
  3. // | Created by Yunbao
  4. // +—————————————————————————————————————————————————————————————————————
  5. // | Copyright (c) 2013~2022 http://www.yunbaokj.com All rights reserved.
  6. // +—————————————————————————————————————————————————————————————————————
  7. // | Author: https://gitee.com/yunbaokeji
  8. // +—————————————————————————————————————————————————————————————————————
  9. // | Date: 2022-02-17
  10. // +—————————————————————————————————————————————————————————————————————
  11. /**
  12. * 直播列表
  13. */
  14. namespace app\admin\controller;
  15. require CMF_ROOT . 'vendor/tencentcloud/vendor/autoload.php';
  16. use cmf\controller\AdminBaseController;
  17. use TencentCloud\Live\V20180801\Models\DescribeLivePullStreamTasksRequest;
  18. use TencentCloud\Live\V20180801\Models\DescribeLiveStreamOnlineListRequest;
  19. use TencentCloud\Live\V20180801\Models\DescribeLiveStreamPublishedListRequest;
  20. use think\Db;
  21. // 根据腾讯云sdk请求 创建直播拉流
  22. use TencentCloud\Live\V20180801\Models\CreateLivePullStreamTaskRequest;
  23. use TencentCloud\Live\V20180801\Models\DeleteLivePullStreamTaskRequest;
  24. use TencentCloud\Common\Exception\TencentCloudSDKException;
  25. use TencentCloud\Common\Credential;
  26. use TencentCloud\Common\Profile\ClientProfile;
  27. use TencentCloud\Common\Profile\HttpProfile;
  28. use TencentCloud\Live\V20180801\LiveClient;
  29. use think\Exception;
  30. use think\exception\PDOException;
  31. class LiveingController extends AdminbaseController {
  32. private $secretId = 'AKID575vicM9rU6iBiWJNi09HF8xhMxOk4Od';
  33. private $secretKey = 'MiDkHwgOFpMpGf2KXcZIo9MYY5qnmhU5';
  34. private $pushDomain = 'push.umotool.com';
  35. private $pushKey = 'd79106bd037188b132bc2d4cc272aa98';
  36. private $pullKey = 'JYthadi3fG4C4fbdmF6R';
  37. private $pullDomain = 'tintonkangdahotel.com';
  38. protected function getLiveClass(){
  39. $liveclass=Db::name("live_class")->order('list_order asc, id desc')->column('id,name');
  40. return $liveclass;
  41. }
  42. protected function getTypes($k=''){
  43. $type=[
  44. '0'=>'普通房间',
  45. '1'=>'密码房间',
  46. '2'=>'门票房间',
  47. '3'=>'计时房间',
  48. ];
  49. if($k==''){
  50. return $type;
  51. }
  52. return $type[$k];
  53. }
  54. public function index(){
  55. $data = $this->request->param();
  56. $map=[];
  57. $map[]=['islive','=',1];
  58. $start_time=isset($data['start_time']) ? $data['start_time']: '';
  59. $end_time=isset($data['end_time']) ? $data['end_time']: '';
  60. if($start_time!=""){
  61. $map[]=['starttime','>=',strtotime($start_time)];
  62. }
  63. if($end_time!=""){
  64. $map[]=['starttime','<=',strtotime($end_time) + 60*60*24];
  65. }
  66. $uid=isset($data['uid']) ? $data['uid']: '';
  67. if($uid!=''){
  68. $lianguid=getLianguser($uid);
  69. if($lianguid){
  70. $map[]=['uid',['=',$uid],['in',$lianguid],'or'];
  71. }else{
  72. $map[]=['uid','=',$uid];
  73. }
  74. }
  75. $this->configpri=getConfigPri();
  76. $lists = Db::name("live")
  77. ->where($map)
  78. ->order("starttime DESC")
  79. ->paginate(20);
  80. $lists->each(function($v,$k){
  81. $v['userinfo']=getUserInfo($v['uid']);
  82. $where=[];
  83. $where['action']=1;
  84. $where['touid']=$v['uid'];
  85. $where['showid']=$v['showid'];
  86. /* 本场总收益 */
  87. $totalcoin=Db::name("user_coinrecord")->where($where)->sum('totalcoin');
  88. if(!$totalcoin){
  89. $totalcoin=0;
  90. }
  91. /* 送礼物总人数 */
  92. $total_nums=Db::name("user_coinrecord")->where($where)->group("uid")->count();
  93. if(!$total_nums){
  94. $total_nums=0;
  95. }
  96. /* 人均 */
  97. $total_average=0;
  98. if($totalcoin && $total_nums){
  99. $total_average=round($totalcoin/$total_nums,2);
  100. }
  101. /* 人数 */
  102. $nums=zSize('user_'.$v['stream']);
  103. $v['totalcoin']=$totalcoin;
  104. $v['total_nums']=$total_nums;
  105. $v['total_average']=$total_average;
  106. $v['nums']=$nums;
  107. if($v['isvideo']==0 && $this->configpri['cdn_switch']!=5){
  108. $v['pull']=PrivateKeyA('rtmp',$v['stream'],0);
  109. }
  110. return $v;
  111. });
  112. $lists->appends($data);
  113. $page = $lists->render();
  114. $liveclass=$this->getLiveClass();
  115. $liveclass[0]='默认分类';
  116. $this->assign('lists', $lists);
  117. $this->assign("page", $page);
  118. $this->assign("liveclass", $liveclass);
  119. $this->assign("type", $this->getTypes());
  120. return $this->fetch();
  121. }
  122. public function getLivePushUrl(){
  123. $uid = $_POST['uid'] ?? ''; // 从 POST 请求中获取 uid 值
  124. if (empty($uid)) {
  125. echo "请输入UID";
  126. } elseif (!is_numeric($uid)) {
  127. echo "UID必须是数字";
  128. } else {
  129. $tx_push = cmf_get_option('configpri')['tx_push'];
  130. $push_url = 'rtmp://' . $tx_push.'/live/'.$uid;
  131. $pull_key = cmf_get_option('configpri')['tx_play_key'];
  132. try {
  133. // 为了保护密钥安全,建议将密钥设置在环境变量中或者配置文件中。
  134. // 硬编码密钥到代码中有可能随代码泄露而暴露,有安全隐患,并不推荐。
  135. // $cred = new Credential("SecretId", "SecretKey");
  136. $cred = new Credential("AKID575vicM9rU6iBiWJNi09HF8xhMxOk4Od",
  137. "MiDkHwgOFpMpGf2KXcZIo9MYY5qnmhU5");
  138. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  139. $httpProfile = new HttpProfile();
  140. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  141. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  142. $clientProfile = new ClientProfile();
  143. $clientProfile->setHttpProfile( $httpProfile );
  144. // 实例化要请求产品的client对象,clientProfile是可选的
  145. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  146. // 实例化一个请求对象,每个接口都会对应一个request对象
  147. $req = new CreateLivePullStreamTaskRequest();
  148. $timestamp = time();
  149. //播放链接限制10分钟 60*10 一天 60*60*24
  150. $end_timestamp = time() + 60*60*24;
  151. $txTime = strtoupper(base_convert($end_timestamp, 10, 16));
  152. $txSecret = md5( $pull_key . $uid . $txTime );
  153. $params = array(
  154. "SourceType" => "PullLivePushLive",
  155. "SourceUrls" => [
  156. 'https://tintonkangdahotel.com/live/'.$uid.'.flv',
  157. ],
  158. "DomainName" => 'push.umotool.com',
  159. "PushArgs" => 'txSecret='.$txSecret.'&txTime='.$txTime,
  160. "AppName" => 'live',
  161. "StreamName" => $uid,
  162. "StartTime" => gmdate("Y-m-d\TH:i:s\Z", $timestamp),
  163. "EndTime" => gmdate("Y-m-d\TH:i:s\Z", $end_timestamp),
  164. "Operator" => 'tom001',
  165. );
  166. $req->fromJsonString( json_encode( $params ) );
  167. // 返回的resp是一个CreateLivePullStreamTaskResponse的实例,与请求对象对应
  168. $resp = $client->CreateLivePullStreamTask( $req );
  169. // 推流地址、播流地址、taskId
  170. $data['push'] = 'rtmp://push.umotool.com/live/'. $uid . '?' .$params['PushArgs'];
  171. $pull_urls = $this->getPullUrl( 'live', $uid, $end_timestamp );
  172. $data['pull'] = $pull_urls[1];
  173. $data['TaskId'] = $resp->TaskId;
  174. echo json_encode( $data , JSON_UNESCAPED_UNICODE );
  175. }
  176. catch(TencentCloudSDKException $e) {
  177. echo $e;
  178. }
  179. }
  180. }
  181. public function xiabo()
  182. {
  183. $uid = $_POST['uid'];
  184. $TaskId = $_POST['TaskId'];
  185. if (empty($uid) || empty($TaskId)) {
  186. echo "请输入 TaskId";
  187. } elseif (!is_numeric($uid) || !is_numeric($TaskId)) {
  188. echo "TaskId 必须是数字";
  189. } else {
  190. require CMF_ROOT . 'vendor/tencentcloud/vendor/autoload.php';
  191. try {
  192. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  193. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。密钥可前往官网控制台 https://console.tencentcloud.com/capi 进行获取
  194. $cred = new Credential("AKID575vicM9rU6iBiWJNi09HF8xhMxOk4Od",
  195. "MiDkHwgOFpMpGf2KXcZIo9MYY5qnmhU5");
  196. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  197. $httpProfile = new HttpProfile();
  198. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  199. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  200. $clientProfile = new ClientProfile();
  201. $clientProfile->setHttpProfile( $httpProfile );
  202. // 实例化要请求产品的client对象,clientProfile是可选的
  203. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  204. // 实例化一个请求对象,每个接口都会对应一个request对象
  205. $req = new DeleteLivePullStreamTaskRequest();
  206. $params = array(
  207. "TaskId" => $TaskId,
  208. "Operator" => "tom001"
  209. );
  210. $req->fromJsonString( json_encode( $params ) );
  211. // 返回的resp是一个DeleteLivePullStreamTaskResponse的实例,与请求对象对应
  212. $resp = $client->DeleteLivePullStreamTask( $req );
  213. // 输出json格式的字符串回包
  214. $json = $resp->toJsonString();
  215. $data['uid'] = $uid;
  216. $data['TaskId'] = '已下播-'.$TaskId;
  217. $rs = DB::name('live')->update($data);
  218. // return $json;
  219. return json_decode( $json, 1 );
  220. } catch ( TencentCloudSDKException $e ) {
  221. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  222. } catch ( PDOException $e ) {
  223. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  224. }catch ( Exception $e ) {
  225. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  226. }
  227. }
  228. }
  229. public function del(){
  230. $uid = $this->request->param('uid', 0, 'intval');
  231. $rs = DB::name('live')->where("uid={$uid}")->delete();
  232. if(!$rs){
  233. $this->error("删除失败!");
  234. }
  235. $this->success("删除成功!",url("liveing/index"));
  236. }
  237. public function add(){
  238. $this->assign("liveclass", $this->getLiveClass());
  239. $this->assign("type", $this->getTypes());
  240. return $this->fetch();
  241. }
  242. public function addPost(){
  243. if ($this->request->isPost()) {
  244. $data = $this->request->param();
  245. $nowtime=time();
  246. $uid=$data['uid'];
  247. $userinfo=DB::name('user')->field("ishot")->where(["id"=>$uid,"user_type"=>2])->find();
  248. if(!$userinfo){
  249. $this->error('用户不存在');
  250. }
  251. $liveinfo=DB::name('live')->field('uid,islive')->where(["uid"=>$uid])->find();
  252. if($liveinfo['islive']==1){
  253. $this->error('该用户正在直播');
  254. }
  255. $TaskId=$data['TaskId'];
  256. // $pull=urldecode($data['pull']);
  257. // $push=urldecode($data['push']);
  258. $pull=$data['pull'];
  259. $push=$data['push'];
  260. $type=$data['type'];
  261. $type_val=$data['type_val'];
  262. $anyway=$data['anyway'];
  263. $liveclassid=$data['liveclassid'];
  264. $stream=$uid.'_'.$nowtime;
  265. $title='';
  266. $data2=array(
  267. "uid"=>$uid,
  268. "showid"=>$nowtime,
  269. "starttime"=>$nowtime,
  270. "title"=>$title,
  271. "province"=>'',
  272. "city"=>'好像在火星',
  273. "stream"=>$stream,
  274. "thumb"=>'',
  275. "TaskId"=>$TaskId,
  276. "pull"=>$pull,
  277. "push"=>$push,
  278. "lng"=>'',
  279. "lat"=>'',
  280. "type"=>$type,
  281. "type_val"=>$type_val,
  282. "isvideo"=>1,
  283. "islive"=>1,
  284. "anyway"=>$anyway,
  285. "liveclassid"=>$liveclassid,
  286. );
  287. if($liveinfo){
  288. $rs = DB::name('live')->update($data2);
  289. }else{
  290. $rs = DB::name('live')->insertGetId($data2);
  291. }
  292. if($rs===false){
  293. $this->error("添加失败!");
  294. }
  295. $this->success("添加成功!");
  296. }
  297. }
  298. public function edit(){
  299. $uid = $this->request->param('uid', 0, 'intval');
  300. $data=Db::name('live')
  301. ->where("uid={$uid}")
  302. ->find();
  303. if(!$data){
  304. $this->error("信息错误");
  305. }
  306. $this->assign('data', $data);
  307. $this->assign("liveclass", $this->getLiveClass());
  308. $this->assign("type", $this->getTypes());
  309. return $this->fetch();
  310. }
  311. public function editPost(){
  312. if ($this->request->isPost()) {
  313. $data = $this->request->param();
  314. // $data['pull']=urldecode($data['pull']);
  315. // $data['push']=urldecode($data['push']);
  316. $rs = DB::name('live')->update($data);
  317. if($rs===false){
  318. $this->error("修改失败!");
  319. }
  320. $this->success("修改成功!");
  321. }
  322. }
  323. /**
  324. * 获取推流地址
  325. * 如果不传key和过期时间,将返回不含防盗链的url
  326. * @param domain 您用来推流的域名
  327. * streamName 您用来区别不同推流地址的唯一流名称
  328. * key 安全密钥
  329. * time 过期时间 sample 2016-11-12 12:00:00
  330. * @return String url
  331. */
  332. public function getPushUrl( $appName, $streamName, $time ): string
  333. {
  334. $domain = $this->pushDomain;
  335. $key = $this->pushKey;
  336. $txTime = strtoupper( base_convert( $time, 10, 16 ) );
  337. //txSecret = MD5( KEY + streamName + txTime )
  338. $txSecret = md5( $key . $streamName . $txTime );
  339. return "?" . http_build_query( array(
  340. "txSecret" => $txSecret,
  341. "txTime" => $txTime
  342. ) );
  343. // return $domain . ( $ext_str ?? "" );
  344. }
  345. public function getPullUrl( $appName, $streamName, $time ): array
  346. {
  347. $domain = $this->pullDomain;
  348. $key = $this->pullKey;
  349. $txTime = strtoupper( base_convert( $time , 10, 16 ) );
  350. //txSecret = MD5( KEY + streamName + txTime )
  351. $txSecret = md5( $key . $streamName . $txTime );
  352. $build_data = [
  353. "txSecret" => $txSecret,
  354. "txTime" => $txTime
  355. ];
  356. $ext_str = "?" . http_build_query( $build_data );
  357. return [
  358. "rtmp://" . $domain . "/" . $appName . "/" . $streamName . $ext_str,
  359. "https://" . $domain . "/" . $appName . "/" . $streamName . ".m3u8" . $ext_str,
  360. "https://" . $domain . "/" . $appName . "/" . $streamName . ".flv" . $ext_str
  361. ];
  362. }
  363. public function getPullUrl2( $appName, $streamName, $time )
  364. {
  365. $domain = $this->pullDomain;
  366. $key = $this->pullKey;
  367. $txTime = strtoupper( base_convert( strtotime( $time ), 10, 16 ) );
  368. //txSecret = MD5( KEY + streamName + txTime )
  369. $txSecret = md5( $key . $streamName . $txTime );
  370. $build_data = [
  371. "txSecret" => $txSecret,
  372. "txTime" => $txTime
  373. ];
  374. $ext_str = "?" . http_build_query( $build_data );
  375. return [
  376. "rtmp://" . $domain . "/" . $appName . "/" . $streamName,
  377. "https://" . $domain . "/" . $appName . "/" . $streamName . ".m3u8",
  378. "https://" . $domain . "/" . $appName . "/" . $streamName . ".flv"
  379. ];
  380. }
  381. /**
  382. * @param $sport_id
  383. * @param $live_data
  384. * @return false|void
  385. * 拉流转推
  386. */
  387. public function setRtmpGetHttp( $sport_id, $live_data ,$play_urls_count=2)
  388. {
  389. try {
  390. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  391. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
  392. // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
  393. $cred = new Credential( $this->secretId, $this->secretKey );
  394. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  395. $httpProfile = new HttpProfile();
  396. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  397. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  398. $clientProfile = new ClientProfile();
  399. $clientProfile->setHttpProfile( $httpProfile );
  400. // 实例化要请求产品的client对象,clientProfile是可选的
  401. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  402. // 实例化一个请求对象,每个接口都会对应一个request对象
  403. $req = new CreateLivePullStreamTaskRequest();
  404. $SourceUrls = [];
  405. if(count($live_data[ 'urls' ]) == 1)
  406. {
  407. $SourceUrls[] = $live_data[ 'urls' ][0]['m3u8'];
  408. }else{
  409. if(!empty($live_data[ 'urls' ][$play_urls_count]['flv']))
  410. {
  411. $SourceUrls[] = $live_data[ 'urls' ][$play_urls_count]['flv'];
  412. }else{
  413. foreach ( $live_data[ 'urls' ] as $item ) {
  414. if ( !empty( $item[ 'flv' ] && empty( $SourceUrls ) ) ) {
  415. $SourceUrls[] = $item[ 'flv' ];
  416. }
  417. }
  418. }
  419. }
  420. if ( empty( $SourceUrls ) ) {
  421. return false;
  422. }
  423. $AppName = 'sport_test_live';
  424. $StreamName = 'sport_test_live_' . $sport_id;
  425. $now = time();
  426. $_now = $this->getNow( $live_data );
  427. $time = date( 'Y-m-d H:i:s', $_now );
  428. $StartTime = date( 'Y-m-d\TH:i:s\Z', ( $now - 28800 ) );
  429. $EndTime = date( 'Y-m-d\TH:i:s\Z', ( $_now - 28800 ) );
  430. $push_url = $this->getPushUrl( $AppName, $StreamName, $time );
  431. //播放链接限制10分钟
  432. $_time = date( 'Y-m-d H:i:s', time() + 600 );
  433. $pull_urls = $this->getPullUrl( $AppName, $StreamName, $_time );
  434. $params = array(
  435. "SourceType" => "PullLivePushLive",
  436. "SourceUrls" => $SourceUrls,
  437. "DomainName" => $this->pushDomain,
  438. "PushArgs" => $push_url,
  439. "AppName" => $AppName,
  440. "StreamName" => $StreamName,
  441. "StartTime" => $StartTime,
  442. "EndTime" => $EndTime,
  443. "Operator" => 'tom001',
  444. );
  445. $req->fromJsonString( json_encode( $params ) );
  446. // 返回的resp是一个CreateLivePullStreamTaskResponse的实例,与请求对象对应
  447. $resp = $client->CreateLivePullStreamTask( $req );
  448. $v_data = [
  449. 'tencent_res' => json_decode( json_encode( $resp ), 1 ),
  450. 'play_urls' => $pull_urls
  451. ];
  452. return $v_data;
  453. } catch ( TencentCloudSDKException $e ) {
  454. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  455. }
  456. }
  457. public function getNow( $live_data )
  458. {
  459. $start_time = $live_data[ 'kickoffTS' ] + ( 12 * 60 * 60 );
  460. if ( $start_time >= time() ) {
  461. return ( $start_time + 10800 );
  462. }
  463. $sy_time = time() - $start_time;
  464. $zy = 10800 - $sy_time;
  465. if ( $sy_time > 9500 ) {
  466. $add_time = time() + 1800;
  467. } else {
  468. $add_time = time() + $zy;
  469. }
  470. return $add_time;
  471. }
  472. public function upRtmpGetHttp( $sport_id, $live_data, $taskId )
  473. {
  474. try {
  475. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  476. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。密钥可前往官网控制台 https://console.tencentcloud.com/capi 进行获取
  477. $cred = new Credential( $this->secretId, $this->secretKey );
  478. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  479. $httpProfile = new HttpProfile();
  480. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  481. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  482. $clientProfile = new ClientProfile();
  483. $clientProfile->setHttpProfile( $httpProfile );
  484. // 实例化要请求产品的client对象,clientProfile是可选的
  485. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  486. // 实例化一个请求对象,每个接口都会对应一个request对象
  487. $req = new ModifyLivePullStreamTaskRequest();
  488. $SourceUrls = [];
  489. foreach ( $live_data as $item ) {
  490. if ( !empty( $item[ 'm3u8' ] && empty( $SourceUrls ) ) ) {
  491. $SourceUrls[] = $item[ 'm3u8' ];
  492. }
  493. }
  494. if ( empty( $SourceUrls ) ) {
  495. return false;
  496. }
  497. $AppName = 'sport_test_live';
  498. $StreamName = 'sport_test_live_' . $sport_id;
  499. $now = time();
  500. $_now = time() + 600;
  501. $time = date( 'Y-m-d H:i:s', $_now );
  502. $StartTime = date( 'Y-m-d\TH:i:s\Z', ( $now - 28800 ) );
  503. $EndTime = date( 'Y-m-d\TH:i:s\Z', ( $_now - 28800 ) );
  504. $pull_urls = $this->getPullUrl( $AppName, $StreamName, $time );
  505. $params = array(
  506. "TaskId" => $taskId,
  507. "SourceUrls" => $SourceUrls,
  508. "StartTime" => $StartTime,
  509. "EndTime" => $EndTime,
  510. "Operator" => 'tom001',
  511. );
  512. $req->fromJsonString( json_encode( $params ) );
  513. // 返回的resp是一个ModifyLivePullStreamTaskResponse的实例,与请求对象对应
  514. $resp = $client->ModifyLivePullStreamTask( $req );
  515. $v_data = [
  516. 'tencent_res' => json_decode( json_encode( $resp ), 1 ),
  517. 'play_urls' => $pull_urls
  518. ];
  519. // 输出json格式的字符串回包
  520. return $v_data;
  521. // 输出json格式的字符串回包
  522. // print_r( $resp->toJsonString() );
  523. } catch ( TencentCloudSDKException $e ) {
  524. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  525. }
  526. }
  527. public function upRtmpGetHttpUrl( $sport_id )
  528. {
  529. $AppName = 'sport_test_live';
  530. $StreamName = 'sport_test_live_' . $sport_id;
  531. $_now = time() + 600;
  532. $time = date( 'Y-m-d H:i:s', $_now );
  533. $pull_urls = $this->getPullUrl( $AppName, $StreamName, $time );
  534. return $pull_urls;
  535. }
  536. public function delSportExpired( $taskId )
  537. {
  538. try {
  539. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  540. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。密钥可前往官网控制台 https://console.tencentcloud.com/capi 进行获取
  541. $cred = new Credential( $this->secretId, $this->secretKey );
  542. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  543. $httpProfile = new HttpProfile();
  544. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  545. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  546. $clientProfile = new ClientProfile();
  547. $clientProfile->setHttpProfile( $httpProfile );
  548. // 实例化要请求产品的client对象,clientProfile是可选的
  549. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  550. // 实例化一个请求对象,每个接口都会对应一个request对象
  551. $req = new DeleteLivePullStreamTaskRequest();
  552. $params = array(
  553. "TaskId" => $taskId,
  554. "Operator" => "tom001"
  555. );
  556. $req->fromJsonString( json_encode( $params ) );
  557. // 返回的resp是一个DeleteLivePullStreamTaskResponse的实例,与请求对象对应
  558. $resp = $client->DeleteLivePullStreamTask( $req );
  559. // 输出json格式的字符串回包
  560. $json = $resp->toJsonString();
  561. return json_decode( $json, 1 );
  562. } catch ( TencentCloudSDKException $e ) {
  563. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  564. }
  565. }
  566. public function getLiveAll( $page = 1, $limit = 20, $liveid = '' )
  567. {
  568. try {
  569. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  570. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。密钥可前往官网控制台 https://console.tencentcloud.com/capi 进行获取
  571. $cred = new Credential( $this->secretId, $this->secretKey );
  572. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  573. $httpProfile = new HttpProfile();
  574. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  575. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  576. $clientProfile = new ClientProfile();
  577. $clientProfile->setHttpProfile( $httpProfile );
  578. // 实例化要请求产品的client对象,clientProfile是可选的
  579. $client = new LiveClient( $cred, "ap-bangkok", $clientProfile );
  580. // 实例化一个请求对象,每个接口都会对应一个request对象
  581. $req = new DescribeLivePullStreamTasksRequest();
  582. $params = [
  583. 'PageNum' => $page,
  584. 'PageSize' => $limit
  585. ];
  586. if ( $liveid ) {
  587. $params[ 'TaskId' ] = $liveid;
  588. }
  589. $req->fromJsonString( json_encode( $params ) );
  590. // 返回的resp是一个DescribeLivePullStreamTasksResponse的实例,与请求对象对应
  591. $resp = $client->DescribeLivePullStreamTasks( $req );
  592. // 输出json格式的字符串回包
  593. return json_decode( $resp->toJsonString(), 1 );
  594. } catch ( TencentCloudSDKException $e ) {
  595. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  596. }
  597. }
  598. public function getLiveOnlineList( $page = 1, $limit = 100, $AppName = 'A-live' )
  599. {
  600. try {
  601. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  602. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
  603. // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
  604. $cred = new Credential( $this->secretId, $this->secretKey );
  605. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  606. $httpProfile = new HttpProfile();
  607. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  608. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  609. $clientProfile = new ClientProfile();
  610. $clientProfile->setHttpProfile( $httpProfile );
  611. // 实例化要请求产品的client对象,clientProfile是可选的
  612. $client = new LiveClient( $cred, "", $clientProfile );
  613. // 实例化一个请求对象,每个接口都会对应一个request对象
  614. $req = new DescribeLiveStreamOnlineListRequest();
  615. $params = array(
  616. "AppName" => $AppName,
  617. "PageNum" => $page,
  618. "PageSize" => $limit
  619. );
  620. $req->fromJsonString( json_encode( $params ) );
  621. // 返回的resp是一个DescribeLiveStreamOnlineListResponse的实例,与请求对象对应
  622. $resp = $client->DescribeLiveStreamOnlineList( $req );
  623. return json_decode( $resp->toJsonString(), 1 );
  624. } catch ( TencentCloudSDKException $e ) {
  625. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  626. }
  627. }
  628. public function getLiveStreamPublishedList( $AppName = 'A-live', $StreamName = '' )
  629. {
  630. try {
  631. // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
  632. // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
  633. // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
  634. $cred = new Credential( $this->secretId, $this->secretKey );
  635. // 实例化一个http选项,可选的,没有特殊需求可以跳过
  636. $httpProfile = new HttpProfile();
  637. $httpProfile->setEndpoint( "live.tencentcloudapi.com" );
  638. // 实例化一个client选项,可选的,没有特殊需求可以跳过
  639. $clientProfile = new ClientProfile();
  640. $clientProfile->setHttpProfile( $httpProfile );
  641. // 实例化要请求产品的client对象,clientProfile是可选的
  642. $client = new LiveClient( $cred, "", $clientProfile );
  643. // 实例化一个请求对象,每个接口都会对应一个request对象
  644. $req = new DescribeLiveStreamPublishedListRequest();
  645. $now = time();
  646. $StartTime = date( 'Y-m-d\TH:i:s\Z', ( $now - 86400 ) );
  647. $EndTime = date( 'Y-m-d\TH:i:s\Z', $now );
  648. $params = array(
  649. 'DomainName' => $this->pushDomain,
  650. "StartTime" => $StartTime,
  651. "EndTime" => $EndTime,
  652. "AppName" => $AppName
  653. );
  654. if ( !empty( $StreamName ) ) {
  655. $params[ 'StreamName' ] = $StreamName;
  656. }
  657. $req->fromJsonString( json_encode( $params ) );
  658. // 返回的resp是一个DescribeLiveStreamPublishedListResponse的实例,与请求对象对应
  659. $resp = $client->DescribeLiveStreamPublishedList( $req );
  660. return json_decode( $resp->toJsonString(), 1 );
  661. } catch ( TencentCloudSDKException $e ) {
  662. return [ 'ode' => $e->getCode(), 'msg' => $e->getMessage() ];
  663. }
  664. }
  665. public function startAnchorRtmp( $roomid, $sportId )
  666. {
  667. $AppName = 'A-live';
  668. $StreamName = 'A-live-' . $roomid . '-' . $sportId;
  669. $now = time();
  670. //推球时间 过期时间是 12个小时
  671. $start_time = date( 'Y-m-d H:i:s', $now + ( 12 * 60 * 60 ) );
  672. //播放链接 有效时间是10分钟,每5分钟更新一次
  673. $end_time = date( 'Y-m-d H:i:s', $now + 600 );
  674. $ext_str = $this->getPushUrl( $AppName, $StreamName, $start_time );
  675. $rtmpPushUrl = "rtmp://" . $this->pushDomain . "/" . $AppName . "/" . $StreamName . $ext_str;
  676. $rtmp_push_url = "rtmp://" . $this->pushDomain . "/" . $AppName . "/";
  677. $rtmp_push_code = $StreamName . $ext_str;
  678. $pull_urls = $this->getPullUrl2( $AppName, $StreamName, $end_time );
  679. $urls = [
  680. 'rtmp_push_url' => $rtmp_push_url,
  681. 'rtmp_push_code' => $rtmp_push_code,
  682. 'rtmp_push' => $rtmpPushUrl,
  683. 'hls_pull' => $pull_urls[ 1 ],
  684. 'http_pull' => $pull_urls[ 2 ],
  685. 'rtmp_pull' => $pull_urls[ 0 ],
  686. ];
  687. return [
  688. 'code' => 0,
  689. 'data' => $urls
  690. ];
  691. }
  692. }