video.action.php 90 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | FANWE 直播系统
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2011 http://www.fanwe.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Author: 云淡风轻(1956838968@qq.com)
  8. // +----------------------------------------------------------------------
  9. class videoModule extends baseModule
  10. {
  11. /**
  12. * 当前房间用户列表(包括机器人,但不包括虚拟人数)
  13. */
  14. public function viewer(){
  15. $root = array();
  16. $group_id = strim($_REQUEST['group_id']);//聊天群id
  17. $video_id = intval($_REQUEST['room_id']);//房间号ID
  18. $page = intval($_REQUEST['p']);//取第几页数据
  19. $root = load_auto_cache("video_viewer",array('group_id'=>$group_id,'video_id'=>$video_id, 'page'=>$page));
  20. /*
  21. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoViewerRedisService.php');
  22. $video_viewer_redis = new VideoViewerRedisService();
  23. $root = $video_viewer_redis->get_viewer_list2($video_id,$page,100);
  24. */
  25. //过滤user_id为0的机器人
  26. for($i=count($root['list'])-1;$i>=0;$i--)
  27. {
  28. if ($root['list'][$i]['user_id']==0)
  29. {
  30. array_splice($root['list'],$i,1);
  31. }
  32. }
  33. ajax_return($root);
  34. }
  35. /**
  36. * 直播结束
  37. */
  38. public function end_video(){
  39. $root = array();
  40. //$GLOBALS['user_info']['id'] = 1;
  41. if(!$GLOBALS['user_info']){
  42. $root['error'] = "用户未登陆,请先登陆.";
  43. $root['status'] = 0;
  44. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  45. }else{
  46. $user_id = intval($GLOBALS['user_info']['id']);
  47. $room_id = strim($_REQUEST['room_id']);//房间号id
  48. $video_vid = strim($_REQUEST['video_url']);//视频地址
  49. //只要主播请求关闭直播,就请求同步redis数据到mysql,防止结束时候mysql数据未同步导致的当前处理的数据错误;
  50. $sql = "SELECT id FROM " . DB_PREFIX . "video";
  51. $list = $GLOBALS['db']->getAll($sql, true, true);
  52. if (count($list) > 0) {
  53. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  54. $video_redis = new VideoRedisService();
  55. foreach ($list as $k => $v) {
  56. $video_id = $v['id'];
  57. //计算权重
  58. $video_redis->syn_sort_num($video_id);
  59. $fields = array('share_count','like_count','fans_count', 'sort_num', 'vote_number', 'robot_num','watch_number', 'virtual_watch_number', 'max_watch_number');
  60. $video = $video_redis->getRow_db($video_id, $fields);
  61. $GLOBALS['db']->autoExecute(DB_PREFIX . "video", $video, "UPDATE", "id=" . $video_id);
  62. }
  63. }
  64. if ($video_vid == 'null') $video_vid = '';
  65. //$root['error'] = $video_vid;
  66. $sql="";
  67. if (OPEN_PAI_MODULE==1) {
  68. $sql = "select id,user_id,max_watch_number,virtual_watch_number,robot_num,vote_number,group_id,room_type,begin_time,end_time,channelid,cate_id,pai_id,is_live_pay,live_pay_type from ".DB_PREFIX."video where id = ".$room_id." and user_id = ".$user_id;
  69. }else {
  70. $sql = "select id,user_id,max_watch_number,virtual_watch_number,robot_num,vote_number,group_id,room_type,begin_time,end_time,channelid,cate_id,is_live_pay,live_pay_type from ".DB_PREFIX."video where id = ".$room_id." and user_id = ".$user_id;
  71. }
  72. $video = $GLOBALS['db']->getRow($sql,true,true);
  73. //只有主播自己能结束
  74. if ($user_id == $video['user_id']){
  75. if (OPEN_BM == 1) {
  76. $is_out = intval($_REQUEST['is_out']);
  77. if ($is_out==1) {
  78. //主播离开
  79. //广播:直播结束
  80. $ext = array();
  81. $ext['type'] = 3; //0:普通消息;1:礼物;2:弹幕消息;3:主播退出;4:禁言;5:观众进入房间;6:观众退出房间;7:直播结束
  82. $ext['room_id'] = $room_id;//直播ID 也是room_id;只有与当前房间相同时,收到消息才响应
  83. $ext['show_num'] = 0;//观看人数
  84. $ext['fonts_color'] = '';//字体颜色
  85. $ext['desc'] = '主播退出';//弹幕消息;
  86. $ext['desc2'] = '主播退出';//弹幕消息;
  87. #构造高级接口所需参数
  88. $msg_content = array();
  89. //创建array 所需元素
  90. $msg_content_elem = array(
  91. 'MsgType' => 'TIMCustomElem', //自定义类型
  92. 'MsgContent' => array(
  93. 'Data' => json_encode($ext),
  94. 'Desc' => '',
  95. )
  96. );
  97. //将创建的元素$msg_content_elem, 加入array $msg_content
  98. array_push($msg_content, $msg_content_elem);
  99. //发送广播:直播结束
  100. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  101. $api = createTimAPI();
  102. $is_nospeaking = $GLOBALS['db']->getOne("select is_nospeaking from ".DB_PREFIX."user where id = ".$user_id,true,true);
  103. if(intval($is_nospeaking)==1){
  104. $ret = $api->group_send_group_msg2('', $video['group_id'], $msg_content);
  105. }else{
  106. $ret = $api->group_send_group_msg2($user_id, $video['group_id'], $msg_content);
  107. }
  108. //结束推送
  109. $sql = "update ".DB_PREFIX."video set is_push = 0 where id = ".$room_id." and user_id = ".$user_id;
  110. $GLOBALS['db']->query($sql);
  111. if($GLOBALS['db']->affected_rows()){
  112. $root['status'] = 1;
  113. //将mysql数据,同步一份到redis中
  114. sync_video_to_redis($room_id,'*',false);
  115. $ext = array();
  116. $ext['type'] = 44;
  117. $ext['room_id'] = $room_id;//直播ID 也是room_id;只有与当前房间相同时,收到消息才响应
  118. $ext['fonts_color'] = '';//字体颜色
  119. $ext['is_push'] = 0;//是否推送
  120. $ext['desc'] = '主播关闭直播';//弹幕消息;
  121. $ext['desc2'] = '主播关闭直播';//弹幕消息;
  122. #构造高级接口所需参数
  123. $msg_content = array();
  124. //创建array 所需元素
  125. $msg_content_elem = array(
  126. 'MsgType' => 'TIMCustomElem', //自定义类型
  127. 'MsgContent' => array(
  128. 'Data' => json_encode($ext),
  129. 'Desc' => '',
  130. )
  131. );
  132. //将创建的元素$msg_content_elem, 加入array $msg_content
  133. array_push($msg_content, $msg_content_elem);;
  134. //发送广播:直播结束
  135. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  136. $api = createTimAPI();
  137. $is_nospeaking = $GLOBALS['db']->getOne("select is_nospeaking from ".DB_PREFIX."user where id = ".$user_id,true,true);
  138. if(intval($is_nospeaking)==1){
  139. $ret = $api->group_send_group_msg2('', $video['group_id'], $msg_content);
  140. }else{
  141. $ret = $api->group_send_group_msg2($user_id, $video['group_id'], $msg_content);
  142. }
  143. }
  144. ajax_return($root);
  145. }
  146. }
  147. //同时关闭子房间
  148. if(defined('CHILD_ROOM') && CHILD_ROOM == 1){
  149. fanwe_require(APP_ROOT_PATH.'mapi/lib/ChildRoom.class.php');
  150. $child_room = new child_room();
  151. $child_room->end_child_video($room_id);
  152. }
  153. do_end_video($video,$video_vid,0,$video['cate_id']);
  154. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/BaseRedisService.php');
  155. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  156. $video_redis = new VideoRedisService();
  157. $root['watch_number'] = intval($video['max_watch_number']);
  158. $root['vote_number'] = intval($video['vote_number'])+intval($video_redis->getOne_db($video['id'],'game_vote_number'));//获得印票
  159. //
  160. /*
  161. if ($video_data['live_in'] == 1){
  162. $video_data['watch_number'] = $video_redis->get_video_watch_num($room_id);
  163. }
  164. */
  165. //redis_do_end_video($video_redis,$video_data,$video_vid,0,$video_data['cate_id']);
  166. //$root['viewer_num'] = $root['watch_number'] + $root['virtual_watch_number'];
  167. //总观看人数
  168. // $root['watch_number'] = $video['watch_number'] + $video['robot_num'] + $video['virtual_watch_number'];//观看人数
  169. //$root['watch_number'] = $video_data['max_watch_number'] ;
  170. //$root['vote_number'] = $video_redis->get_video_ticket_num($room_id);
  171. //$root['room_type'] = $video['room_type'];//房间类型 : 1私有群(Private),0公开群(Public),2聊天室(ChatRoom),3互动直播聊天室(AVChatRoom)
  172. $time_len = NOW_TIME - $video['begin_time'];//私有聊天或小于5分钟的视频,不保存
  173. $m_config = load_auto_cache("m_config");
  174. $short_video_time = $m_config['short_video_time']?$m_config['short_video_time']:300;
  175. if ($video['room_type'] == 1 || $time_len < $short_video_time && $m_config['has_save_video'] == 0){
  176. $root['has_delvideo'] = 0;//1:显示删除视频按钮; 0:不显示;
  177. }else {
  178. $root['has_delvideo'] = 1;//1:显示删除视频按钮; 0:不显示;
  179. }
  180. //$root['has_delvideo'] = 1;
  181. /*if (OPEN_PAI_MODULE==1&&intval($video['pai_id'])>0) {
  182. //关闭竞拍
  183. $data=array();
  184. $data['podcast_id']=$video['user_id'];
  185. $data['pai_id']=$video['pai_id'];
  186. $data['video_id']=$room_id;
  187. $rs = FanweServiceCall("pai_podcast","stop_pai",$data);
  188. }*/
  189. }
  190. rm_auto_cache("select_video");
  191. $root['status'] = 1;
  192. }
  193. ajax_return($root);
  194. }
  195. /**
  196. * 删除录制的视频
  197. */
  198. public function del_video(){
  199. $root = array();
  200. //$GLOBALS['user_info']['id'] = 1;
  201. if(!$GLOBALS['user_info']){
  202. $root['error'] = "用户未登陆,请先登陆.";
  203. $root['status'] = 0;
  204. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  205. }else{
  206. $user_id = intval($GLOBALS['user_info']['id']);
  207. $room_id = strim($_REQUEST['room_id']);//房间号id
  208. $sql = "update ".DB_PREFIX."video set is_delete = 1 where id = ".$room_id." and user_id = ".$user_id;
  209. $GLOBALS['db']->query($sql);
  210. if($GLOBALS['db']->affected_rows()){
  211. $root['status'] = 1;
  212. sync_video_to_redis($room_id,'is_delete',false);
  213. }else{
  214. $root['status'] = 0;
  215. }
  216. }
  217. //$root['status'] = 1;
  218. ajax_return($root);
  219. }
  220. /**
  221. * 删除回看录制的视频
  222. */
  223. public function del_video_history(){
  224. $root = array();
  225. //$GLOBALS['user_info']['id'] = 1;
  226. if(!$GLOBALS['user_info']){
  227. $root['error'] = "用户未登陆,请先登陆.";
  228. $root['status'] = 0;
  229. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  230. }else{
  231. $user_id = intval($GLOBALS['user_info']['id']);
  232. $room_id = strim($_REQUEST['room_id']);//房间号id
  233. $sql = "update ".DB_PREFIX."video_history set is_delete = 1 where live_in = 0 and id = ".$room_id." and user_id = ".$user_id;
  234. $GLOBALS['db']->query($sql);
  235. if($GLOBALS['db']->affected_rows()){
  236. $sql = "select count(*) as num from ".DB_PREFIX."video_history where is_delete = 0 and is_del_vod = 0 and user_id = '".$user_id."'";
  237. $video_count = $GLOBALS['db']->getOne($sql);
  238. $sql = "update ".DB_PREFIX."user set video_count = ".$video_count." where id = ".$user_id;
  239. $GLOBALS['db']->query($sql);
  240. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/BaseRedisService.php');
  241. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/UserRedisService.php');
  242. $user_redis = new UserRedisService();
  243. $user_data = array();
  244. $user_data['video_count'] = $video_count;
  245. $user_redis->update_db($user_id, $user_data);
  246. /*
  247. $sql = "select destroy_group_status,group_id from ".DB_PREFIX."video where id = ".$room_id;
  248. //$video = $video_redis->getRow_db($video_id);
  249. $video_data = $GLOBALS['db']->getRow($sql);
  250. //如果是删除状态,则解散群组
  251. if ($video_data['destroy_group_status'] == 1){
  252. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoRedisService.php');
  253. $video_redis = new VideoRedisService();
  254. if ($video_data['group_id'] != ''){
  255. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  256. $api = createTimAPI();
  257. $ret = $api->group_destroy_group($video_data['group_id']);
  258. $destroy_group_status = $ret['ErrorCode'];
  259. $video_redis->del_video_group_db($video_data['group_id']);//只有在:解散 聊天组时,才删除
  260. }else{
  261. $destroy_group_status = 0;
  262. }
  263. $sql = "update ".DB_PREFIX."video_history set destroy_group_status = ".$destroy_group_status." where id = ".$room_id." and user_id = ".$user_id;
  264. $GLOBALS['db']->query($sql);
  265. $data = array();
  266. $data['destroy_group_status'] = $destroy_group_status;
  267. $video_redis->update_db($room_id, $data);
  268. }
  269. */
  270. $root['status'] = 1;
  271. $root['error'] = "已删除";
  272. }else{
  273. $root['status'] = 0;
  274. $root['error'] = "只能删除非上架的视频";
  275. }
  276. }
  277. //$root['status'] = 1;
  278. ajax_return($root);
  279. }
  280. /**
  281. * 主播心跳监听,每30秒监听一次;监听数据:时间点,印票数,房间人数
  282. */
  283. public function monitor(){
  284. $root = array();
  285. $root['status'] = 1;
  286. if(!$GLOBALS['user_info']){
  287. $root['error'] = "用户未登陆,请先登陆.";
  288. $root['status'] = 0;
  289. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  290. }else{
  291. $user_id = intval($GLOBALS['user_info']['id']);//用户ID
  292. $room_id = intval($_REQUEST['room_id']);//直播ID 也是room_id
  293. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoRedisService.php');
  294. $video_redis = new VideoRedisService();
  295. $fields = array('vote_number','watch_number','is_live_pay','live_pay_time','live_pay_type','live_fee','live_is_mention','robot_num','virtual_watch_number','group_id');
  296. $video_number = $video_redis->getRow_db($room_id,$fields);
  297. $vote_number = intval($video_number['vote_number']);//获得印票数
  298. $watch_number = intval($video_number['watch_number']);//当前观看人数
  299. $group_id = strim($video_number['group_id']);//聊天组ID
  300. $live_pay_time = $video_number['live_pay_time'];//开始收费时间
  301. $live_pay_type = intval($video_number['live_pay_type']);//收费模式
  302. $live_fee = intval($video_number['live_fee']);//付费直播 收费多少
  303. $live_is_mention = intval($video_number['live_is_mention']);//收费模式 是否已经提档过
  304. if(intval($_REQUEST['watch_number']) > 0){
  305. //客户端有返回:当前观看人数 则取客户端返回的
  306. $watch_number = intval($_REQUEST['watch_number']);//当前观看人数
  307. }
  308. $lianmai_num = intval($_REQUEST['lianmai_num']);//当前连麦数量
  309. $live_quality = json_decode($_REQUEST['live_quality'],true);
  310. $appCPURate = intval($live_quality['appCPURate']);//appcpu占用率
  311. $sysCPURate = intval($live_quality['sysCPURate']);//系统cpu占用率
  312. $sendKBps = intval($live_quality['sendKBps']);//上行速率
  313. $recvKBps = intval($live_quality['recvKBps']);//下行速率
  314. $sendLossRate = intval($live_quality['sendLossRate']);//上行丢包率
  315. $fps = intval($live_quality['fps']);//视频帧率fps
  316. $device = strim($live_quality['device']);//设备系统
  317. $monitor_time = to_date(NOW_TIME,'Y-m-d H:i:s');
  318. //00:00; 05:00; 10:00; 15:00; ....; 55:00;
  319. $i_time = to_date(NOW_TIME,'i');
  320. $s_time = to_date(NOW_TIME,'s');
  321. if ($i_time >=55 && $s_time > 0){
  322. //放在下一小时的:00:00 时段
  323. $statistic_time = to_date(NOW_TIME + 330,'Y-m-d H:00:00');
  324. }else{
  325. if ($i_time >=50){
  326. $i_time2 = '55';
  327. }else if ($i_time >=45){
  328. $i_time2 = '50';
  329. }else if ($i_time >=40){
  330. $i_time2 = '45';
  331. }else if ($i_time >=35){
  332. $i_time2 = '40';
  333. }else if ($i_time >=30){
  334. $i_time2 = '35';
  335. }else if ($i_time >=25){
  336. $i_time2 = '30';
  337. }else if ($i_time >=20){
  338. $i_time2 = '25';
  339. }else if ($i_time >=15){
  340. $i_time2 = '20';
  341. }else if ($i_time >=10){
  342. $i_time2 = '15';
  343. }else if ($i_time >=5){
  344. $i_time2 = '10';
  345. }else{
  346. $i_time2 = '05';
  347. }
  348. $statistic_time = to_date(NOW_TIME,'Y-m-d H:').$i_time2.':00';
  349. }
  350. //更新最后心跳时间点
  351. $sql = "update ".DB_PREFIX."video set monitor_time = '".$monitor_time."' where live_in =1 and id = ".$room_id." and user_id = ".$user_id;
  352. $GLOBALS['db']->query($sql);
  353. if($GLOBALS['db']->affected_rows()){
  354. $video_monitor = array();
  355. $video_monitor['user_id'] = $user_id;
  356. $video_monitor['video_id'] = $room_id;
  357. $video_monitor['vote_number'] = $vote_number;
  358. $video_monitor['watch_number'] = $watch_number;
  359. $video_monitor['lianmai_num'] = $lianmai_num;
  360. $video_monitor['monitor_time'] = $monitor_time;
  361. $video_monitor['statistic_time'] = $statistic_time;
  362. $video_monitor['appCPURate'] = $appCPURate;
  363. $video_monitor['sysCPURate'] = $sysCPURate;
  364. $video_monitor['sendKBps'] = $sendKBps;
  365. $video_monitor['recvKBps'] = $recvKBps;
  366. $video_monitor['sendLossRate'] = $sendLossRate;
  367. $video_monitor['fps'] = $fps;
  368. $video_monitor['device'] = $device;
  369. $GLOBALS['db']->autoExecute(DB_PREFIX."video_monitor", $video_monitor,"INSERT");
  370. //在主播心跳接口monitor,做一次:连麦用户的IM通知更新,确保不漏单
  371. $root['push_lianmai'] = $this->push_lianmai($room_id);
  372. if($lianmai_num>0){
  373. $this->mix_stream2($room_id,0);
  374. }
  375. }
  376. }
  377. $live_pay= $GLOBALS['db']->getRow("SELECT id,class FROM ".DB_PREFIX."plugin WHERE is_effect=1 and type = 1 ");
  378. $m_config = load_auto_cache("m_config");//初始化手机端配置
  379. if((defined('OPEN_LIVE_PAY')&&OPEN_LIVE_PAY==1)&&$live_pay){
  380. $root['live']['allow_live_pay'] = 0;
  381. $root['live']['allow_mention'] = 0;
  382. $root['live']['live_fee'] = $live_fee;
  383. $root['live']['live_is_mention'] = $live_is_mention;
  384. $live_pay_type = intval($video_number['live_pay_type']);
  385. if(intval($m_config['live_pay_num'])<=intval($video_number['watch_number']+$video_number['robot_num']+$video_number['virtual_watch_number'])){
  386. if($live_pay_time!=''&&$live_fee>0){
  387. $root['live']['allow_live_pay'] = 2;//已经付费过
  388. }else{
  389. $root['live']['allow_live_pay'] = 1;//可以付费
  390. }
  391. }
  392. if((defined('PUBLIC_PAY')&&PUBLIC_PAY==1)&&$m_config['switch_public_pay']==1&&$m_config['public_pay']>0){
  393. $public_screen = $GLOBALS['db']->getOne("SELECT public_screen FROM ".DB_PREFIX."video WHERE user_id=" . $user_id . " and live_in=1");
  394. if($public_screen==1){
  395. $root['live']['allow_live_pay'] = 1;//可以付费
  396. }
  397. }
  398. if((intval($m_config['live_pay_rule']*60) <= intval(NOW_TIME-$live_pay_time))&&$live_pay_time>0&&$live_pay_type==0){
  399. if($live_is_mention){
  400. $root['live']['allow_mention'] = 2;//已经提档
  401. }else{
  402. $root['live']['allow_mention'] = 1;//可以提档
  403. }
  404. }
  405. //直播间主播获得的印票
  406. $sql = "select ticket from ".DB_PREFIX."user where id = ".$user_id;
  407. $users = $GLOBALS['db']->getRow($sql,true,true);
  408. $root['live']['ticket'] = intval($users['ticket']);
  409. //默认价格
  410. $root['live']['live_fee'] = intval($root['live']['live_fee'])>0?intval($root['live']['live_fee']):1;
  411. $live_time = $live_pay_time-NOW_TIME;
  412. $live_time = $live_time>0?intval($live_time):0;
  413. //实际付费人数
  414. if($live_pay_type==0){
  415. if($live_time==0){
  416. $times = get_gmtime()-120;
  417. $sql ="select id from ".DB_PREFIX."live_pay_log where total_diamonds>0 and video_id =".$room_id." and pay_time_end>=".$times." group by from_user_id ";
  418. $live_list = $GLOBALS['db']->getAll($sql,true,true);
  419. }else{
  420. $live_list = array();
  421. }
  422. }else{
  423. $live_list = $GLOBALS['db']->getAll("select id from ".DB_PREFIX."live_pay_log where total_diamonds>0 and video_id =".$room_id." group by from_user_id " ,true,true);
  424. }
  425. $live_viewer = count($live_list);
  426. $root['live']['live_viewer'] = intval($live_viewer);
  427. //收费类型 0是按时付费、1按场付费、2 普通付费
  428. if($live_pay_type==0&&intval($video_number['is_live_pay'])){
  429. $root['live']['live_pay_type'] = 0;
  430. }else if($live_pay_type==1&&intval($video_number['is_live_pay'])){
  431. $root['live']['live_pay_type'] = 1;
  432. }else{
  433. $root['live']['live_pay_type'] = 2;
  434. }
  435. }
  436. /*推送内容大小被限制,暂时不能用
  437. //推送观众列表
  438. //$dev_type = strim($_REQUEST['sdk_type']);
  439. //if($dev_type=='android'){
  440. $ext = array();
  441. $ext['type'] = 42; //42 通用数据格式
  442. $ext['data_type'] = 0 ;//直播间观众列表
  443. //消息发送者
  444. //$sender = array();
  445. //$ext['sender'] = $sender;
  446. //观众列表
  447. //$list = load_auto_cache("video_viewer",array('group_id'=>$group_id,'page'=>0));
  448. //$ext['list'] = $list; //礼物id
  449. //观众列表
  450. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoViewerRedisService.php');
  451. $video_viewer_redis = new VideoViewerRedisService();
  452. $viewer = $video_viewer_redis->get_viewer_list2($room_id,1,50);
  453. $ext['data'] = $viewer;
  454. //$ext['group_id'] = $group_id;
  455. #构造高级接口所需参数
  456. $msg_content = array();
  457. //创建array 所需元素
  458. $msg_content_elem = array(
  459. 'MsgType' => 'TIMCustomElem', //自定义类型
  460. 'MsgContent' => array(
  461. 'Data' => json_encode($ext),
  462. 'Desc' => '',
  463. // 'Ext' => $ext,
  464. // 'Sound' => '',
  465. )
  466. );
  467. //将创建的元素$msg_content_elem, 加入array $msg_content
  468. array_push($msg_content, $msg_content_elem);
  469. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  470. $api = createTimAPI();
  471. //$api->group_send_group_system_notification();
  472. $ret = $api->group_send_group_msg2($user_id, $group_id, $msg_content);
  473. if ($ret['ActionStatus'] == 'FAIL' && $ret['ErrorCode'] == 10002){
  474. //10002 系统错误,请再次尝试或联系技术客服。
  475. $ret = $api->group_send_group_msg2($user_id, $group_id, $msg_content);
  476. }
  477. //}
  478. $root['group_id'] = $group_id;
  479. $root['ret'] = $ret;
  480. $root['msg_content'] = $msg_content;
  481. */
  482. //设置直播间观众列表返回数量
  483. $page_size = intval($m_config['view_page_size'])>0?intval($m_config['view_page_size']):50;
  484. $root['ret'] = push_viewer($room_id,$group_id,$page_size);
  485. ajax_return($root);
  486. }
  487. /**
  488. * 获得一个正在直播的房间
  489. */
  490. function get_video2(){
  491. $root = array();
  492. //$GLOBALS['user_info']['id'] = 278;
  493. if(!$GLOBALS['user_info']){
  494. $root['error'] = "用户未登陆,请先登陆.";
  495. $root['status'] = 0;
  496. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  497. }else{
  498. //客服端手机类型dev_type=android;dev_type=ios
  499. $dev_type = strim($_REQUEST['sdk_type']);
  500. if (($dev_type == 'ios' || $dev_type == 'android')){
  501. $room_id = intval($_REQUEST['room_id']);//房间号id; 如果有的话,则返回当前房间信息;
  502. $user_id = intval($GLOBALS['user_info']['id']);//用户ID
  503. $type= intval($_REQUEST['type']);//type: 0:热门;1:最新;2:关注 [随机返回一个type类型下的直播]
  504. //强制升级不升级无法查看直播
  505. $status = 1;
  506. $m_config = load_auto_cache("m_config");//初始化手机端配置
  507. if(intval($m_config['forced_upgrade'])){
  508. $root =$this->compel_upgrade($m_config);
  509. $status = $root['status'];
  510. }
  511. if($status==1){
  512. //子房间
  513. if(defined('CHILD_ROOM') && CHILD_ROOM == 1) {
  514. fanwe_require(APP_ROOT_PATH.'mapi/lib/ChildRoom.class.php');
  515. $child_room = new child_room();
  516. $root = $child_room->get_child_video($room_id,$user_id,$type,$_REQUEST);
  517. }else{
  518. $root = get_video_info2($room_id, $user_id, $type, $_REQUEST);
  519. }
  520. if ($root['live_in'] == 1 && $root['user_id'] == $user_id){
  521. //主播重新进入自己的房间后,重新推一下:连麦观众消息
  522. $this->push_lianmai($room_id);
  523. }
  524. }
  525. }
  526. }
  527. ajax_return($root);
  528. }
  529. /**
  530. * 客户端,创建房间状态 回调
  531. * room_id:房间号id
  532. * status:1:成功,其它用户可以开始加入;1:失败
  533. */
  534. public function video_cstatus(){
  535. $root = array();
  536. //$GLOBALS['user_info']['id'] = 1;
  537. if(!$GLOBALS['user_info']){
  538. $root['error'] = "用户未登陆,请先登陆.";
  539. $root['status'] = 0;
  540. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  541. }else{
  542. $user_id = intval($GLOBALS['user_info']['id']);
  543. $room_id = strim($_REQUEST['room_id']);//房间号id
  544. $status = intval($_REQUEST['status']);//status: 1:成功,其它用户可以开始加入;0:创建失败; 2:主播离开; 3:主播回来
  545. //当$status=2,3时,下面3个参数可以不用传;
  546. $channelid = strim($_REQUEST['channelid']);//旁路直播,频道ID
  547. $play_rtmp = strim($_REQUEST['play_rtmp']);//旁路直播,播放地址
  548. $play_flv = strim($_REQUEST['play_flv']);//旁路直播,播放地址
  549. $play_hls = strim($_REQUEST['play_hls']);//旁路直播,播放地址
  550. //在返回的hls地址中,加入/live/这一层
  551. //@author jiangzuru
  552. $s1 = $play_hls;
  553. if ($s1 && strpos($s1, "com/live/") === false) {
  554. $pos1 = strpos($s1, "com/");
  555. $play_hls = substr_replace($s1, "live/", $pos1+4,0);
  556. }
  557. $group_id = strim($_REQUEST['group_id']);//group_id; Private,Public,ChatRoom,AVChatRoom
  558. //$room_type = intval($_REQUEST['room_type']);//房间类型 : 1私有群(Private),0公开群(Public),2聊天室(ChatRoom),3互动直播聊天室(AVChatRoom)
  559. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoRedisService.php');
  560. $video_redis = new VideoRedisService();
  561. if ($status == 2 || $status ==3){
  562. //online_status 主播在线状态;1:在线(默认); 0:离开
  563. if ($status == 2){
  564. $sql = "update ".DB_PREFIX."video set online_status = 0 where id = ".$room_id." and user_id = ".$user_id;
  565. }else{
  566. $sql = "update ".DB_PREFIX."video set online_status = 1 where id = ".$room_id." and user_id = ".$user_id;
  567. }
  568. $GLOBALS['db']->query($sql);
  569. if($GLOBALS['db']->affected_rows()){
  570. $root['status'] = 1;
  571. sync_video_to_redis($room_id,'online_status',false);
  572. }else{
  573. $root['status'] = 0;
  574. }
  575. }else{
  576. $set_fields = "";
  577. if ($group_id != ''){
  578. $set_fields .= ",group_id='".$group_id."'";
  579. }
  580. if ($channelid != ''){
  581. $set_fields .= ",channelid = '".$channelid."'";
  582. }
  583. if ($play_rtmp != ''){
  584. $set_fields .= ",play_rtmp = '".$play_rtmp."'";
  585. }
  586. if ($play_flv != ''){
  587. $set_fields .= ",play_flv = '".$play_flv."'";
  588. }
  589. if ($play_hls != ''){
  590. $set_fields .= ",play_hls = '".$play_hls."'";
  591. }
  592. $sql = "update ".DB_PREFIX."video set live_in = 1 ".$set_fields." where live_in =2 and id = ".$room_id." and user_id = ".$user_id;
  593. $GLOBALS['db']->query($sql);
  594. //live_in:是否直播中 1-直播中 0-已停止;2:正在创建直播;
  595. if($GLOBALS['db']->affected_rows()){
  596. if(defined('CHILD_ROOM') && CHILD_ROOM == 1){
  597. fanwe_require(APP_ROOT_PATH.'mapi/lib/ChildRoom.class.php');
  598. $child_room = new child_room();
  599. $child_room->cstatus($room_id);
  600. }
  601. $sql = "select user_id,room_type,title,city,cate_id from ".DB_PREFIX."video where id = ".$room_id;
  602. $video = $GLOBALS['db']->getRow($sql);
  603. $video_redis->video_online($room_id,$group_id);
  604. //将mysql数据,同步一份到redis中
  605. sync_video_to_redis($room_id,'*',false);
  606. if ($video['cate_id'] > 0){
  607. $sql = "update ".DB_PREFIX."video_cate a set a.num = (select count(*) from ".DB_PREFIX."video b where b.cate_id = a.id and b.live_in in (1,3)";
  608. $m_config = load_auto_cache("m_config");//初始化手机端配置
  609. if((defined('OPEN_ROOM_HIDE')&&OPEN_ROOM_HIDE==1)&&intval($m_config['open_room_hide'])==1){
  610. $sql.= " and b.province <> '火星' and b.province <>''";
  611. }
  612. $sql.=") where a.id = ".$video['cate_id'];
  613. $GLOBALS['db']->query($sql);
  614. }
  615. //
  616. if ($video['room_type'] == 3){
  617. crontab_robot($room_id);
  618. }
  619. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/UserRedisService.php');
  620. $user_redis = new UserRedisService();
  621. $user_data = $user_redis->getRow_db($user_id,array('id','nick_name','head_image'));
  622. $pushdata = array(
  623. 'user_id' =>$user_id, //'主播ID',
  624. 'nick_name' => $user_data['nick_name'],//'主播昵称',
  625. 'create_time' =>NOW_TIME, //'创建时间',
  626. 'cate_title' =>$video['title'],// '直播主题',
  627. 'room_id' =>$room_id,// '房间ID',
  628. 'city' =>$video['city'],// '直播城市地址',
  629. 'head_image' =>get_spec_image($user_data['head_image']),
  630. 'status' =>0,//'推送状态(0:未推送,1:推送中;2:已推送)'
  631. );
  632. $m_config = load_auto_cache("m_config");
  633. if(intval($m_config['service_push'])){
  634. $pushdata['pust_type'] =1; //'推送状态(0:粉丝推送,1:全服推送)';
  635. }else{
  636. $pushdata['pust_type'] =0; //'推送状态(0:粉丝推送,1:全服推送)';
  637. }
  638. $GLOBALS['db']->autoExecute(DB_PREFIX."push_anchor", $pushdata,'INSERT');
  639. $root['status'] = 1;
  640. }else{
  641. $sql = "update ".DB_PREFIX."video set live_in = 0".$set_fields.", end_time = ".NOW_TIME.", is_delete = 1 where live_in =2 and id = ".$room_id." and user_id = ".$user_id;
  642. $GLOBALS['db']->query($sql);
  643. if($GLOBALS['db']->affected_rows()){
  644. $root['status'] = 1;
  645. //将mysql数据,同步一份到redis中
  646. sync_video_to_redis($room_id,'*',false);
  647. }else{
  648. $root['status'] = 0;
  649. }
  650. }
  651. }
  652. }
  653. ajax_return($root);
  654. }
  655. /**
  656. * 贡献榜(当天,所有)
  657. * room_id: ===>如果有值,则取:本场直播贡献榜排行
  658. * user_id:===>取某个用户的:总贡献榜排行
  659. * p:不传或传0;则取前50位排行
  660. */
  661. public function cont(){
  662. $root = array();
  663. $room_id = intval($_REQUEST['room_id']);//当前正在直播的房间id
  664. $user_id = intval($_REQUEST['user_id']);//被查看的用户id
  665. if($room_id == 0 && $user_id == 0){
  666. $user_id = intval($GLOBALS['user_info']['id']);//取当前用户的id
  667. }
  668. if($room_id == 0 && $user_id == 0){
  669. $root['error'] = "房间ID跟用户ID必须传一个";
  670. $root['status'] = 0;
  671. }else{
  672. $page = intval($_REQUEST['p']);//取第几页数据
  673. $page_size = 50;
  674. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoContributionRedisService.php');
  675. $video_con = new VideoContributionRedisService($user_id);
  676. if ($room_id > 0){
  677. // //当日对主播的贡献榜排行
  678. $root = $video_con->get_video_contribute($room_id,$page,$page_size);
  679. $root['total_num'] = intval($root['total_ticket_num']);
  680. $root['v_icon'] = $root['user']['v_icon'];
  681. $root['user']['ticket'] = intval($root['user']['ticket']);
  682. }else{
  683. //总贡献榜排行
  684. //用户总票数
  685. $root = $video_con->get_podcast_contribute($user_id,$page,$page_size);
  686. $root['total_num'] = intval(floor($root['user']['ticket']));
  687. }
  688. foreach($root['list'] as $k=>$v)
  689. {
  690. $root['list'][$k]['nick_name'] = emoji_decode($root['list'][$k]['nick_name']);
  691. $root['list'][$k]['use_ticket'] = intval($root['list'][$k]['num']);
  692. $root['list'][$k]['ticket'] = intval($root['list'][$k]['ticket']);
  693. }
  694. }
  695. $root['user']['nick_name'] = emoji_decode($root['user']['nick_name']);
  696. ajax_return($root);
  697. }
  698. /**
  699. * 检查用户是否有发起连麦的权限
  700. */
  701. public function check_lianmai()
  702. {
  703. $root = array();
  704. if(!$GLOBALS['user_info']){
  705. $root['error'] = "用户未登陆,请先登陆.";// es_session::id();
  706. $root['status'] = 0;
  707. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  708. }else{
  709. $user_id = $GLOBALS['user_info']['id'];//申请连麦的用户id
  710. $room_id = intval($_REQUEST['room_id']);//当前正在直播的房间id
  711. $root['status'] = 1;
  712. }
  713. ajax_return($root);
  714. }
  715. /**
  716. * 开始连麦(主播同意后,主播调用)
  717. */
  718. public function start_lianmai()
  719. {
  720. $root = array();
  721. if(!$GLOBALS['user_info']){
  722. $root['error'] = "用户未登陆,请先登陆.";
  723. $root['status'] = 0;
  724. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  725. }else{
  726. $to_user_id = intval($_REQUEST['to_user_id']);//申请连麦的用户id
  727. $room_id = intval($_REQUEST['room_id']);//当前正在直播的房间id
  728. $m_config = load_auto_cache('m_config');
  729. $qcloud_security_key = $m_config['qcloud_security_key'];
  730. $bizId = $m_config['qcloud_bizid'];
  731. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  732. $video_redis = new VideoRedisService();
  733. $data = $video_redis->getRow_db($room_id, array('channelid','video_type','play_rtmp','push_rtmp'));
  734. $video_lianmai = array();
  735. if ($data['video_type'] == 1 && !empty($qcloud_security_key)) {
  736. //直播码 方式
  737. fanwe_require(APP_ROOT_PATH.'mapi/lib/core/video_factory.php');
  738. $video_factory = new VideoFactory();
  739. $channel_info = $video_factory->GetChannelInfo($to_user_id,'s',$room_id,$to_user_id);
  740. $video_lianmai['channelid'] = $channel_info['channel_id'];
  741. $video_lianmai['push_rtmp'] = $channel_info['upstream_address'];
  742. $video_lianmai['play_rtmp'] = $channel_info['downstream_address']['rtmp'];
  743. //小主播的 push_rtmp 推流地址
  744. $push_rtmp2 = $video_lianmai['push_rtmp'];
  745. $root['push_rtmp2'] = $push_rtmp2;//小主播的 push_rtmp 推流地址
  746. //小主播的 rtmp_acc 播放地址; 12小时失效
  747. $play_rtmp2_acc = $video_lianmai['play_rtmp'] ."?bizid=".$bizId."&".$video_factory->get_acc_sign($qcloud_security_key,$video_lianmai['channelid'],43200);
  748. $play_rtmp2_acc = $play_rtmp2_acc.'&session_id='.$room_id;//str_pad($room_id,32,'0',STR_PAD_LEFT);
  749. $root['play_rtmp2_acc'] = $play_rtmp2_acc;//小主播的 rtmp_acc 播放地址;
  750. //大主播的 rtmp_acc 播放地址; 12小时失效
  751. $play_rtmp_acc = $data['play_rtmp'] ."?bizid=".$bizId."&".$video_factory->get_acc_sign($qcloud_security_key,$data['channelid'],43200);
  752. $play_rtmp_acc = $play_rtmp_acc.'&session_id='.$room_id;//str_pad($room_id,32,'0',STR_PAD_LEFT);
  753. $root['play_rtmp_acc'] = $play_rtmp_acc;//大主播的 rtmp_acc 播放地址;
  754. $video_lianmai['play_rtmp_acc'] = $root['play_rtmp2_acc'];
  755. $video_lianmai['v_play_rtmp_acc'] = $root['play_rtmp_acc'];
  756. }
  757. //如果用户有旧的:连麦没结束,则把它结束掉
  758. $sql = 'update '.DB_PREFIX."video_lianmai set stop_time ='".NOW_TIME."' where stop_time = 0 and video_id =".$room_id." and user_id =".$to_user_id;
  759. $GLOBALS['db']->query($sql);
  760. $video_lianmai['user_id'] = $to_user_id;
  761. $video_lianmai['video_id'] = $room_id;
  762. $video_lianmai['start_time'] = NOW_TIME;
  763. $GLOBALS['db']->autoExecute(DB_PREFIX."video_lianmai", $video_lianmai,"INSERT");
  764. $video_lianmai_id = $GLOBALS['db']->insert_id();
  765. $root['video_lianmai_id'] = $video_lianmai_id;
  766. if ($video_lianmai_id > 0){
  767. $root['status'] = 1;
  768. $this->push_lianmai($room_id);
  769. }else{
  770. $root['status'] = 0;
  771. $root['error'] = "连麦数据记录出错";
  772. }
  773. }
  774. ajax_return($root);
  775. }
  776. /**
  777. * 推送:连麦观众列表,到 连麦观众APP端
  778. * @param unknown_type $video_id
  779. * @return mixed|string
  780. */
  781. private function push_lianmai($video_id){
  782. $user_id = intval($GLOBALS['user_info']['id']);
  783. $m_config = load_auto_cache('m_config');
  784. $qcloud_security_key = $m_config['qcloud_security_key'];
  785. $bizId = $m_config['qcloud_bizid'];
  786. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  787. $video_redis = new VideoRedisService();
  788. $video = $video_redis->getRow_db($video_id, array('channelid','group_id','user_id','video_type','play_rtmp','push_rtmp'));
  789. $receiver_list = array();
  790. //直播码 方式
  791. if ($video['video_type'] == 1 && !empty($qcloud_security_key)) {
  792. $receiver_list[] = $video['user_id'];
  793. fanwe_require(APP_ROOT_PATH.'mapi/lib/core/video_factory.php');
  794. $video_factory = new VideoFactory();
  795. $data = array();
  796. //大主播的 rtmp_acc 播放地址; 5分钟失效
  797. $play_rtmp_acc = $video['play_rtmp'] ."?bizid=".$bizId."&".$video_factory->get_acc_sign($qcloud_security_key,$video['channelid'],3000);
  798. $play_rtmp_acc = $play_rtmp_acc.'&session_id='.$video_id;//str_pad($room_id,32,'0',STR_PAD_LEFT);
  799. $data['play_rtmp_acc'] = $play_rtmp_acc;//大主播的 rtmp_acc 播放地址;
  800. $data['push_rtmp'] = $video['push_rtmp'];//大主播的 push_rtmp 推流地址;
  801. //获得连麦观众的列表,最多取最新3个
  802. $sql = "select user_id,push_rtmp,play_rtmp,channelid from ".DB_PREFIX."video_lianmai where stop_time = 0 and video_id =".$video_id ." order by start_time desc limit 3";
  803. $list = $GLOBALS['db']->getAll($sql,true,true);
  804. $list_lianmai = array();
  805. $total = count($list);
  806. if ($total > 0) {
  807. $image_layer = 2;
  808. foreach ( $list as $k => $v )
  809. {
  810. $user = array();
  811. $user['user_id'] = $v['user_id'];
  812. $receiver_list[] = $v['user_id'];
  813. $user['push_rtmp2'] = $v['push_rtmp'];//小主播的 push_rtmp 推流地址
  814. //小主播的 rtmp_acc 播放地址; 5分钟失效
  815. $play_rtmp2_acc = $v['play_rtmp'] ."?bizid=".$bizId."&".$video_factory->get_acc_sign($qcloud_security_key,$v['channelid'],3000);
  816. $play_rtmp2_acc = $play_rtmp2_acc.'&session_id='.$video_id;//str_pad($room_id,32,'0',STR_PAD_LEFT);
  817. $user['play_rtmp2_acc'] = $play_rtmp2_acc;//小主播的 rtmp_acc 播放地址;
  818. $user['layout_params'] = $this->get_lianmai_layout($total, $image_layer);
  819. $image_layer ++;
  820. $list_lianmai[] = $user;
  821. }
  822. }
  823. $data['list_lianmai'] = $list_lianmai;
  824. }
  825. if (count($receiver_list) > 0){
  826. $ext = array();
  827. $ext['type'] = 42; //42 通用数据格式
  828. $ext['data_type'] = 1;//直播间,连麦观众列表
  829. $ext['data'] = $data;
  830. //$ext['receiver_list'] = $receiver_list;
  831. $msg_content = json_encode($ext);
  832. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  833. $api = createTimAPI();
  834. $ret = $api->group_send_group_system_notification2($video['group_id'], $msg_content,$receiver_list);
  835. //$ret['receiver_list'] = $receiver_list;
  836. return $ret;
  837. }else{
  838. $root['status'] = 0;
  839. $root['error'] = "无效数据";
  840. return $root;
  841. }
  842. }
  843. /**
  844. * 获得混流小主播大小,位置参数
  845. * @param unknown_type $total 小主播个数
  846. * @param unknown_type $image_layer 小主播图层标识号,从2开始; 大主播填 1 ; 小主播按照顺序填写2、3、4
  847. */
  848. private function get_layout($total, $image_layer, $video_resolution_type){
  849. if($video_resolution_type == 1){
  850. //高清(540*960)
  851. $width = 540;
  852. $height = 960;
  853. }else if ($video_resolution_type == 2){
  854. //超清(720*1280)
  855. $width = 720;
  856. $height = 1280;
  857. }else{
  858. $width = 360;
  859. $height = 640;
  860. }
  861. $layout_params = $this->get_lianmai_layout($total, $image_layer);
  862. $layout_params['image_width'] = intval($layout_params['image_width'] * $width);//小主播画面宽度
  863. $layout_params['image_height'] = intval($layout_params['image_height'] * $height);//小主播画面高度
  864. $layout_params['location_x'] = intval($layout_params['location_x'] * $width);//x偏移:相对于大主播背景画面左上角的横向偏移
  865. $layout_params['location_y'] = intval($layout_params['location_y'] * $height);//y偏移:相对于大主播背景画面左上角的纵向偏移
  866. return $layout_params;
  867. }
  868. /**
  869. * app连麦观众 的小窗口排序
  870. * @param unknown_type $total
  871. * @param unknown_type $image_layer
  872. * @return multitype:number unknown
  873. */
  874. private function get_lianmai_layout($total, $image_layer){
  875. $image_width = 0.3;//小主播画面宽度
  876. $image_height = 0.27;//小主播画面高度
  877. $layout_params = array();
  878. $layout_params['image_layer'] = $image_layer;//图层标识号:大主播填 1 ; 小主播按照顺序填写2、3、4
  879. $layout_params['image_width'] = $image_width;//小主播画面宽度
  880. $layout_params['image_height'] = $image_height;//小主播画面高度
  881. $layout_params['location_x'] = 0.66;//x偏移:相对于大主播背景画面左上角的横向偏移
  882. if ($total == 1){
  883. $layout_params['location_y'] = 0.61 ;//y偏移:相对于大主播背景画面左上角的纵向偏移
  884. }else if ($total == 2){
  885. if ($image_layer == 2){
  886. $layout_params['location_y'] = 0.61;//y偏移:相对于大主播背景画面左上角的纵向偏移
  887. }else{
  888. $layout_params['location_y'] = 0.61 - $image_height - 0.005;//y偏移:相对于大主播背景画面左上角的纵向偏移
  889. }
  890. }else{
  891. if ($image_layer == 2){
  892. $layout_params['location_y'] = 0.635; //y偏移:相对于大主播背景画面左上角的纵向偏移
  893. }else if ($image_layer == 3){
  894. $layout_params['location_y'] = 0.635 - $image_height - 0.005; //y偏移:相对于大主播背景画面左上角的纵向偏移
  895. }else{
  896. $layout_params['location_y'] = 0.635 -($image_height + 0.005)*2; //y偏移:相对于大主播背景画面左上角的纵向偏移
  897. }
  898. }
  899. return $layout_params;
  900. }
  901. /**
  902. * 结束连麦(主播调用)
  903. */
  904. public function stop_lianmai()
  905. {
  906. //$GLOBALS['user_info']['id'] = 270;
  907. $root = array();
  908. if(!$GLOBALS['user_info']){
  909. $root['error'] = "用户未登陆,请先登陆.";
  910. $root['status'] = 0;
  911. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  912. }else{
  913. $user_id = intval($GLOBALS['user_info']['id']);
  914. $room_id = intval($_REQUEST['room_id']);//当前正在直播的房间id
  915. $to_user_id = intval($_REQUEST['to_user_id']);//申请连麦的用户id
  916. if ($to_user_id > 0){
  917. //只有主播,才可以结束其它人的连麦
  918. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  919. $video_redis = new VideoRedisService();
  920. $video = $video_redis->getRow_db($room_id, array('user_id','video_type'));
  921. if ($video['user_id'] != $user_id){
  922. $to_user_id = $user_id;//如果不是主播的话,只能结束自己的连麦
  923. }
  924. }else{
  925. $to_user_id = $user_id;
  926. }
  927. $sql = 'update '.DB_PREFIX."video_lianmai set stop_time ='".NOW_TIME."' where stop_time = 0 and video_id =".$room_id." and user_id =".$to_user_id;
  928. $GLOBALS['db']->query($sql);
  929. //有人:结束连麦,通知:其它连麦用户
  930. $this->push_lianmai($room_id);
  931. //混合更新
  932. $this->mix_stream2($room_id,$to_user_id);
  933. $root['status'] = 1;
  934. }
  935. ajax_return($root);
  936. }
  937. /**
  938. * 混合
  939. * https://www.qcloud.com/document/product/454/8872
  940. */
  941. private function mix_stream2($room_id,$to_user_id){
  942. $m_config = load_auto_cache('m_config');
  943. $qcloud_security_key = $m_config['qcloud_security_key'];
  944. $bizId = $m_config['qcloud_bizid'];
  945. fanwe_require(APP_ROOT_PATH . 'mapi/lib/redis/VideoRedisService.php');
  946. $video_redis = new VideoRedisService();
  947. $video = $video_redis->getRow_db($room_id, array('channelid','video_type','user_id', 'play_rtmp','push_rtmp'));
  948. //print_r($video);
  949. //直播码 方式 && $user_id == $video['user_id']
  950. if ($video['video_type'] == 1 && !empty($qcloud_security_key)) {
  951. $data = array();
  952. $data['timestamp'] = NOW_TIME;//UNIX时间戳,即从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数
  953. $data['eventId'] = NOW_TIME;//混流事件ID,取时间戳即可,后台使用
  954. $interface = array();
  955. $interface['interfaceName'] = 'Mix_StreamV2';//固定取值"Mix_StreamV2"
  956. $para = array();
  957. $para['app_id'] = $m_config['vodset_app_id'];//# 填写直播APPID
  958. $para['interface'] = "mix_streamv2.start_mix_stream_advanced";//# 固定取值"mix_streamv2.start_mix_stream_advanced"
  959. $para['mix_stream_session_id'] = $video['channelid'] ;// 填大主播的流ID
  960. $para['output_stream_id'] = $video['channelid'] ;// 填大主播的流ID
  961. $input_stream_list = array();
  962. $user = array();
  963. $user['input_stream_id'] = $video['channelid'];//流ID
  964. $user['layout_params']['image_layer'] = 1;//图层标识号:大主播填 1 ; 小主播按照顺序填写2、3、4
  965. $input_stream_list[] = $user;
  966. //获得连麦观众的列表,最多取最新3个
  967. $sql = "select user_id,play_rtmp,play_rtmp,channelid from ".DB_PREFIX."video_lianmai where stop_time = 0 and video_id =".$room_id ." order by start_time desc limit 3";
  968. $list = $GLOBALS['db']->getAll($sql,true,true);
  969. $total = count($list);
  970. if ($total > 0) {
  971. $image_layer = 2;
  972. foreach ( $list as $k => $v )
  973. {
  974. $user = array();
  975. $user['input_stream_id'] = $v['channelid'];//流ID
  976. $user['layout_params'] = $this->get_layout($total, $image_layer,$m_config['video_resolution_type']);
  977. //$user['layout_params2'] = $this->get_lianmai_layout($total, $image_layer);
  978. $input_stream_list[] = $user;
  979. $image_layer ++;
  980. }
  981. }
  982. $para['input_stream_list'] = $input_stream_list;
  983. $interface['para'] = $para;
  984. $data['interface'] = $interface;
  985. $key = $m_config['qcloud_auth_key'];//$qcloud_security_key
  986. $t = get_gmtime() + 86400;
  987. //http://fcgi.video.qcloud.com/common_access?cmd=appid&interface=Mix_StreamV2&t=t&sign=sign
  988. $url = "http://fcgi.video.qcloud.com/common_access?" . http_build_query(array(
  989. 'cmd' => $m_config['vodset_app_id'],
  990. 'interface' => 'Mix_StreamV2',
  991. 't' => $t,
  992. 'sign' => md5($key . $t)
  993. ));
  994. //echo $url;
  995. //print_r($data);
  996. fanwe_require(APP_ROOT_PATH .'mapi/lib/core/transport.php');
  997. $trans = new transport();
  998. $post_json = json_encode($data);
  999. //print_r($post_json);
  1000. $req = $trans->request($url,$post_json,'POST');
  1001. //print_r($post_json);
  1002. //print_r($req);
  1003. $req = json_decode($req['body'],1);
  1004. if ($req['code'] == 0){
  1005. $return['status'] =1;
  1006. }else{
  1007. $return['status'] = 0;
  1008. }
  1009. if(intval(IS_DEBUG)){
  1010. $return['error'] = $req['message'];
  1011. }else{
  1012. $return['error'] = '';
  1013. }
  1014. //$return['url'] = $url;
  1015. //$return['key'] = $key;
  1016. //$return['daqcloud_security_key'] = $qcloud_security_key;
  1017. //$return['data'] = $data;
  1018. $return['req'] = $req;
  1019. }else{
  1020. $return['error'] = "无效直播间";
  1021. $return['status'] =0;
  1022. }
  1023. return $return;
  1024. }
  1025. public function mix_stream(){
  1026. if(!$GLOBALS['user_info'] && false){
  1027. $return['error'] = "用户未登陆,请先登陆.";
  1028. $return['status'] =0;
  1029. $return['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1030. }else{
  1031. $user_id = intval($GLOBALS['user_info']['id']);
  1032. $room_id = intval($_REQUEST['room_id']);//当前正在直播的房间id
  1033. $to_user_id = intval($_REQUEST['to_user_id']);//app端上传,那个小主播拉流成功,预留
  1034. $return = $this->mix_stream2($room_id,$to_user_id);
  1035. }
  1036. ajax_return($return);
  1037. }
  1038. //开始直播,加入预先创建房间 并修改 begin_time状态
  1039. public function add_video(){
  1040. if(!$GLOBALS['user_info']){
  1041. $return['error'] = "用户未登陆,请先登陆.";
  1042. $return['status'] =0;
  1043. $return['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1044. }else{
  1045. //用户是否禁播,$is_ban=1 永久禁播;$is_ban=0非永久禁播,$ban_time禁播结束时间
  1046. $user_id = intval($GLOBALS['user_info']['id']);
  1047. $sql = "select is_authentication,is_ban,ban_time,mobile,login_ip,ban_type,apns_code,sex,ticket,refund_ticket,user_level,fans_count,head_image,thumb_head_image from ".DB_PREFIX."user where id = ".$user_id;
  1048. $user = $GLOBALS['db']->getRow($sql,true,true);
  1049. $video_classified=intval($_REQUEST['video_classified']);
  1050. $is_authentication = intval($user['is_authentication']);
  1051. $m_config=load_auto_cache("m_config");
  1052. if(!isset($m_config['video_type'])){
  1053. $re = array("error"=>"直播类型不存在","status"=>0);
  1054. ajax_return($re);
  1055. }
  1056. $dev_type = strim($_REQUEST['sdk_type']);
  1057. $sdk_version_name = strim($_REQUEST['sdk_version_name']);
  1058. //提过限制开播
  1059. $allow = 0;
  1060. if($user['mobile']=='13888888888'&&$m_config['ios_check_version'] != ''&&$m_config['ios_check_version'] == $sdk_version_name){
  1061. $allow = 1;
  1062. }
  1063. if($user['mobile']=='13999999999'&&$m_config['ios_check_version'] != ''){
  1064. $allow = 1;
  1065. }
  1066. if($allow){
  1067. $is_authentication = 2;
  1068. $m_config['is_limit_time'] = 0;
  1069. }
  1070. if($m_config['must_authentication']==1&&$is_authentication!=2){
  1071. $re = array("error"=>"请认证后再发起直播 ","status"=>0);
  1072. ajax_return($re);
  1073. }
  1074. if(intval($m_config['is_limit_time'])==1){
  1075. $now = to_date(get_gmtime(),"H");
  1076. if(intval($m_config['is_limit_time_end'])==intval($m_config['is_limit_time_start'])){
  1077. $re = array("error"=>"直播功能已关闭","status"=>0);
  1078. ajax_return($re);
  1079. }
  1080. $to_day = 1;
  1081. if(intval($m_config['is_limit_time_start'])>intval($m_config['is_limit_time_end'])){
  1082. $to_day = 0;
  1083. }
  1084. if($to_day==0&&intval($m_config['is_limit_time_start'])>$now&&intval($m_config['is_limit_time_end'])<=$now){
  1085. $re = array("error"=>"请在每天的".intval($m_config['is_limit_time_start'])."时到第二天的".intval($m_config['is_limit_time_end'])."时期间进行直播","status"=>0);
  1086. ajax_return($re);
  1087. }
  1088. if($to_day==1&&(intval($m_config['is_limit_time_start'])>$now||intval($m_config['is_limit_time_end'])<=$now)){
  1089. $re = array("error"=>"请在每天的".intval($m_config['is_limit_time_start'])."时到".intval($m_config['is_limit_time_end'])."时期间进行直播","status"=>0);
  1090. ajax_return($re);
  1091. }
  1092. }
  1093. // $apns_code = addslashes($_REQUEST['apns_code']);
  1094. // if($user['ban_type']==1&&$user['login_ip']==get_client_ip()&&$user['is_ban']==1){
  1095. // $re =array("error"=>"请求房间id失败,当前IP已被封停,请联系客服处理","status"=>0);
  1096. // ajax_return($re);
  1097. // }
  1098. //
  1099. // if($user['ban_type']==2&&$user['apns_code']==$apns_code&&$user['is_ban']==1){
  1100. // $re = array("error"=>"请求房间id失败,当前设备已被禁用,请联系客服处理","status"=>0);
  1101. // ajax_return($re);
  1102. // }
  1103. if($GLOBALS['db']->getRow("select ban_ip from ".DB_PREFIX."ban_list where ban_type=1 and ban_ip='".$user['login_ip']."'")){
  1104. $re =array("error"=>"请求房间id失败,当前IP已被封停,请联系客服处理","status"=>0);
  1105. ajax_return($re);
  1106. }
  1107. if($GLOBALS['db']->getRow("select apns_code from ".DB_PREFIX."ban_list where ban_type=2 and apns_code='".$user['apns_code']."'")){
  1108. $re = array("error"=>"请求房间id失败,当前设备已被禁用,请联系客服处理","status"=>0);
  1109. ajax_return($re);
  1110. }
  1111. if(intval($user['is_ban']) == 0 && intval($user['ban_time']) < get_gmtime()){
  1112. //$_REQUEST['title'] = $_REQUEST['title']?$_REQUEST['title']:"#新人直播#";
  1113. $title = strim(str_replace('#','',$_REQUEST['title']));
  1114. //$title = iconv("UTF-8","UTF-8//IGNORE",$title);
  1115. //===lym start====
  1116. $cate_name = $title;
  1117. //===lym end===
  1118. $cate_id = intval($_REQUEST['cate_id']);
  1119. $xpoint = floatval($_REQUEST['xpoint']);//x座标(用来计算:附近)
  1120. $ypoint = floatval($_REQUEST['ypoint']);//y座标(用来计算:附近)
  1121. $live_image = strim($_REQUEST['live_image']);//图片地址,手机端图片先上传到oss,然后获得图片地址,再跟其它资料一起提交到服务器
  1122. $location_switch = intval($_REQUEST['location_switch']);//1-上传当前城市名称
  1123. $province = strim($_REQUEST['province']);//省
  1124. $city = strim($_REQUEST['city']);//市
  1125. $is_private = intval($_REQUEST['is_private']);//1:私密聊天; 0:公共聊天
  1126. $share_type = strtolower(strim($_REQUEST['share_type']));//WEIXIN,WEIXIN_CIRCLE,QQ,QZONE,EMAIL,SMS,SINA
  1127. if ($share_type == 'null'){
  1128. $share_type = '';
  1129. }
  1130. //检查话题长度
  1131. if(strlen($title)>60){
  1132. $return['error'] = "话题太长";
  1133. $return['status'] =0;
  1134. ajax_return($return);
  1135. }
  1136. //$private_ids = strim($_REQUEST['private_ids']);//字符串类型的私聊好友id 23,123,3455 以英文逗号分割的字符串 只有私聊时才需要上传这个参数
  1137. $sql = "select id,video_type from ".DB_PREFIX."video where live_in =2 and user_id = ".$user_id;
  1138. $video = $GLOBALS['db']->getRow($sql,true,true);
  1139. if ($video){
  1140. //更新心跳时间,免得被删除了
  1141. $sql = "update ".DB_PREFIX."video set monitor_time = '".to_date(NOW_TIME,'Y-m-d H:i:s')."' where id =".$video['id'];
  1142. $GLOBALS['db']->query($sql);
  1143. if($GLOBALS['db']->affected_rows()){
  1144. //如果数据库中发现,有一个正准备执行中的,则直接返回当前这条记录;
  1145. $return['status'] =1;
  1146. $return['error'] ='';
  1147. $return['room_id'] = intval($video['id']);
  1148. $return['video_type'] = intval($video['video_type']);
  1149. ajax_return($return);
  1150. }
  1151. }
  1152. //关闭 之前的房间,非正常结束的直播,还在通知所有人:退出房间
  1153. $sql = "select id,user_id,watch_number,vote_number,group_id,room_type,begin_time,end_time,channelid,video_vid,cate_id from ".DB_PREFIX."video where live_in =1 and user_id = ".$user_id;
  1154. $list = $GLOBALS['db']->getAll($sql,true,true);
  1155. foreach ( $list as $k => $v )
  1156. {
  1157. //结束直播
  1158. do_end_video($v,$v['video_vid'],1,$v['cate_id']);
  1159. }
  1160. //话题
  1161. if($cate_id){
  1162. //$cate_title = $GLOBALS['db']->getOne("select title from ".DB_PREFIX."video_cate where id=".$cate_id,true,true);
  1163. $cate = load_auto_cache("cate_id",array('id'=>$cate_id));
  1164. $cate_title = $cate['title'];
  1165. if($cate_title != $title){
  1166. $cate_id = 0;
  1167. }
  1168. }
  1169. if ($cate_id == 0 && $title != ''){
  1170. $cate_id = $GLOBALS['db']->getOne("select id from ".DB_PREFIX."video_cate where title='".$title."'",true,true);
  1171. if($cate_id){
  1172. $is_newtitle = 0;
  1173. }else{
  1174. $is_newtitle = 1;
  1175. }
  1176. }
  1177. if($is_newtitle){
  1178. $data_cate = array();
  1179. $data_cate['title'] = $title;
  1180. $data_cate['is_effect'] =1 ;
  1181. $data_cate['is_delete'] =0;
  1182. $data_cate['create_time'] =NOW_TIME;
  1183. $GLOBALS['db']->autoExecute(DB_PREFIX."video_cate", $data_cate,'INSERT');
  1184. $cate_id = $GLOBALS['db']->insert_id();
  1185. }
  1186. if($m_config['must_cate']==1){
  1187. if(!$cate_id){
  1188. $re = array("error"=>"直播话题不能为空","status"=>0);
  1189. ajax_return($re);
  1190. }
  1191. }
  1192. //添加位置
  1193. if ($province == 'null'){
  1194. $province = '';
  1195. }
  1196. if ($city == 'null'){
  1197. $city = '';
  1198. }
  1199. $province = str_replace("省", "", $province);
  1200. $city = str_replace("市", "", $city);
  1201. if (($province == '' || $city == '') && $location_switch == 1){
  1202. /*
  1203. //客户端没有定位到,服务端则用ip再定位一次
  1204. fanwe_require APP_ROOT_PATH . "system/extend/ip.php";
  1205. $ip = new iplocate ();
  1206. $area = $ip->getaddress ( CLIENT_IP );
  1207. $location = $area ['area1'];
  1208. */
  1209. $ipinfo = get_ip_info();
  1210. $province = $ipinfo['province'];
  1211. $city = $ipinfo['city'];
  1212. //$title = print_r($ipinfo,1);
  1213. }
  1214. if ($province == ''){
  1215. $province= '火星';
  1216. }
  1217. if ($city == ''){
  1218. $city= '火星';
  1219. }
  1220. if($city=='火星'||$province=='火星'){
  1221. $xpoint = '';//x座标(用来计算:附近)
  1222. $ypoint = '';//y座标(用来计算:附近)
  1223. }
  1224. //
  1225. $video_id = get_max_room_id(0);
  1226. $data =array();
  1227. $data['id'] = $video_id;
  1228. //room_type 房间类型 : 1私有群(Private),0公开群(Public),2聊天室(ChatRoom),3互动直播聊天室(AVChatRoom)
  1229. if ($is_private == 1){
  1230. $data['room_type'] = 1;
  1231. $data['private_key'] = md5($video_id.rand(1,9999999));//私密直播key
  1232. }else
  1233. $data['room_type'] = 3;
  1234. $data['virtual_number'] = intval($m_config['virtual_number']);
  1235. $data['max_robot_num'] = intval($m_config['robot_num']);//允许添加的最大机器人数;
  1236. /*$sql = "select sex,ticket,refund_ticket,user_level,fans_count,head_image,thumb_head_image from ".DB_PREFIX."user where id = ".$user_id;
  1237. $user = $GLOBALS['db']->getRow($sql,true,true);*/
  1238. //图片,应该从客户端上传过来,如果没上传图片再用会员头像
  1239. if ($live_image!=''&&$live_image!='./(null)'){
  1240. fanwe_require(APP_ROOT_PATH .'mapi/lib/core/transport.php');
  1241. $trans = new transport();
  1242. $req = $trans->request(get_spec_image($live_image),'','GET');
  1243. if(strlen($req['body'])>1000){
  1244. $data['live_image'] = $live_image;
  1245. }else{
  1246. $data['live_image'] = $user['head_image'];
  1247. }
  1248. }else{
  1249. $data['live_image'] = $user['head_image'];
  1250. }
  1251. $data['head_image'] = $user['head_image'];
  1252. $data['thumb_head_image'] = $user['thumb_head_image'];
  1253. $data['sex'] = intval($user['sex']);//性别 0:未知, 1-男,2-女
  1254. $data['xpoint'] = $xpoint;
  1255. $data['ypoint'] = $ypoint;
  1256. $data['video_type'] = intval($m_config['video_type']);//0:腾讯云互动直播;1:腾讯云直播
  1257. if($data['video_type'] > 0){
  1258. require_once(APP_ROOT_PATH.'system/tim/TimApi.php');
  1259. $api = createTimAPI();
  1260. $ret = $api->group_create_group('AVChatRoom', (string)$user_id, (string)$user_id, (string)$video_id);
  1261. if ($ret['ActionStatus'] != 'OK'){
  1262. ajax_return(array(
  1263. 'status' => 0,
  1264. 'error' => $ret['ErrorCode'].$ret['ErrorInfo']
  1265. ));
  1266. }
  1267. $data['group_id'] = $ret['GroupId'];
  1268. fanwe_require(APP_ROOT_PATH.'mapi/lib/core/video_factory.php');
  1269. $video_factory = new VideoFactory();
  1270. $channel_info = $video_factory->Create($video_id,'mp4',$user_id);
  1271. if(! empty($channel_info['video_type'])) {
  1272. $data['video_type'] = $channel_info['video_type'];
  1273. }
  1274. $data['channelid'] = $channel_info['channel_id'];
  1275. $data['push_rtmp'] = $channel_info['upstream_address'];
  1276. $data['play_flv'] = $channel_info['downstream_address']['flv'];
  1277. $data['play_rtmp'] = $channel_info['downstream_address']['rtmp'];
  1278. $data['play_hls'] = $channel_info['downstream_address']['hls'];
  1279. }
  1280. $data['monitor_time'] = to_date(NOW_TIME,'Y-m-d H:i:s');//主播心跳监听
  1281. $data['push_url'] = '';//video_type=1;1:腾讯云直播推流地址
  1282. $data['play_url'] = '';//video_type=1;1:腾讯云直播播放地址(rmtp,flv)
  1283. $data['share_type'] = $share_type;
  1284. $data['title'] = $title;
  1285. $data['cate_id'] = $cate_id;
  1286. $data['video_classified'] = $video_classified;
  1287. $data['user_id'] = $user_id;
  1288. $data['live_in'] = 2;//live_in:是否直播中 1-直播中 0-已停止;2:正在创建直播;
  1289. $data['watch_number'] = '';//'当前观看人数';
  1290. $data['vote_number'] = '';//'获得票数';
  1291. $data['province'] = $province;//'省';
  1292. $data['city'] = $city;//'城市';
  1293. $data['create_time'] = NOW_TIME;//'创建时间';
  1294. $data['begin_time'] = NOW_TIME;//'开始时间';
  1295. $data['end_time'] = '';//'结束时间';
  1296. $data['is_hot'] = 1;//'1热门; 0:非热门';
  1297. $data['is_new'] =1; //'1新的; 0:非新的,直播结束时把它标识为:0?'
  1298. $data['online_status'] = 1;//主播在线状态;1:在线(默认); 0:离开
  1299. //sort_init(初始排序权重) = (用户可提现印票:fanwe_user.ticket - fanwe_user.refund_ticket) * 保留印票权重+ 直播/回看[回看是:0; 直播:9000000000 直播,需要排在最上面 ]+ fanwe_user.user_level * 等级权重+ fanwe_user.fans_count * 当前有的关注数权重
  1300. $sort_init = (intval($user['ticket']) - intval($user['refund_ticket'])) * floatval($m_config['ticke_weight']);
  1301. $sort_init += intval($user['user_level']) * floatval($m_config['level_weight']);
  1302. $sort_init += intval($user['fans_count']) * floatval($m_config['focus_weight']);
  1303. $data['sort_init'] = 200000000 + $sort_init;
  1304. $data['sort_num'] = $data['sort_init'];
  1305. // 1、创建视频时检查表是否存在,如不存在创建礼物表,表命名格式 fanwe_ video_ prop_201611、格式同fanwe_ video_ prop相同
  1306. // 2、将礼物表名称写入fanwe_video 中,需新建字段
  1307. // 3、记录礼物发送时候读取fanwe_video 的礼物表名,写入对应的礼物表
  1308. // 4、修改所有读取礼物表的地方,匹配数据
  1309. $data['prop_table'] = createPropTable();
  1310. //直播分类
  1311. $data['classified_id'] = $video_classified;
  1312. if((defined('PUBLIC_PAY')&&PUBLIC_PAY==1)&&intval($m_config['switch_public_pay'])==1&&intval($m_config['public_pay'])>0) {
  1313. $data['is_live_pay'] = 1;
  1314. $data['live_pay_type'] = 1;
  1315. $data['public_screen'] = 1;
  1316. $data['live_fee'] = intval($m_config['public_pay']);
  1317. $data['live_pay_time']=intval(NOW_TIME);
  1318. }
  1319. $GLOBALS['db']->autoExecute(DB_PREFIX."video", $data,'INSERT');
  1320. //$video_id = $GLOBALS['db']->insert_id();
  1321. if($GLOBALS['db']->affected_rows()){
  1322. $return['status'] =1;
  1323. $return['error'] ='';
  1324. $return['room_id'] = $video_id;
  1325. $return['video_type'] = intval($data['video_type']);
  1326. sync_video_to_redis($video_id,'*',false);
  1327. }else{
  1328. $return['status'] =0;
  1329. $return['error'] ='创建房间失败!';
  1330. }
  1331. }else{
  1332. if(intval($user['is_ban']&&intval($user['ban_type']==0))){
  1333. $return['status'] =0;
  1334. $return['error'] ='请求房间id失败,您被禁播,请联系客服处理。';
  1335. }elseif(intval($user['is_ban']&&intval($user['ban_type']==1))){
  1336. $return['status'] =0;
  1337. $return['error'] ='请求房间id失败,当前IP已被封停,请联系客服处理。';
  1338. }elseif(intval($user['is_ban']&&intval($user['ban_type']==2))){
  1339. $return['status'] =0;
  1340. $return['error'] ='请求房间id失败,当前设备已被禁用,请联系客服处理。';
  1341. }
  1342. else{
  1343. $return['status'] =0;
  1344. $return['error'] ='由于您的违规操作,您被封号暂时不能直播,封号时间截止到:'.to_date(intval($user['ban_time']),'Y-m-d H:i:s').'。';
  1345. }
  1346. }
  1347. }
  1348. if($m_config['must_authentication']==1){
  1349. if($is_authentication!=2){
  1350. $return['room_id'] = 0;
  1351. }
  1352. }
  1353. //-------------------------------------
  1354. //sdk_type 0:使用腾讯SDK、1:使用金山SDK
  1355. //映射关系类型 腾讯云直播, 金山云,星域,方维云 ,阿里云
  1356. //video_type 1 2 3 4 5
  1357. //sdk_type 0 1 - - -
  1358. $return['sdk_type'] = get_sdk_info($m_config['video_type']);
  1359. ajax_return($return);
  1360. }
  1361. /**
  1362. * 检查直播状态
  1363. * room_id:房间号id
  1364. */
  1365. public function check_status(){
  1366. $root = array();
  1367. //$root['sql'] = $sql;
  1368. if(!$GLOBALS['user_info']){
  1369. $root['error'] = "用户未登陆,请先登陆.";
  1370. $root['status'] = 0;
  1371. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1372. }else{
  1373. $room_id = intval($_REQUEST['room_id']);//房间号id
  1374. $user_id = intval($GLOBALS['user_info']['id']);//用户ID
  1375. $private_key = strim($_REQUEST['private_key']);//私密直播key
  1376. if ($private_key != ''){
  1377. $sql = "select v.id,v.city,v.live_in,v.user_id,v.group_id,u.nick_name,u.head_image,v.video_type from ".DB_PREFIX."video v left join ".DB_PREFIX."user u on u.id = v.user_id where v.room_type = 1 and v.private_key='".$private_key."'";
  1378. $video = $GLOBALS['db']->getRow($sql);
  1379. $room_id = intval($video['id']);
  1380. /*
  1381. $sql = "select id from ".DB_PREFIX."video_private where status = 0 and user_id = ".$user_id. " and video_id =".$room_id;
  1382. $video_private = $GLOBALS['db']->getRow($sql);
  1383. if ($video_private){
  1384. $root['error'] = "您已经被踢出,不能再加入";
  1385. $root['status'] = 0;
  1386. ajax_return($root);
  1387. }
  1388. */
  1389. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoPrivateRedisService.php');
  1390. $video_private_redis = new VideoPrivateRedisService();
  1391. if ($video_private_redis->check_user_drop($room_id, $user_id)){
  1392. $root['error'] = "您已经被踢出,不能再加入";
  1393. $root['status'] = 0;
  1394. ajax_return($root);
  1395. }
  1396. }else{
  1397. $sql = "select v.city,v.live_in,v.user_id,v.group_id,u.nick_name,u.head_image,v.live_image,v.video_type from ".DB_PREFIX."video v left join ".DB_PREFIX."user u on u.id = v.user_id where v.id='".$room_id."'";
  1398. $video = $GLOBALS['db']->getRow($sql);
  1399. if (!$video){
  1400. $sql = "select v.city,v.live_in,v.user_id,v.group_id as group_id,u.nick_name,u.head_image,v.live_image,v.video_type from ".DB_PREFIX."video_history v left join ".DB_PREFIX."user u on u.id = v.user_id where v.id='".$room_id."'";
  1401. $video = $GLOBALS['db']->getRow($sql);
  1402. }
  1403. }
  1404. if ($video){
  1405. $video['nick_name'] = emoji_decode($video['nick_name']);
  1406. $m_config = load_auto_cache("m_config");//手机端配置
  1407. if ($video['live_in'] == 1){
  1408. $root['room_id'] = $room_id;
  1409. $root['live_in'] = 1;//正在直播
  1410. $root['user_id'] = $video['user_id'];
  1411. $root['group_id'] = $video['group_id'];
  1412. $root['video_type'] =$video['video_type'];
  1413. if($video['live_image']==''){
  1414. $root['live_image'] = get_spec_image($video['head_image']);
  1415. $root['head_image'] = get_spec_image($video['head_image']);
  1416. }else{
  1417. $root['live_image'] = get_spec_image($video['live_image']);
  1418. $root['head_image'] = get_spec_image($video['head_image'],150,150);
  1419. }
  1420. $root['content'] = $video['nick_name']."(".$m_config['account_name'].$video['user_id'].") 正在".$video['city']."直播";
  1421. }else{
  1422. $root['room_id'] = $room_id;
  1423. $root['live_in'] = 0;//直播结束
  1424. $root['user_id'] = $video['user_id'];
  1425. $root['group_id'] = $video['group_id'];
  1426. $root['content'] = $video['nick_name']."(".$m_config['account_name'].$video['user_id'].") 已经直播结束,进入主页查看更多回放?";
  1427. }
  1428. if (defined('OPEN_EDU_MODULE') && OPEN_EDU_MODULE == 1) {
  1429. $root['is_verify'] = $GLOBALS['db']->getOne("select is_verify from " . DB_PREFIX . "edu_video_info where video_id= " . $room_id);
  1430. }
  1431. $root['error'] = "";
  1432. $root['status'] = 1;
  1433. }else{
  1434. if ($private_key != ''){
  1435. $root['error'] = "无效的直播房间或直播已结束";
  1436. $root['status'] = 0;
  1437. }else{
  1438. $root['error'] = "无效的直播房间".$room_id;
  1439. $root['status'] = 0;
  1440. }
  1441. }
  1442. }
  1443. ajax_return($root);
  1444. }
  1445. /**
  1446. * 推送通知,私聊用户
  1447. */
  1448. public function private_push_user(){
  1449. if(!$GLOBALS['user_info']){
  1450. $return['error'] = "用户未登陆,请先登陆.";
  1451. $return['status'] =0;
  1452. $return['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1453. }else{
  1454. $user_id = intval($GLOBALS['user_info']['id']);
  1455. $video_id = intval($_REQUEST['room_id']);
  1456. $user_ids = strim($_REQUEST['user_ids']);//字符串类型的私聊好友id 23,123,3455 以英文逗号分割的字符串
  1457. //主播自己或管理员,可以:邀请人员
  1458. $sql = "select id,city,user_id from ".DB_PREFIX."video where room_type = 1 and live_in = 1 and id =".$video_id;
  1459. $video = $GLOBALS['db']->getRow($sql);
  1460. if ($video && $video['user_id'] != $user_id){
  1461. //判断是否管理员
  1462. $sql = "select id from ".DB_PREFIX."user_admin where podcast_id = ".$video['user_id']." and user_id =".$user_id;
  1463. if (intval($GLOBALS['db']->getRow($sql)) == 0){
  1464. //非管理员
  1465. unset($video);
  1466. }
  1467. }
  1468. if ($video){
  1469. //将选中的:私聊 数据添加到数据库中
  1470. $user_list = explode(',',$user_ids);
  1471. if (count($user_list) > 500){
  1472. $return['status'] =0;
  1473. $return['error'] ='一次添加,不能大于500个用户';
  1474. ajax_return($return);
  1475. }else if (count($user_list) > 0 && count($user_list) <= 500){
  1476. foreach ( $user_list as $k => $v )
  1477. {
  1478. /*
  1479. $sql = "select id from ".DB_PREFIX."video_private where user_id = ".$v. " and video_id =".$video_id;
  1480. $video_private_id = intval($GLOBALS['db']->getOne($sql));
  1481. if ($video_private_id == 0){
  1482. $video_private =array();
  1483. $video_private['video_id'] = $video_id;
  1484. $video_private['user_id'] = $v;
  1485. $video_private['status'] = 1;
  1486. //$video_private['ErrorInfo'] = strim($_REQUEST['user_ids']);
  1487. $GLOBALS['db']->autoExecute(DB_PREFIX."video_private", $video_private,'INSERT');
  1488. }else{
  1489. $sql = "update ".DB_PREFIX."video_private set status = 1 where id = ".$video_private_id;
  1490. $GLOBALS['db']->query($sql);
  1491. }
  1492. */
  1493. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoPrivateRedisService.php');
  1494. $video_private_redis = new VideoPrivateRedisService();
  1495. $video_private_redis->push_user($video_id, $v);
  1496. }
  1497. fanwe_require(APP_ROOT_PATH.'system/schedule/android_list_schedule.php');
  1498. fanwe_require(APP_ROOT_PATH.'system/schedule/ios_list_schedule.php');
  1499. //推送通知:
  1500. //推送消息文本
  1501. $nick_name = emoji_decode($GLOBALS['user_info']['nick_name']);
  1502. $content ="你的好友:".$nick_name."正在".$video['city']."直播,邀请你一起";
  1503. $room_id = $video_id;
  1504. $code_sql = "select u.apns_code,u.device_type from ".DB_PREFIX."user u where u.device_type in (1,2) and u.id in (".$user_ids.")";
  1505. $code_list = $GLOBALS['db']->getAll($code_sql);
  1506. //得到机器码列表
  1507. $apns_app_code_list = array();
  1508. $apns_ios_code_list = array();
  1509. $j=$i=0;
  1510. foreach($code_list as $kk=>$vv){
  1511. //获取android机器码
  1512. if($vv['device_type']==1){
  1513. $apns_app_code_list[$i] = $vv['apns_code'];
  1514. $i++;
  1515. }
  1516. //获取IOS机器码
  1517. if($vv['device_type']==2){
  1518. $apns_ios_code_list[$j] = $vv['apns_code'];
  1519. $j++;
  1520. }
  1521. }
  1522. //安卓推送信息
  1523. if(count($apns_app_code_list)>0){
  1524. $AndroidList = new android_list_schedule();
  1525. $data = array(
  1526. 'dest' =>implode(",",$apns_app_code_list),
  1527. 'content' =>$content,
  1528. 'room_id'=>$room_id,
  1529. 'type'=>0,
  1530. );
  1531. $ret_android =$AndroidList->exec($data);
  1532. }
  1533. //ios 推送信息
  1534. if(count($apns_ios_code_list)>0){
  1535. $IosList = new ios_list_schedule();
  1536. $ios_data = array(
  1537. 'dest' =>implode(",",$apns_ios_code_list),
  1538. 'content' =>$content,
  1539. 'room_id'=>$room_id,
  1540. 'type'=>0,
  1541. );
  1542. $ret_ios = $IosList->exec($ios_data);
  1543. }
  1544. $return['status'] =1;
  1545. $return['error'] ='已发邀请通知';//.print_r($ret_android,1).print_r($ret_ios,1).$code_sql;
  1546. }
  1547. }else{
  1548. $return['status'] =0;
  1549. $return['error'] ='邀请通知失败!';
  1550. }
  1551. }
  1552. ajax_return($return);
  1553. }
  1554. /**
  1555. * 踢人私聊用户
  1556. */
  1557. public function private_drop_user(){
  1558. $return['status'] = 1;
  1559. $return['error'] ='操作完成';
  1560. if(!$GLOBALS['user_info']){
  1561. $return['error'] = "用户未登陆,请先登陆.";
  1562. $return['status'] =0;
  1563. $return['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1564. }else{
  1565. $user_id = intval($GLOBALS['user_info']['id']);
  1566. $video_id = intval($_REQUEST['room_id']);
  1567. $user_ids = strim($_REQUEST['user_ids']);//字符串类型的私聊好友id 23,123,3455 以英文逗号分割的字符串 只有私聊时才需要上传这个参数
  1568. $sql = "select id,user_id from ".DB_PREFIX."video where room_type = 1 and live_in = 1 and id =".$video_id;
  1569. $video = $GLOBALS['db']->getRow($sql);
  1570. //主播自己或管理员,可以:踢人
  1571. if ($video && $video['user_id'] != $user_id){
  1572. //判断是否管理员
  1573. $sql = "select id from ".DB_PREFIX."user_admin where podcast_id = ".$video['user_id']." and user_id =".$user_id;
  1574. if (intval($GLOBALS['db']->getRow($sql)) == 0){
  1575. //非管理员
  1576. unset($video);
  1577. }
  1578. }
  1579. if ($video){
  1580. //将选中的:私聊 数据添加到数据库中
  1581. $user_ids = explode(',',$user_ids);
  1582. if (count($user_ids) > 0){
  1583. $ext = array();
  1584. $ext['type'] = 17;
  1585. $ext['room_id'] = $video_id;
  1586. $ext['desc'] = '您被踢出房间';
  1587. #构造高级接口所需参数
  1588. $msg_content = array();
  1589. //创建array 所需元素
  1590. $msg_content_elem = array(
  1591. 'MsgType' => 'TIMCustomElem', //自定义类型
  1592. 'MsgContent' => array(
  1593. 'Data' => json_encode($ext),
  1594. 'Desc' => '',
  1595. // 'Ext' => $ext,
  1596. // 'Sound' => '',
  1597. )
  1598. );
  1599. //将创建的元素$msg_content_elem, 加入array $msg_content
  1600. array_push($msg_content, $msg_content_elem);
  1601. fanwe_require(APP_ROOT_PATH.'system/tim/TimApi.php');
  1602. $api = createTimAPI();
  1603. foreach ( $user_ids as $k => $v )
  1604. {
  1605. $ret = $api->openim_send_msg2((string)$user_id, $v, $msg_content);
  1606. /*
  1607. $video_private =array();
  1608. $video_private['ActionStatus'] = $ret['ActionStatus'];
  1609. $video_private['ErrorCode'] = $ret['ErrorCode'];
  1610. $video_private['ErrorInfo'] = $ret['ErrorInfo'];
  1611. $video_private['status'] = 0;
  1612. $GLOBALS['db']->autoExecute(DB_PREFIX."video_private", $video_private,'UPDATE'," user_id = ".$v. " and video_id =".$video_id);
  1613. */
  1614. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoPrivateRedisService.php');
  1615. $video_private_redis = new VideoPrivateRedisService();
  1616. $video_private_redis->drop_user($video_id, $v);
  1617. if ($ret['ActionStatus'] != 'OK'){
  1618. $return['status'] =0;
  1619. $return['error'] ='踢人失败,'.$ret['ErrorInfo'].";".$ret['ErrorCode'];
  1620. }
  1621. }
  1622. }
  1623. }else{
  1624. $return['status'] =0;
  1625. $return['error'] ='踢人失败!';
  1626. }
  1627. }
  1628. ajax_return($return);
  1629. }
  1630. /**
  1631. * 已经在私密房间中的用户列表,主要用过:踢出聊天室
  1632. */
  1633. public function private_room_friends(){
  1634. $root = array();
  1635. $root['status'] = 1;
  1636. //$GLOBALS['user_info']['id'] = 278;
  1637. if(!$GLOBALS['user_info']){
  1638. $root['error'] = "用户未登陆,请先登陆.";
  1639. $root['status'] = 0;
  1640. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1641. }else{
  1642. $user_id = intval($GLOBALS['user_info']['id']);//id
  1643. $video_id = intval($_REQUEST['room_id']);
  1644. $page = intval($_REQUEST['p']);//取第几页数据
  1645. if($page==0){
  1646. $page = 1;
  1647. }
  1648. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoRedisService.php');
  1649. $video_redis = new VideoRedisService();
  1650. $video_data = $video_redis->getRow_db($video_id,array('group_id','user_id'));
  1651. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoViewerRedisService.php');
  1652. $video_viewer_redis = new VideoViewerRedisService();
  1653. $group_id = $video_data['group_id'];//聊天群id
  1654. if($group_id){
  1655. $root = $video_viewer_redis->get_viewer_list($group_id,$page);
  1656. if($root['list']){
  1657. $list = $root['list'];
  1658. $sql = "select user_id from ".DB_PREFIX."user_admin where podcast_id = ".$video_data['user_id'];
  1659. $user_admin_list = $GLOBALS['db']->getAll($sql,true,true);
  1660. $user_admin_list = array_column($user_admin_list,'user_id');
  1661. foreach($list as $k=>$v){
  1662. if(in_array($v['user_id'],$user_admin_list) && $video_data['user_id']!=$user_id){
  1663. unset($list[$k]);
  1664. }
  1665. }
  1666. $list = array_values($list);
  1667. $root['list'] = $list;
  1668. }
  1669. }else{
  1670. $root = array(
  1671. 'list'=>array(),
  1672. 'has_next'=>0,
  1673. 'page'=>1,
  1674. 'status'=>1
  1675. );
  1676. }
  1677. /*
  1678. $page_size=20;
  1679. $limit = (($page-1)*$page_size).",".$page_size;
  1680. //$sql = "select group_id from ".DB_PREFIX."video where room_type = 1 and live_in = 0 and id =".$video_id;
  1681. $sql = "select group_id from ".DB_PREFIX."video where id =".$video_id;
  1682. $video = $GLOBALS['db']->getRow($sql);
  1683. $group_id = $video['group_id'];
  1684. $root['group_id'] = $group_id;
  1685. $root['sql1'] = $sql;
  1686. $sql = "SELECT v.user_id,u.nick_name,u.signature,u.sex,u.head_image,u.user_level FROM ".DB_PREFIX."video_viewer v LEFT JOIN ".DB_PREFIX."user u on u.id = v.user_id WHERE v.end_time = 0 AND v.group_id = '".$group_id."' limit ".$limit;
  1687. $root['sql2'] = $sql;
  1688. $root['sql'] = $sql;
  1689. // fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/UserFollwRedisService.php');
  1690. // $user_redis = new UserFollwRedisService($user_id);
  1691. // $root = $user_redis->get_private_user($page,$page_size);
  1692. $list = $GLOBALS['db']->getAll($sql);
  1693. $root['list'] = $list;
  1694. if($page==0){
  1695. $root['has_next'] = 0;
  1696. }else{
  1697. if (count($list) == $page_size)
  1698. $root['has_next'] = 1;
  1699. else
  1700. $root['has_next'] = 0;
  1701. }
  1702. $root['page'] = $page;//
  1703. */
  1704. if(!empty($root['list']))
  1705. {
  1706. for($i=0;$i<count($root['list']);$i++)
  1707. {
  1708. $root['list'][$i]['nick_name'] = emoji_decode($root['list'][$i]['nick_name']);
  1709. }
  1710. }
  1711. }
  1712. ajax_return($root);
  1713. }
  1714. /**
  1715. * 点赞数
  1716. */
  1717. public function like()
  1718. {
  1719. $root = array();
  1720. if(!$GLOBALS['user_info']){
  1721. $root['error'] = "用户未登陆,请先登陆.";// es_session::id();
  1722. $root['status'] = 0;
  1723. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1724. }else{
  1725. $user_id = $GLOBALS['user_info']['id'];
  1726. $room_id = intval($_REQUEST['room_id']);
  1727. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoRedisService.php');
  1728. $video_redis = new VideoRedisService();
  1729. $video_redis->like($room_id,$user_id);
  1730. $root['status'] = 1;
  1731. }
  1732. ajax_return($root);
  1733. }
  1734. /**
  1735. * PC端全部直播接口
  1736. */
  1737. public function video_list(){
  1738. $root = array();
  1739. $page=intval($_REQUEST('p'));
  1740. $cate_id=intval($_REQUEST('cate_id'));
  1741. $jump_type=($_REQUEST('jump_type'));
  1742. $page_size = 20;//分页数量
  1743. if($page==0||$page==''){
  1744. $page = 1;
  1745. }
  1746. $param=array('page'=>$page,'page_size'=>$page_size,'cate_id'=>$cate_id);
  1747. $root['cate_top'] = load_auto_cache("cate_top");
  1748. $info = load_auto_cache("all_video",$param);
  1749. $root['list'] = $info['list'];
  1750. $root['status'] = 1;
  1751. $root['has_next'] = $info['has_next'];
  1752. $root['page'] = $info['page'];
  1753. $root['jump_type'] = $jump_type;
  1754. ajax_return($root);
  1755. }
  1756. /**
  1757. * PC端话题列表
  1758. */
  1759. public function search_video_cate(){
  1760. $root=array();
  1761. $page = intval($_REQUEST['p']);//取第几页数据
  1762. $title = strim($_REQUEST['title']);
  1763. if($page==0||$page==''){
  1764. $page = 1;
  1765. }
  1766. $page_size=50;
  1767. $limit = (($page-1)*$page_size).",".$page_size;
  1768. if ($title){
  1769. $sql = "select vc.id as cate_id,vc.title,vc.num from ".DB_PREFIX."video_cate as vc
  1770. where vc.is_effect = 1 and vc.title like '%".$title."%' order by vc.sort desc, vc.num desc limit ".$limit;
  1771. $rs_count = $GLOBALS['db']->getAll("select count(id) from ".DB_PREFIX."video_cate where vc.is_effect = 1 and vc.title like '%".$title."%'");
  1772. }else{
  1773. $rs_count = $GLOBALS['db']->getAll("select count(id) from ".DB_PREFIX."video_cate where vc.is_effect = 1");
  1774. $sql = "select vc.id as cate_id,vc.title,vc.num from ".DB_PREFIX."video_cate as vc
  1775. where vc.is_effect = 1 order by vc.sort desc, vc.num desc limit ".$limit;
  1776. }
  1777. //查询话题列表,修改成 从只读数据库中取,但不是高效做法;主并发时,可以加入阿里云的搜索服务
  1778. //https://www.aliyun.com/product/opensearch?spm=5176.8142029.388261.62.tgDxhe
  1779. $list = $GLOBALS['db']->getAll($sql,true,true);
  1780. foreach($list as $k=>$v){
  1781. $list[$k]['title'] ="#".$v['title']."#";
  1782. }
  1783. if($page==0){
  1784. $root['has_next'] = 0;
  1785. }else{
  1786. if ($rs_count >= $page*$page_size)
  1787. $root['has_next'] = 1;
  1788. else
  1789. $root['has_next'] = 0;
  1790. }
  1791. $root['page'] = $page;//
  1792. $root['list'] =$list;
  1793. $root['status'] =1;
  1794. ajax_return($root);
  1795. }
  1796. /**
  1797. * 我的关注
  1798. */
  1799. public function focus_video(){
  1800. $root=array();
  1801. $page = intval($_REQUEST['p']);//取第几页数据
  1802. $cateid=intval($_REQUEST['cate_id']);
  1803. if(!$GLOBALS['user_info']){
  1804. $root['error'] = "用户未登陆,请先登陆.";
  1805. $root['status'] = 0;
  1806. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1807. }else{
  1808. //关注
  1809. $user_id = intval($GLOBALS['user_info']['id']);//登录用户id
  1810. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/UserFollwRedisService.php');
  1811. $userfollw_redis = new UserFollwRedisService($user_id);
  1812. $user_list = $userfollw_redis->following();
  1813. //私密直播 video_private,私密直播结束后, 本表会清空
  1814. fanwe_require(APP_ROOT_PATH.'mapi/lib/redis/VideoPrivateRedisService.php');
  1815. $video_private_redis = new VideoPrivateRedisService();
  1816. $private_list = $video_private_redis->get_video_list($user_id);
  1817. /*
  1818. $sql = "select video_id from ".DB_PREFIX."video_private where status = 1 and user_id = ".$user_id;
  1819. $private_list = $GLOBALS['db']->getAll($sql,true,true);
  1820. */
  1821. $list = array();
  1822. if($page==0||$page==''){
  1823. $page=1;
  1824. }
  1825. $page_size=20;
  1826. $param=array('page'=>$page,'page_size'=>$page_size,'has_private'=>1,'cate_id'=>$cateid);
  1827. if(sizeof($private_list) || sizeof($user_list)){
  1828. $info = load_auto_cache("foucs_video",$param);
  1829. $list_all=$info['list'];
  1830. foreach($list_all as $k=>$v){
  1831. if (($v['room_type'] == 1 && in_array($v['room_id'], $private_list)) || ($v['room_type'] == 3 && in_array($v['user_id'], $user_list))) {
  1832. $list[] = $v;
  1833. }
  1834. }
  1835. }
  1836. $root['list'] = $list;
  1837. $root['cate_top'] = load_auto_cache("cate_top");
  1838. // $playback = load_auto_cache("playback_list",array('user_id'=>$user_id));
  1839. //
  1840. // $root['playback'] = $playback;
  1841. $root['status'] = 1;
  1842. $root['has_next'] = $info['has_next'];
  1843. $root['page'] = $info['page'];
  1844. }
  1845. ajax_return($root);
  1846. }
  1847. /**
  1848. * 主播调用列表
  1849. */
  1850. public function p_viewer(){
  1851. $root = array();
  1852. $room_id = strim($_REQUEST['room_id']);//聊天群id
  1853. $group_id = strim($_REQUEST['group_id']);//聊天群id
  1854. $page = intval($_REQUEST['p']);//取第几页数据
  1855. if($room_id){
  1856. $sql = "select is_live_pay from ".DB_PREFIX."video where id = ".$room_id;
  1857. $is_live_pay = $GLOBALS['db']->getOne($sql,true,true);
  1858. }else{
  1859. $root['error'] = "room_id不存在";
  1860. $root['status'] = 0;
  1861. ajax_return($root);
  1862. }
  1863. $root = load_auto_cache("video_viewer",array('group_id'=>$group_id,'page'=>$page));
  1864. if(intval($is_live_pay)){
  1865. $list = array();
  1866. $live_pay_log_list = array();
  1867. //分页
  1868. if (intval($_REQUEST['page_size'])) {
  1869. $page_size = intval($_REQUEST['page_size']);
  1870. } else {
  1871. $page_size = 100;//分页数量
  1872. }
  1873. if ($page == 0) {
  1874. $page = 1;
  1875. }
  1876. $limit = (($page - 1) * $page_size) . "," . $page_size;
  1877. $live_pay_log = $GLOBALS['db']->getAll("select from_user_id as user_id from ".DB_PREFIX."live_pay_log where video_id =".$room_id." limit".$limit);
  1878. foreach($live_pay_log as $v){
  1879. $live_pay_log_list[$v['user_id']] = $v['user_id'];
  1880. }
  1881. if($live_pay_log_list){
  1882. foreach($root['list'] as $k=>$v){
  1883. if($live_pay_log_list[$v['user_id']]==$v['user_id']){
  1884. $list[$k] = $v;
  1885. }
  1886. }
  1887. $rs_count = intval(count($list));
  1888. if ($page == 0) {
  1889. $list['page'] = 0;
  1890. $list['has_next'] = 0;
  1891. }else{
  1892. $has_next = ($rs_count > $page * $page_size) ? '1' : '0';
  1893. $list['page'] = $page;
  1894. $list['has_next'] = $has_next;
  1895. }
  1896. $list['status'] = 1;
  1897. }else{
  1898. $list = array(
  1899. 'list'=>array(),
  1900. 'has_next'=>0,
  1901. 'page'=>1,
  1902. 'status'=>1
  1903. );
  1904. }
  1905. $root['list'] = $list;
  1906. $root['watch_number'] = intval($rs_count);
  1907. }
  1908. ajax_return($root);
  1909. }
  1910. /**
  1911. * 金山连麦 鉴权 ks_auth()
  1912. * https://github.com/ksvc/KSYRTCLive_Android/wiki/auth
  1913. *
  1914. * stringToSign = "GET\n" + str(expiretime) + "\n"
  1915. * strResource = "nonce=" + nonce + "&uid=" + uid + "&uniqname=" + UNIQNAME
  1916. * stringToSign = stringToSign + strResource
  1917. *
  1918. * String authString = "accesskey=D8uDWZ88ZK8/eZHmRm&expire=1470212584&nonce=wybR8MEyhOpALCGh7xg17R5ejDrtk0&public=0&uniqname=apptest&signature=uFByPHHUKbszXR2t5NAuoUgTw%3D&uid=1000";
  1919. */
  1920. public function ks_auth(){
  1921. $root = array();
  1922. $user_id = intval($GLOBALS['user_info']['id']);
  1923. //if($user_id == 0){
  1924. // $user_id = 'test111';
  1925. //}
  1926. if($user_id == 0){
  1927. $root['error'] = "用户未登陆,请先登陆.".$user_id;
  1928. $root['status'] = 0;
  1929. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  1930. }else{
  1931. $uid = $user_id;
  1932. //开发者ak/sk
  1933. $accesskey = '8+n2Kl2Ta8ofvMM5YHjT';
  1934. $secretkey = 'MJh86NtGhAa+KNjOonq5E0xVDym0ZuorqclugV4z';
  1935. $uniqname = 'fanwe';
  1936. $nonce = rand(1, 100000);
  1937. //用于签名的参数,字典序排列
  1938. //用于签名的参数,字典序排列
  1939. $arrrsrc = array(
  1940. 'nonce' => $nonce,
  1941. 'uid' => $uid,
  1942. 'uniqname' => $uniqname,
  1943. );
  1944. $strrsrc = http_build_query($arrrsrc);
  1945. //$strrsrc = "nonce=".urlencode($nonce)."&uid=".urlencode($uid)."&uniqname=".urlencode($uniqname);
  1946. //过期时间
  1947. $expire = get_gmtime() + 28800 + 600;
  1948. //拼接用于计算签名sign的源字符串
  1949. $strtosign = "GET\n$expire\n$strrsrc";
  1950. //计算签名
  1951. $sign = hash_hmac('sha1', $strtosign, $secretkey, true);
  1952. $signature = base64_encode($sign);
  1953. $params = array(
  1954. 'nonce' => $nonce,
  1955. 'uid' => $uid,
  1956. 'uniqname' => $uniqname,
  1957. 'accesskey' => $accesskey,
  1958. 'expire' => $expire,
  1959. 'signature' => $signature,
  1960. );
  1961. $auth_string = http_build_query($params);
  1962. //$auth_string = "accesskey=".urlencode($accesskey)."&expire=".$expire."&signature=".urlencode($signature)."&".$strrsrc;
  1963. $root['uniqname'] = $uniqname;
  1964. $root['uid'] = $uid;
  1965. $root['auth_string'] = $auth_string;
  1966. $root['status'] = 1;
  1967. /*
  1968. $root['strtosign'] = $strtosign;
  1969. $root['signature'] = $signature;
  1970. $root['nonce'] = $nonce;
  1971. $root['expire'] = $expire;
  1972. $root['accesskey'] = $accesskey;
  1973. $root['secretkey'] = $secretkey;
  1974. */
  1975. }
  1976. ajax_return($root);
  1977. }
  1978. /**
  1979. * 强制升级不升级无法查看直播
  1980. * @param $m_config
  1981. * @return array
  1982. */
  1983. public function compel_upgrade($m_config)
  1984. {
  1985. $root = array('status'=>1,'error'=>'');
  1986. $dev_type = strim($_REQUEST['sdk_type']);
  1987. $version = strim($_REQUEST['sdk_version']);//升级版本号yyyymmddnn: 2017031502
  1988. if ($dev_type == 'android'){
  1989. $root['serverVersion'] = $m_config['android_version'];//android版本号
  1990. //print_r($m_config);
  1991. if ($version < $root['serverVersion'] && $m_config['android_filename'] != ''){
  1992. $root['status'] = 0;
  1993. $root['filename'] = $m_config['android_filename'];//android下载包名
  1994. $root['android_upgrade'] = $m_config['android_upgrade'];//android版本升级内容
  1995. $root['forced_upgrade'] = 1;//强制升级
  1996. $root['hasfile'] = 1;
  1997. $root['has_upgrade'] = 1;//1:可升级;0:不可升级
  1998. $root['error'] = $m_config['forced_upgrade_tips'];//强制升级提醒
  1999. }else{
  2000. $root['hasfile'] = 0;
  2001. $root['has_upgrade'] = 0;//1:可升级;0:不可升级
  2002. }
  2003. }else if ($dev_type == 'ios'){
  2004. $root['serverVersion'] = $m_config['ios_version'];//IOS版本号
  2005. if ($version < $root['serverVersion']&&$m_config['ios_down_url']!=''){
  2006. $root['status'] = 0;
  2007. $root['ios_down_url'] = $m_config['ios_down_url'];//ios下载地址
  2008. $root['ios_upgrade'] = $m_config['ios_upgrade'];//ios版本升级内容
  2009. $root['has_upgrade'] = 1;//1:可升级;0:不可升级
  2010. $root['forced_upgrade'] = intval($m_config['ios_forced_upgrade']);//0:非强制升级;1:强制升级
  2011. $root['error'] = $m_config['forced_upgrade_tips'];//强制升级提醒
  2012. }else{
  2013. $root['has_upgrade'] = 0;//1:可升级;0:不可升级
  2014. }
  2015. }else{
  2016. $root['hasfile'] = 0;
  2017. $root['has_upgrade'] = 0;//1:可升级;0:不可升级
  2018. }
  2019. return $root;
  2020. }
  2021. /**
  2022. * 声网授权
  2023. * channe_name: 频道名称,默认是:房间号
  2024. * @return multitype:string number
  2025. */
  2026. public function agora_auth(){
  2027. $root = array();
  2028. $user_id = intval($GLOBALS['user_info']['id']);
  2029. if($user_id == 0){
  2030. $root['error'] = "用户未登陆,请先登陆.".$user_id;
  2031. $root['status'] = 0;
  2032. $root['user_login_status'] = 0;//有这个参数: user_login_status = 0 时,表示服务端未登陆、要求登陆,操作
  2033. }else{
  2034. fanwe_require(APP_ROOT_PATH.'mapi/lib/core/DynamicKey5.php');
  2035. $m_config = load_auto_cache("m_config");//初始化手机端配置
  2036. $channe_name = strim($_REQUEST['channe_name']);//频道名称,默认是:房间号
  2037. $appID = strim($m_config['agora_app_id']);
  2038. $appCertificate = strim($m_config['agora_app_certificate']);
  2039. $ts = get_gmtime();//Dynamic Key 生成时的时间戳,自1970.1.1开始到当前时间的秒数。授权该 Dynamic Key 在生成后的 5 分钟内可以访问 Agora 服务,如果 5 分钟内没有访问,则该 Dynamic Key 无法再使用。
  2040. $expiredTs = 0;//用户使用 Agora 服务终止的时间戳,在此时间之后,将不能继续使用 Agora 服务(比如进行的通话会被强制终止);如果对终止时间没有限制,设置为 0。设置服务到期时间并不意味着Dynamic Key 失效,而仅仅用于限制用户使用当前服务的时间。
  2041. $randomInt = rand(1, 1000000);//随机数
  2042. if (!empty($appCertificate)){
  2043. //setClientRole
  2044. $role_key = generateInChannelPermissionKey($appID, $appCertificate, $channe_name, $ts, $randomInt, $user_id, $expiredTs, "0");
  2045. $channe_key = generateMediaChannelKey($appID, $appCertificate, $channe_name, $ts, $randomInt, $user_id, $expiredTs);
  2046. //setClientRole
  2047. $root['role_key'] = $role_key;
  2048. //joinChannel
  2049. $root['channe_key'] = $channe_key;
  2050. }else{
  2051. $root['role_key'] = '';
  2052. $root['channe_key'] = '';
  2053. }
  2054. $root['agora_anchor_resolution'] = intval($m_config['agora_anchor_resolution']);//大主播分辨率 (0,1,2,3)240*424,360*640,480*848,720*1280
  2055. $root['agora_audience_resolution'] = intval($m_config['agora_anchor_resolution']);//小主播分辨率 (0,1,2,3)180*320,240*424,360*640,480*848
  2056. }
  2057. return $root;
  2058. }
  2059. }