1+ <?php
2+ /**
3+ * @link http://www.tintsoft.com/
4+ * @copyright Copyright (c) 2012 TintSoft Technology Co. Ltd.
5+ * @license http://www.tintsoft.com/license/
6+ */
7+ namespace aliyun \live ;
8+
9+ use yii \base \Component ;
10+ use yii \base \InvalidConfigException ;
11+ use GuzzleHttp \HandlerStack ;
12+ use GuzzleHttp \Client as HttpClient ;
13+ use aliyun \guzzle \subscriber \Rpc ;
14+
15+ /**
16+ * Class Client
17+ * @package aliyun\live
18+ */
19+ class Live extends Component
20+ {
21+ /**
22+ * @var string
23+ */
24+ public $ accessKeyId ;
25+
26+ /**
27+ * @var string
28+ */
29+ public $ accessSecret ;
30+
31+ /**
32+ * @var string API版本
33+ */
34+ public $ version = '2016-11-01 ' ;
35+
36+ /**
37+ * @var string 网关地址
38+ */
39+ public $ baseUri = 'https://live.aliyuncs.com/ ' ;
40+
41+ /**
42+ * @var string 应用名称
43+ */
44+ public $ appName ;
45+
46+ /**
47+ * @var string 应用域名
48+ */
49+ public $ domain ;
50+
51+ /**
52+ * @var string 推流鉴权
53+ */
54+ public $ pushAuth ;
55+
56+ /**
57+ * @var string 媒体中心地址
58+ */
59+ public $ pushDomain = 'video-center.alivecdn.com ' ;
60+
61+ /**
62+ * @var bool 是否使用安全连接
63+ */
64+ public $ secureConnection = false ;
65+
66+ /**
67+ * @var int 签名有效期,默认有效期是一周
68+ */
69+ public $ authTime = 604800 ;
70+
71+ /**
72+ * @var int 秘钥过期时间
73+ */
74+ private $ expirationTime ;
75+
76+ /**
77+ * @var string 播放协议
78+ */
79+ private $ playScheme ;
80+
81+ /**
82+ * @var string 播放地址
83+ */
84+ private $ httpPlayUrl ;
85+
86+ /**
87+ * @var HttpClient
88+ */
89+ private $ _httpClient ;
90+
91+ /**
92+ * 初始化直播组件
93+ * @throws InvalidConfigException
94+ */
95+ public function init (){
96+ parent ::init ();
97+ $ this ->expirationTime = time () + $ this ->authTime ;
98+ $ this ->playScheme = $ this ->secureConnection ? 'https:// ' : 'http:// ' ;
99+ $ this ->httpPlayUrl = $ this ->playScheme . $ this ->domain ;
100+
101+ if (empty ($ this ->accessKeyId )) {
102+ throw new InvalidConfigException ('The "accessKeyId" property must be set. ' );
103+ }
104+ if (empty ($ this ->accessSecret )) {
105+ throw new InvalidConfigException ('The "accessSecret" property must be set. ' );
106+ }
107+ if (empty ($ this ->appName )) {
108+ throw new InvalidConfigException ('The "appName" property must be set. ' );
109+ }
110+
111+ if (empty ($ this ->domain )) {
112+ throw new InvalidConfigException ('The "domain" property must be set. ' );
113+ }
114+ }
115+
116+ /**
117+ * 获取Http Client
118+ * @return HttpClient
119+ */
120+ public function getHttpClient ()
121+ {
122+ if (!is_object ($ this ->_httpClient )) {
123+ $ stack = HandlerStack::create ();
124+ $ middleware = new Rpc ([
125+ 'accessKeyId ' => $ this ->accessKeyId ,
126+ 'accessSecret ' => $ this ->accessSecret ,
127+ 'Version ' => $ this ->version
128+ ]);
129+ $ stack ->push ($ middleware );
130+
131+ $ this ->_httpClient = new HttpClient ([
132+ 'base_uri ' => $ this ->baseUri ,
133+ 'handler ' => $ stack ,
134+ 'verify ' => false ,
135+ 'http_errors ' => false ,
136+ 'connect_timeout ' => 3 ,
137+ 'read_timeout ' => 10 ,
138+ 'debug ' => false ,
139+ ]);
140+ }
141+ return $ this ->_httpClient ;
142+ }
143+
144+ /**
145+ * 发起Api请求
146+ * @param array $params
147+ * @return \Psr\Http\Message\ResponseInterface
148+ */
149+ public function createRequest (array $ params )
150+ {
151+ return $ this ->getHttpClient ()->get ('/ ' , ['query ' => $ params ]);
152+ }
153+
154+ /**
155+ * 禁止推流
156+ * @param string $streamName
157+ * @return string
158+ */
159+ public function forbidLiveStream ($ streamName )
160+ {
161+ return $ this ->createRequest ([
162+ 'Action ' => 'ForbidLiveStream ' ,
163+ 'DomainName ' => $ this ->domain ,
164+ 'AppName ' => $ this ->appName ,
165+ 'StreamName ' => $ streamName ,
166+ 'LiveStreamType ' => 'publisher ' ,
167+ 'ResumeTime ' => gmdate ('Y-m-d\TH:i:s\Z ' , mktime (0 , 0 , 0 , 1 , 1 , 2099 ))
168+ ]);
169+ }
170+
171+ /**
172+ * 允许推流
173+ * @param string $streamName
174+ * @return string
175+ */
176+ public function startLiveStream ($ streamName )
177+ {
178+ return $ this ->createRequest ([
179+ 'Action ' => 'ResumeLiveStream ' ,
180+ 'DomainName ' => $ this ->domain ,
181+ 'AppName ' => $ this ->appName ,
182+ 'StreamName ' => $ streamName ,
183+ 'LiveStreamType ' => 'publisher '
184+ ]);
185+ }
186+
187+ /**
188+ * 实时查询在线人数的请求参数
189+ * @param null|string $streamName
190+ * @param null|int $startTime
191+ * @param null|int $endTime
192+ * @return string
193+ */
194+ public function describeLiveStreamOnlineUserNum ($ streamName = null , $ startTime = null , $ endTime = null )
195+ {
196+ $ params = [
197+ 'Action ' => 'DescribeLiveStreamOnlineUserNum ' ,
198+ 'DomainName ' => $ this ->domain ,
199+ 'AppName ' => $ this ->appName
200+ ];
201+ if (!empty ($ streamName )) {
202+ $ params ['StreamName ' ] = $ streamName ;
203+ }
204+ if (!empty ($ startTime ) && !empty ($ endTime )) {
205+ $ params ['StartTime ' ] = gmdate ('Y-m-d\TH:i:s\Z ' , $ startTime );
206+ $ params ['EndTime ' ] = gmdate ('Y-m-d\TH:i:s\Z ' , $ endTime );
207+ }
208+ return $ this ->createRequest ($ params );
209+ }
210+
211+ /**
212+ * 查询在线的直播推流列表
213+ * @return string
214+ */
215+ public function describeLiveStreamsOnlineList ()
216+ {
217+ return $ this ->createRequest ([
218+ 'Action ' => 'DescribeLiveStreamsOnlineList ' ,
219+ 'DomainName ' => $ this ->domain ,
220+ 'AppName ' => $ this ->appName
221+ ]);
222+ }
223+
224+ /**
225+ * 直播签名
226+ * @param string $streamName
227+ * @return string
228+ */
229+ public function getSign ($ streamName )
230+ {
231+ $ uri = "/ {$ this ->appName }/ {$ streamName }" ;
232+ if ($ this ->pushAuth ) {
233+ $ authKey = "?vhost= {$ this ->domain }&auth_key= {$ this ->expirationTime }-0-0- " . md5 ("{$ uri }- {$ this ->expirationTime }-0-0- {$ this ->pushAuth }" );
234+ } else {
235+ $ authKey = "?vhost= {$ this ->domain }" ;
236+ }
237+ return $ authKey ;
238+ }
239+
240+ /**
241+ * 获取推流地址
242+ * @return string
243+ */
244+ public function getPushPath ()
245+ {
246+ return "rtmp:// {$ this ->pushDomain }/ {$ this ->appName }/ " ;
247+ }
248+
249+ /**
250+ * 获取串码流
251+ * @param string $streamName 流名称
252+ * @return string
253+ */
254+ public function getPushArg ($ streamName )
255+ {
256+ return $ streamName . $ this ->getSign ($ streamName );
257+ }
258+
259+ /**
260+ * 获取直播推流地址
261+ * @param string $streamName
262+ * @return string
263+ */
264+ public function getPushUrl ($ streamName )
265+ {
266+ $ uri = "/ {$ this ->appName }/ {$ streamName }" ;
267+ return "rtmp:// {$ this ->pushDomain }" . $ uri . $ this ->getSign ($ streamName );
268+ }
269+
270+ /**
271+ * 验证签名
272+ * @param string $streamName
273+ * @param string $usrargs
274+ * @return bool
275+ */
276+ public function checkSign ($ streamName , $ usrargs )
277+ {
278+ parse_str ($ usrargs , $ args );
279+ if (isset ($ args ['vhost ' ]) && isset ($ args ['auth_key ' ])) {
280+ if ($ args ['vhost ' ] != $ this ->domain ) {
281+ return false ;
282+ }
283+ $ params = explode ('- ' , $ args ['auth_key ' ], 4 );
284+ if (isset ($ params [0 ]) && $ params [3 ]) {
285+ $ uri = "/ {$ this ->appName }/ {$ streamName }" ;
286+ if ($ params [3 ] == md5 ("{$ uri }- {$ params [0 ]}-0-0- {$ this ->pushAuth }" )) {
287+ return true ;
288+ }
289+
290+ }
291+ }
292+ return false ;
293+ }
294+
295+ /**
296+ * 获取签名
297+ * @param string $uri
298+ * @return string
299+ */
300+ protected function getAuthKey ($ uri )
301+ {
302+ $ authKey = '' ;
303+ if ($ this ->pushAuth ) {
304+ $ authKey = "?auth_key= {$ this ->expirationTime }-0-0- " . md5 ("{$ uri }- {$ this ->expirationTime }-0-0- {$ this ->pushAuth }" );
305+ }
306+ return $ authKey ;
307+ }
308+
309+ /**
310+ * 获取RTMP拉流地址
311+ * @param string $streamName
312+ * @return string
313+ */
314+ public function getPlayUrlForRTMP ($ streamName )
315+ {
316+ $ uri = "/ {$ this ->appName }/ {$ streamName }" ;
317+ return 'rtmp:// ' . $ this ->domain . $ uri . $ this ->getAuthKey ($ uri );
318+ }
319+
320+ /**
321+ * 获取FLV播放地址
322+ * @param string $streamName
323+ * @return string
324+ */
325+ public function getPlayUrlForFLV ($ streamName )
326+ {
327+ $ uri = "/ {$ this ->appName }/ {$ streamName }.flv " ;
328+ return $ this ->httpPlayUrl . $ uri . $ this ->getAuthKey ($ uri );
329+ }
330+
331+ /**
332+ * 获取M3U8播放地址
333+ * @param string $streamName
334+ * @return string
335+ */
336+ public function getPlayUrlForM3U8 ($ streamName )
337+ {
338+ $ uri = "/ {$ this ->appName }/ {$ streamName }.m3u8 " ;
339+ return $ this ->httpPlayUrl . $ uri . $ this ->getAuthKey ($ uri );
340+ }
341+
342+ /**
343+ * 获取阿里云播放地址
344+ * @param string $streamName
345+ * @return array
346+ */
347+ public function getPlayUrls ($ streamName )
348+ {
349+ return [
350+ 'rtmp ' => $ this ->getPlayUrlForRTMP ($ streamName ),
351+ 'flv ' => $ this ->getPlayUrlForFLV ($ streamName ),
352+ 'm3u8 ' => $ this ->getPlayUrlForM3U8 ($ streamName )
353+ ];
354+ }
355+
356+ /**
357+ * 设置签名过期时间
358+ * @param int $expirationTime
359+ * @return $this
360+ */
361+ public function setExpirationTime ($ expirationTime )
362+ {
363+ $ this ->expirationTime = $ expirationTime ;
364+ return $ this ;
365+ }
366+
367+ /**
368+ * 获取签名过期时间
369+ * @return int
370+ */
371+ public function getExpirationTime ()
372+ {
373+ return $ this ->expirationTime ;
374+ }
375+
376+ /**
377+ * @return string
378+ */
379+ public function getPlayScheme ()
380+ {
381+ return $ this ->playScheme ;
382+ }
383+
384+ /**
385+ * @return string
386+ */
387+ public function getHttpPlayUrl ()
388+ {
389+ return $ this ->httpPlayUrl ;
390+ }
391+ }
0 commit comments