AliyunLive.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. <?php
  2. namespace Api;
  3. class AliyunLive extends AliyunSdk
  4. {
  5. /**
  6. * 推流地址
  7. * @var string
  8. */
  9. protected $rtmpLink;
  10. /**
  11. * 播放地址
  12. * @var string
  13. */
  14. protected $playLike;
  15. /**
  16. * 推流Key
  17. * @var string
  18. */
  19. protected $key;
  20. /**
  21. * 播放key
  22. * @var string
  23. */
  24. protected $payKey;
  25. /**
  26. * 应用名
  27. * @var string
  28. */
  29. protected $appName;
  30. /**
  31. * OSS存储桶名
  32. * @var string
  33. */
  34. protected $OssBucket;
  35. /**
  36. * OSS存储外网访问域名
  37. * @var string
  38. */
  39. protected $OssEndpoint;
  40. /**
  41. * 自动加载阿里云类
  42. * @var array
  43. */
  44. protected $autoLoadPath = ['live'];
  45. /**
  46. * 实例化阿里云接口
  47. * */
  48. protected function _initialize()
  49. {
  50. $this->OssEndpoint = isset($this->config['OssEndpoint']) ? $this->config['OssEndpoint'] : null;
  51. $this->appName = isset($this->config['appName']) ? $this->config['appName'] : null;
  52. $this->OssBucket = isset($this->config['OssBucket']) ? $this->config['OssBucket'] : null;
  53. $this->payKey = isset($this->config['payKey']) ? $this->config['payKey'] : null;
  54. $this->key = isset($this->config['key']) ? $this->config['key'] : null;
  55. $this->playLike = isset($this->config['playLike']) ? $this->config['playLike'] : null;
  56. $this->rtmpLink = isset($this->config['rtmpLink']) ? $this->config['rtmpLink'] : null;
  57. $this->client = $this->client === null ?
  58. new \DefaultAcsClient(\DefaultProfile::getProfile("cn-hangzhou", $this->AccessKey, $this->AccessKeySecret)) :
  59. $this->client;
  60. }
  61. /**
  62. * 设置OSS存储桶名
  63. * @param string $OssBucket
  64. * @return $this
  65. * */
  66. public function setOssBucketAttr($OssBucket)
  67. {
  68. $this->OssBucket = $OssBucket;
  69. return $this;
  70. }
  71. /**
  72. * 设置OSS存储外网访问域名
  73. * @param string $OssEndpoint
  74. * @return $this
  75. * */
  76. public function setOssEndpointAttr($OssEndpoint)
  77. {
  78. $this->OssEndpoint = $OssEndpoint;
  79. return $this;
  80. }
  81. /**
  82. * 设置播放域名
  83. * @param string $PlayLike
  84. * @return $this
  85. * */
  86. public function setPlayLike($PlayLike)
  87. {
  88. $this->playLike = $PlayLike;
  89. return $this;
  90. }
  91. /**
  92. * 设置推流域名
  93. * @param string $rtmpLink
  94. * @return $this
  95. * */
  96. public function setRtmpLink($rtmpLink)
  97. {
  98. $this->rtmpLink = $rtmpLink;
  99. return $this;
  100. }
  101. /**
  102. * 设置应用名
  103. * @param string $AppName
  104. * @return $this
  105. * */
  106. public function setAppName($AppName)
  107. {
  108. $this->appName = $AppName;
  109. return $this;
  110. }
  111. /**
  112. * 获取直播间推流url和播放url
  113. * @param string $appName 直播间号
  114. * @param string $streamName 直播间号
  115. * @param int $expire 过期时间
  116. * @return array
  117. * */
  118. public function foundLiveStudio($streamName, $expire = 1800)
  119. {
  120. $time = time() + $expire;
  121. $LiveName = '/' . $this->appName . '/' . $streamName;
  122. //推流地址
  123. $pushUrl = 'rtmp://' . $this->rtmpLink . $LiveName . '?auth_key=' . md5($LiveName . '-' . $time . '-0-0-' . $this->key);
  124. //rtmp 播放地址
  125. $rtmpUrl = 'rtmp://' . $this->playLike . $LiveName . '?auth_key=' . md5($LiveName . '-' . $time . '-0-0-' . $this->payKey);
  126. //flv 播放地址
  127. $flvUrl = 'http://' . $this->playLike . $LiveName . '.flv?auth_key=' . md5($LiveName . '.flv-' . $time . '-0-0-' . $this->payKey);
  128. //m3u8 播放地址
  129. $m3u8Url = 'http://' . $this->playLike . $LiveName . '.m3u8?auth_key=' . md5($LiveName . '.m3u8-' . $time . '-0-0-' . $this->payKey);
  130. return compact('pushUrl', 'rtmpUrl', 'flvUrl', 'm3u8Url');
  131. }
  132. /**
  133. * 生成推流地址
  134. * @param string $streamName 直播间号码
  135. * @param boolean $complete 加速域名
  136. * @param int $time 有效时间单位秒
  137. * @return array
  138. */
  139. public function getPushSteam($streamName, $complete = false, $time = 1800)
  140. {
  141. $time = time() + $time;
  142. $videohost = $this->rtmpLink;
  143. $appName = $this->appName;
  144. $privateKey = $this->key;
  145. if ($privateKey) {
  146. $auth_key = md5("/{$appName}/{$streamName}-{$time}-0-0-{$privateKey}");
  147. if ($complete) {
  148. $url = "rtmp://{$videohost}/{$appName}/{$streamName}?auth_key={$time}-0-0-{$auth_key}";
  149. } else {
  150. $url['href'] = "rtmp://{$videohost}/{$appName}/";
  151. $url['code'] = "{$streamName}?auth_key={$time}-0-0-{$auth_key}";
  152. }
  153. } else {
  154. $url = $complete ? ['href' => "rtmp://{$videohost}/{$appName}/", 'code' => $streamName] : "rtmp://{$videohost}/{$appName}/{$streamName}";
  155. }
  156. return $url;
  157. }
  158. /**
  159. * 生成拉流地址
  160. * @param $streamName 用户专有名
  161. * @param $vhost 加速域名
  162. * @param $type 视频格式 支持rtmp、flv、m3u8三种格式
  163. */
  164. public function getPullSteam($streamName, $vhost = '', $time = 1800, $type = 'm3u8')
  165. {
  166. $time = time() + $time;
  167. $vhost = $vhost ? $vhost : $this->playLike;
  168. $appName = $this->appName;
  169. $privateKey = $this->payKey;
  170. $url = '';
  171. switch ($type) {
  172. case 'rtmp':
  173. $host = 'rtmp://' . $vhost;
  174. $url = "/{$appName}/{$streamName}";
  175. break;
  176. case 'flv':
  177. $host = 'http://' . $vhost;
  178. $url = "/{$appName}/{$streamName}.flv";
  179. break;
  180. case 'm3u8':
  181. $host = 'http://' . $vhost;
  182. $url = "/{$appName}/{$streamName}.m3u8";
  183. break;
  184. }
  185. if ($privateKey) {
  186. $auth_key = md5($url . '-' . $time . '-0-0-' . $privateKey);
  187. $url = $host . $url . "?auth_key={$time}-0-0-{$auth_key}";
  188. } else {
  189. $url = $host . $url;
  190. }
  191. return $url;
  192. }
  193. /**
  194. * 实时在线人数
  195. * @param string $streamName 直播房间号
  196. * @param string $actionName 执行动作
  197. * @return $this
  198. * */
  199. public function onlineUserNum($streamName, $actionName = __FUNCTION__)
  200. {
  201. $this->action[] = $actionName;
  202. $request = new \live\Request\V20161101\DescribeLiveStreamOnlineUserNumRequest();
  203. $this->request[$actionName] = $request->setDomainName($this->playLike)->setAppName($this->appName)->setStreamName($streamName);
  204. return $this;
  205. }
  206. /**
  207. * 恢复某个直播间
  208. * @param string $streamName 用户id
  209. * @param string $actionName 动作名称 默认本方法名
  210. * @return array
  211. * */
  212. public function resumeLive($streamName, $actionName = __FUNCTION__)
  213. {
  214. $this->action[] = $actionName;
  215. $request = new \live\Request\V20161101\ResumeLiveStreamRequest();
  216. $this->request[$actionName] = $request->setAppName($this->appName)->setLiveStreamType('publisher')->setDomainName($this->playLike)->setStreamName($streamName);
  217. return $this;
  218. }
  219. /**
  220. * 禁掉某个直播间
  221. * @param string $streamName 用户id
  222. * @param string $resumeTime 警用时间 时间格式 2015-12-01T17:37:00Z
  223. * @param string $actionName 动作名称 默认本方法名
  224. * @return array
  225. * */
  226. public function forbid($streamName, $resumeTime, $actionName = __FUNCTION__)
  227. {
  228. $this->action[] = $actionName;
  229. $request = new \live\Request\V20161101\ForbidLiveStreamRequest();
  230. $this->request[$actionName] = $request->setAppName($this->appName)->setLiveStreamType('publisher')->setDomainName($this->playLike)->setStreamName($streamName)->setResumeTime($resumeTime);
  231. return $this;
  232. }
  233. /**
  234. * 设置回调地址
  235. * @param string $notifyUrl 回调地址
  236. * @param string $actionName 动作名称 默认本方法名
  237. * @return $this
  238. * */
  239. public function setLiveNotifyUrl($notifyUrl, $actionName = __FUNCTION__)
  240. {
  241. $this->action[] = $actionName;
  242. $request = new \live\Request\V20161101\SetLiveStreamsNotifyUrlConfigRequest();
  243. $this->request[$actionName] = $request->setDomainName($this->playLike)->setNotifyUrl($notifyUrl);
  244. return $this;
  245. }
  246. /**
  247. * 手动录制直播间
  248. * @param string $StreamName 直播间号
  249. * @param boolean $CommandType 暂停 或 开始
  250. * @param string $actionName 动作名称 默认本方法名
  251. * @return $this
  252. * */
  253. public function liveRecording($StreamName, $CommandType = true, $actionName = __FUNCTION__)
  254. {
  255. $this->action[] = $actionName;
  256. $Command = $CommandType ? "start" : "stop";
  257. $request = new \live\Request\V20161101\RealTimeRecordCommandRequest();
  258. $this->request[$actionName] = $request->setDomainName($this->playLike)->setAppName($this->appName)->setStreamName($StreamName)->setCommand($Command);
  259. return $this;
  260. }
  261. /**
  262. * 添加录制回调
  263. * @param $onDemandUrl
  264. * @param string $actionName
  265. * @return $this
  266. */
  267. public function addLiveRecordNotifyConfig($onDemandUrl, $actionName = __FUNCTION__)
  268. {
  269. $this->action[] = $actionName;
  270. $request = new \live\Request\V20161101\AddLiveRecordNotifyConfigRequest();
  271. $this->request[$actionName] = $request->setDomainName($this->playLike)->setNotifyUrl($onDemandUrl)->setOnDemandUrl($onDemandUrl);
  272. return $this;
  273. }
  274. /**
  275. * 直播间录制配置
  276. * @param string $OnDemand 按需录制 0表示关闭。1表示通过HTTP回调方式 7表示默认不录制
  277. * @param int $CycleDuration 15-360 分钟
  278. * @return $this
  279. * */
  280. public function liveRecordConfig($Duration = 2, $OnDemand = 7, $actionName = __FUNCTION__)
  281. {
  282. $this->action[] = $actionName;
  283. $CycleDuration = $Duration * 3600;
  284. $request = new \live\Request\V20161101\AddLiveAppRecordConfigRequest();
  285. $this->request[$actionName] = $request->setDomainName($this->playLike)->setAppName($this->appName)
  286. ->setOssBucket($this->OssBucket)->setOssEndpoint($this->OssEndpoint)->setOnDemand($OnDemand)
  287. // ->setStartTime(self::setTimeFormat())->setEndTime(self::setTimeFormat(time() + $CycleDuration))
  288. ->setRecordFormats([
  289. [
  290. 'Format' => 'mp4',
  291. 'CycleDuration' => $CycleDuration,
  292. 'OssObjectPrefix' => 'live/{AppName}/{StreamName}/{Sequence}{EscapedStartTime}{EscapedEndTime}',
  293. 'SliceOssObjectPrefix' => 'live/{AppName}/{StreamName}/{UnixTimestamp}_{Sequence}'
  294. ],
  295. ]);
  296. return $this;
  297. }
  298. /**
  299. * 解除录制配置
  300. * @param string $StreamName 直播间号
  301. * @param string $actionName 动作名称 默认本方法名
  302. * @return $this
  303. * */
  304. public function liveDelRecording(string $StreamName, $actionName = __FUNCTION__)
  305. {
  306. $this->action[] = $actionName;
  307. $request = new \live\Request\V20161101\DeleteLiveAppRecordConfigRequest();
  308. $request->setDomainName($this->playLike)->setAppName($this->appName);
  309. if ($StreamName) $request->setStreamName($StreamName);
  310. $this->request[$actionName] = $request;
  311. return $this;
  312. }
  313. /**
  314. * 创建直播索引文件
  315. * 开播后调用创建录制索引返回:
  316. * {
  317. * "RecordInfo":{
  318. * "AppName":"xxx",
  319. * "CreateTime":"2016-05-27T09:40:56Z",
  320. * "DomainName":"xxx",
  321. * "Duration":588.849,
  322. * "EndTime":"2016-05-25T05:47:11Z",
  323. * "Height":480,
  324. * "OssBucket":"bucket",
  325. * "OssEndpoint":"oss-cn-hangzhou.aliyuncs.com",
  326. * "OssObject":"atestObject.m3u8",
  327. * "RecordId":"c4d7f0a4-b506-43f9-8de3-07732c3f3d82", $this->queryLiveRecordFile() 使用索引id
  328. * "RecordUrl":"http://xxx.xxx/atestObject.m3u8",
  329. * "StartTime":"2016-05-25T05:37:11Z",
  330. * "StreamName":"xxx",
  331. * "Width":640
  332. * },
  333. * "RequestId":"550439A3-F8EC-4CA2-BB62-B9DB43EEEF30"
  334. * }
  335. * @param string $StreamName 直播间号
  336. * @param string $EndTime 结束时间 按照当前时间后多少分钟
  337. * @param string $OssObject OSS 存储的录制文件名 示例:{AppName}/{StreamName}/{Date}/{Hour}/{Minute}_{Second}.m3u8
  338. * @return array|bool
  339. * */
  340. public function createLiveRecordConfig($StreamName, $EndTime, $OssObject = null)
  341. {
  342. $Time = time();
  343. $StartTime = date("Y-m-d\\TH:i:s\\Z", $Time);
  344. $EndTime = bcadd($Time, bcmul($EndTime, 60), 0);
  345. $EndTime = date("Y-m-d\\TH:i:s\\Z", $EndTime);
  346. $OssObject = is_null($OssObject) ? '{AppName}/{StreamName}/{Date}/{Hour}/{Minute}_{Second}.m3u8' : $OssObject;
  347. $request = new \live\Request\V20161101\CreateLiveStreamRecordIndexFilesRequest();
  348. $request->setAppName($this->appName)->setDomainName($this->playLike)->setStartTime($StartTime)->setEndTime($EndTime)
  349. ->setOssBucket($this->OssBucket)->setOssEndpoint($this->OssEndpoint)->setOssObject($OssObject)->setStreamName($StreamName);
  350. return $this->query($request);
  351. }
  352. /**
  353. * 查询录制的索引文件
  354. *
  355. * */
  356. public function queryLiveRecordFiles($StreamName, $StartTime, $EndTime, $page = 1, $limit = 100, $Order = 'desc')
  357. {
  358. $request = new \live\Request\V20161101\DescribeLiveStreamRecordIndexFilesRequest();
  359. $request->setStreamName($StreamName)->setDomainName($this->playLike)->setAppName($this->appName)->setStartTime($StartTime)
  360. ->setEndTime($EndTime)->setOrder($Order)->setPageNum($page)->setPageSize($limit);
  361. return $this->query($request);
  362. }
  363. /**
  364. * 查询单个录制的文件
  365. * @param string $StreamName 直播间号码
  366. * @param string $RecordId 索引文件id
  367. * @return array
  368. * */
  369. public function queryLiveRecordFile($StreamName, $RecordId)
  370. {
  371. $request = new \live\Request\V20161101\DescribeLiveStreamRecordIndexFileRequest();
  372. $request->setStreamName($StreamName)->setDomainName($this->playLike)->setAppName($this->appName)->setRecordId($RecordId);
  373. return $this->query($request);
  374. }
  375. /**
  376. * 查询直播间录制回放
  377. * @param string $StreamName 直播间号
  378. * @param string $StartTime 开始时间 示例:2015-12-01T17:36:00Z
  379. * @param string $EndTime 结束时间 示例:2015-12-01T17:36:00Z
  380. * @return JSON
  381. * */
  382. public function queryLiveRecordList($StreamName, $StartTime, $EndTime)
  383. {
  384. $StartTime = date("Y-m-d\\TH:i:s\\Z", $StartTime);
  385. $EndTime = date("Y-m-d\\TH:i:s\\Z", $EndTime);
  386. $request = new \live\Request\V20161101\DescribeLiveStreamRecordContentRequest();
  387. $request->setAppName($this->appName)->setDomainName($this->playLike)->setStreamName($StreamName)->setStartTime($StartTime)->setEndTime($EndTime);
  388. return $this->query($request);
  389. }
  390. /**
  391. * 执行单个请求
  392. * @param object $request
  393. * @return array | boolean
  394. * */
  395. public function query($request)
  396. {
  397. try {
  398. $response = $this->client->getAcsResponse($request);
  399. $response = json_encode($response);
  400. return json_decode($response, true);
  401. } catch (\Exception $e) {
  402. return self::setErrorInfo($e);
  403. }
  404. }
  405. /**
  406. * 执行多个请求
  407. * @param string $action 需要执行的动作
  408. * @return array
  409. *
  410. * */
  411. public function executeResponse($action = null)
  412. {
  413. $thsiAction = null;
  414. try {
  415. if ($action === null && count($this->action) == 1) $action = $this->action[0];
  416. if ($action) {
  417. $thsiAction = $action;
  418. $request = isset($this->request[$action]) ? $this->request[$action] : false;
  419. if (!$request) return self::setErrorInfo('请求的资源不存在!');
  420. $response = $this->client->getAcsResponse($request);
  421. $response = json_encode($response);
  422. $this->action = [];
  423. $this->request = [];
  424. return json_decode($response, true);
  425. } else {
  426. $responses = [];
  427. foreach ($this->request as $act => $request) {
  428. $thsiAction = $act;
  429. $response = $this->client->getAcsResponse($request);
  430. $response = json_encode($response);
  431. $responses[$act] = json_decode($response, true);
  432. }
  433. $responses = count($responses) == 1 && count($this->action) == 1 ? $responses[$this->action[0]] : $responses;
  434. $this->action = [];
  435. $this->request = [];
  436. return $responses;
  437. }
  438. } catch (\Exception $e) {
  439. return self::setErrorInfo($e, $thsiAction);
  440. }
  441. }
  442. }