video_qlvb.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. <?php
  2. /* API 文档
  3. * 点播 https://www.qcloud.com/doc/api/257/1965
  4. */
  5. class VideoQlvb
  6. {
  7. public function __construct()
  8. {
  9. fanwe_require(APP_ROOT_PATH . 'system/QcloudApi/QcloudApi.php');
  10. }
  11. private function loadService($module_name, $config = null)
  12. {
  13. $m_config = load_auto_cache("m_config");
  14. if ($config == null){
  15. $config = array(
  16. 'SecretId' => $m_config['qcloud_secret_id'],
  17. 'SecretKey' => $m_config['qcloud_secret_key'],
  18. 'RequestMethod' => 'GET',
  19. 'DefaultRegion' => 'gz'
  20. );
  21. }
  22. return QcloudApi::load($module_name, $config);
  23. }
  24. /**
  25. * 创建一个直播频道
  26. * @param unknown_type $video_id
  27. * @param unknown_type $user_id
  28. * @param unknown_type $is_record
  29. * @return Ambigous <multitype:string, multitype:string multitype:string >
  30. */
  31. public function Create($account)
  32. {
  33. $video_id = get_max_room_id(0);
  34. $user_id = $account;
  35. $flow_user_id = $account;
  36. $is_record = 1;
  37. return $this->GetChannelInfo($video_id, 'b', $video_id, $user_id, $is_record,$flow_user_id);
  38. }
  39. /**
  40. * 关闭频道推流
  41. * @param string $channel_id 有些早期提供的API中直播码参数被定义为channel_id,新的API则称直播码为stream_id,仅历史原因而已
  42. * @return multitype:number unknown
  43. */
  44. public function Stop($stream_id)
  45. {
  46. $m_config = load_auto_cache('m_config');
  47. $key = $m_config['qcloud_auth_key'];
  48. $t = get_gmtime() + 86400;
  49. $url = "http://fcgi.video.qcloud.com/common_access?" . http_build_query(array(
  50. 'cmd' => $m_config['vodset_app_id'],
  51. 'interface' => 'Live_Channel_SetStatus',
  52. 't' => $t,
  53. 'sign' => md5($key . $t),
  54. 'Param.s.channel_id' => $stream_id,
  55. 'Param.n.status' => 0,//0:关闭; 1:开启
  56. ));
  57. $ret = $this->accessService($url);
  58. //ret 返回码 int 0:成功;其他值:失败
  59. //message 错误信息 string 错误信息
  60. if($ret==0){
  61. return true;
  62. }else{
  63. return false;
  64. }
  65. }
  66. /**
  67. * 获取直播录制文件
  68. * @param string $channel_id
  69. * @return multitype:number NULL multitype:multitype:unknown
  70. *
  71. * https://www.qcloud.com/document/product/267/5960
  72. */
  73. public function GetRecord($stream_id)
  74. {
  75. $m_config = load_auto_cache('m_config');
  76. $key = $m_config['qcloud_auth_key'];
  77. $t = get_gmtime() + 86400;
  78. $url = "http://fcgi.video.qcloud.com/common_access?" . http_build_query(array(
  79. 'cmd' => $m_config['vodset_app_id'],
  80. 'interface' => 'Live_Tape_GetFilelist',
  81. 't' => $t,
  82. 'sign' => md5($key . $t),
  83. 'Param.n.page_size' => 100,
  84. 'Param.s.channel_id' => $stream_id,
  85. ));
  86. $res = $this->accessService($url);
  87. /*
  88. $filesInfo = array();
  89. foreach ($res['output']['file_list'] as $file) {
  90. $filesInfo[] = array(
  91. 'fileId' => $file['file_id'],
  92. );
  93. }*/;
  94. return array('status' => 1, 'total_count' => intval($res['output']['all_count']), 'file_list' => $res['output']['file_list']);
  95. }
  96. /**
  97. * 视频拼接 https://www.qcloud.com/document/product/266/7821
  98. * @param unknown_type $channel_id
  99. * @return multitype:number NULL multitype:multitype:unknown
  100. */
  101. public function ConcatVideo($channel_id,$new_file_name)
  102. {
  103. $res = $this->GetFilelist($channel_id);
  104. if ($res['total_count'] > 1){
  105. $params = array();
  106. $params['name'] = $new_file_name;
  107. $params['dstType.0'] = 'mp4';
  108. $i = 0;
  109. foreach ($res['file_list'] as $file) {
  110. $params['srcFileList.'.$i.'.fileId'] = $file['file_id'];
  111. $i = $i + 1;
  112. }
  113. $service = $this->loadService(QcloudApi::MODULE_VOD);
  114. $ret = $service->ConcatVideo($params);
  115. if ($ret === false) {
  116. // 请求失败,解析错误信息
  117. $error = $service->getError();
  118. return array(
  119. 'status' => 0,
  120. 'error' => $error->getMessage(),
  121. );
  122. }else{
  123. //code 错误码, 0: 成功, 其他值: 失败
  124. //vodTaskId 描述拼接任务的唯一id,可以通过此id查询任务状态
  125. return $ret;
  126. }
  127. }else{
  128. //只有一个文件时,不需要调用:合并视频功能
  129. }
  130. }
  131. /**
  132. * 删除视频文件 https://www.qcloud.com/document/product/266/1324
  133. * @param string $channel_id
  134. * @return multitype:NULL
  135. */
  136. public function DeleteVodFile($channel_id)
  137. {
  138. $res = $this->GetFilelist($channel_id);
  139. $delvodset = array();
  140. if ($res['total_count'] > 0){
  141. $service = $this->loadService(QcloudApi::MODULE_VOD);
  142. foreach ($res['file_list'] as $file) {
  143. $delvodset[$file['file_id']] = $service->DeleteVodFile(array('fileId' => $file['file_id'], 'priority' => 0));
  144. }
  145. }
  146. return $delvodset;
  147. }
  148. /** URL拉取视频上传 文档地址 https://www.qcloud.com/document/product/266/1393
  149. * @param $url
  150. */
  151. public function MultiPullVodFile($flow_user_id, $url, $file_name)
  152. {
  153. //$config
  154. $service = $this->loadService(QcloudApi::MODULE_VOD,$config);
  155. $ret = $service->MultiPullVodFile(array(
  156. 'pullset.1.url' => $url,
  157. 'pullset.1.fileName' => $file_name,
  158. ));
  159. if ($ret === false) {
  160. // 请求失败,解析错误信息
  161. $error = $service->getError();
  162. return array(
  163. 'status' => 0,
  164. 'error' => $error->getMessage(),
  165. );
  166. }
  167. return $ret;
  168. }
  169. /**
  170. * 拉取事件通知【点播API】
  171. 视频拼接、URL拉取视频上传 通过可靠回调,获得执行结果;
  172. PullVodEvent:https://www.qcloud.com/document/product/266/7818
  173. 5.1 监听到 视频拼接完 事件则执行第5步,把视频文件保存到用户的腾讯云帐户下,同时调用第4步删除源文件
  174. 5.2 监听到【用户腾讯云帐户】下的 URL拉取视频上传完 事件;则删除方维腾讯云下的合并后的视频文件;并通知用户的appserver,点播视频生成;
  175. * @param int $flow_user_id
  176. * @return multitype:number NULL |unknown
  177. */
  178. public function PullEvent($flow_user_id = 0)
  179. {
  180. //$config
  181. $config = null;
  182. $m_config = load_auto_cache("m_config");
  183. $service = $this->loadService(QcloudApi::MODULE_VOD,$config);
  184. //print_r($service);
  185. //echo $service->getLastRequest();
  186. $ret = $service->PullEvent();
  187. if ($ret === false) {
  188. print_r($service);
  189. // 请求失败,解析错误信息
  190. $error = $service->getError();
  191. return array(
  192. 'status' => 0,
  193. 'error' => $error->getMessage(),
  194. );
  195. }
  196. return $ret;
  197. }
  198. /**
  199. * 确认事件通知【点播API】
  200. ConfirmVodEvent:https://www.qcloud.com/document/product/266/7819
  201. * @param unknown_type $flow_user_id
  202. * @param unknown_type $msgHandle
  203. * @return multitype:number NULL |unknown
  204. */
  205. public function ConfirmVodEvent($flow_user_id = 0, $msgHandle = array())
  206. {
  207. //$config
  208. $params = array();
  209. $i = 1;
  210. foreach ($msgHandle as $key =>$val) {
  211. $params['msgHandle.'.$i] = $val;
  212. $i = $i + 1;
  213. }
  214. $service = $this->loadService(QcloudApi::MODULE_VOD,$config);
  215. $ret = $service->ConfirmVodEvent($params);
  216. if ($ret === false) {
  217. // 请求失败,解析错误信息
  218. $error = $service->getError();
  219. return array(
  220. 'status' => 0,
  221. 'error' => $error->getMessage(),
  222. );
  223. }
  224. return $ret;
  225. }
  226. /**
  227. * 获取播放统计历史信息【直播API】
  228. * @param string $stream_id 直播码也是$channel_id值
  229. * @param int $start_time 查询起始时间 3天内的数据 时间戳
  230. * @param int $end_time 查询终止时间 建议查询跨度不大于2小时 时间戳
  231. * @return multitype:number NULL
  232. */
  233. public function LivePlayStatHistory($stream_id,$start_time,$end_time)
  234. {
  235. $m_config = load_auto_cache('m_config');
  236. $key = $m_config['qcloud_auth_key'];
  237. $t = get_gmtime() + 86400;
  238. $url = "http://statcgi.video.qcloud.com/common_access?" . http_build_query(array(
  239. 'cmd' => $m_config['vodset_app_id'],
  240. 'interface' => 'Get_LivePlayStatHistory',
  241. 't' => $t,
  242. 'sign' => md5($key . $t),
  243. 'Param.n.start_time' => $start_time,
  244. 'Param.n.end_time' => $end_time,
  245. 'Param.s.stream_id' => $stream_id,
  246. ));
  247. $res = $this->accessService($url);
  248. return $res;
  249. }
  250. /**
  251. *
  252. * @param int $app_video_id fanwe_video.id
  253. * @param string $layer b:主播; s:小主播
  254. * @param int $session_id
  255. * @param int $app_user_id fanwe_user.id
  256. * @param int $is_record 是否记录文件;1:记录;0:不记录
  257. * @param int $flow_user_id 流量平台用户id;
  258. * @param int $flow_video_id 流量平台频道id;
  259. * @return multitype:string multitype:string
  260. */
  261. public function GetChannelInfo(
  262. $app_video_id,
  263. $layer = 'b',
  264. $session_id = 0,
  265. $app_user_id = 0,
  266. $is_record = 0,
  267. $flow_user_id = 0,
  268. $flow_video_id =0
  269. ) {
  270. $m_config = load_auto_cache('m_config');
  271. $bizId = $m_config['qcloud_bizid'];
  272. $key = $m_config['qcloud_security_key'];
  273. //$stream_id = $session_id . $layer . $app_user_id . "_" . substr(md5($app_video_id . microtime_float()), 12);
  274. //$stream_id = $bizId . "_" . $stream_id; //直播码
  275. if ($flow_video_id == 0) $flow_video_id = $app_video_id;
  276. //if ($flow_user_id == 0) $flow_user_id = $bizId;
  277. //直播码生成规则: 商户ID."_".商户会员id.$layer.商户直播ID."_".平台直播ID."_".to_date(NOW_TIME, 'Y-m-d H:i:s')
  278. //直播码:用作识别不同推流的ID标示,唯一的要求就是以“bizid+下划线”作为前缀,剩下的部分您可以自由指定,只要确保不跟已经分配过的直播码冲突就行了,所以很多客户会选择用主播的用户id来作为直播码使用。
  279. $stream_id = $bizId."_".$flow_user_id."_".$app_user_id.$layer.$app_video_id."_".$flow_video_id."_".microtime_format(NOW_TIME,'YmdHisx');
  280. if ($session_id == 0) {
  281. $session_id = $flow_video_id;
  282. }
  283. $time = to_date(get_gmtime() + 86400, 'Y-m-d H:i:s');
  284. $txTime = strtoupper(base_convert(strtotime($time), 10, 16));
  285. //$stream_id = bizid+"_"+stream_id 如 8888_test123456
  286. // 24小时失效
  287. $ext_str = $this->get_acc_sign($key, $stream_id, 86400);
  288. $ext_str = "?bizid=" . $bizId . "&" . $ext_str . "&mix=layer:{$layer};session_id:{$session_id};t_id:1";
  289. $upstream_address = "rtmp://" . $bizId . ".livepush.myqcloud.com/live/" . $stream_id . $ext_str;
  290. //后台开启录制 或者 非私密直播 录制视频
  291. $save_video = '';
  292. if ($is_record == 1) {
  293. $save_video = "&record=mp4&record_interval=5400";
  294. }
  295. return array(
  296. 'stream_id' => $stream_id,
  297. 'push_rtmp' => $upstream_address . $save_video,
  298. 'play_rtmp' => "rtmp://" . $bizId . ".liveplay.myqcloud.com/live/" . $stream_id,
  299. 'play_flv' => "http://" . $bizId . ".liveplay.myqcloud.com/live/" . $stream_id . ".flv",
  300. 'play_hls' => "http://" . $bizId . ".liveplay.myqcloud.com/live/" . $stream_id . ".m3u8",
  301. );
  302. }
  303. private function get_acc_sign($key, $stream_id, $len = 300)
  304. {
  305. $time = to_date(get_gmtime() + $len, 'Y-m-d H:i:s');
  306. //$time = '2017-01-22 23:59:59';
  307. $txTime = strtoupper(base_convert(strtotime($time), 10, 16));
  308. //txSecret的生成方法是 = MD5(KEY+ stream_id + txTime)
  309. $txSecret = md5($key . $stream_id . $txTime);
  310. $ext_str = http_build_query(array(
  311. "txSecret" => $txSecret,
  312. "txTime" => $txTime,
  313. ));
  314. return $ext_str;
  315. }
  316. private function accessService($url)
  317. {
  318. $ch = curl_init($url);
  319. curl_setopt($ch, CURLOPT_HEADER, false);
  320. curl_setopt($ch, CURLOPT_NOBODY, false); //对body进行输出。
  321. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  322. $package = curl_exec($ch);
  323. $res = json_decode($package, true);
  324. return $res;
  325. }
  326. }