VideoViewerRedisService.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  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 VideoViewerRedisService extends BaseRedisService
  10. {
  11. //var $video_viewer_level_db;//:video_id zset 房间观众列表,user_id:会员级别
  12. /**
  13. *
  14. +----------------------------------------------------------
  15. * 架构函数
  16. +----------------------------------------------------------
  17. * @access public
  18. +----------------------------------------------------------
  19. */
  20. public function __construct()
  21. {
  22. parent::__construct();
  23. //注:本redis只产生了一个:video_viewer_level_db 数据;观众列表
  24. }
  25. /*
  26. * 新会员进入
  27. */
  28. public function member_join($post){
  29. $GroupId = $post['GroupId'];
  30. $video_id = $this->redis->hGet($this->video_group_db,$GroupId);
  31. if(!$video_id){
  32. return false;
  33. }
  34. $video = $this->redis->hMGet($this->video_db.$video_id,array('room_type','virtual_number','robot_num','watch_number','user_id'));
  35. //前台展示的观众列表数量
  36. $now_num = $video['robot_num'] + $video['watch_number'];
  37. //新入群成员列表
  38. foreach ( $post['NewMemberList'] as $k => $v ){
  39. $user_id = $v['Member_Account'];
  40. $user_db = $this->redis->hMGet($this->user_db.$user_id,array('user_level','is_robot','is_authentication'));
  41. $sort_num = $user_db['user_level']*$this->gz_level_weight;
  42. if($user_db['is_robot']==0){
  43. $sort_num+= $this->gz_real_weight;
  44. }
  45. if($user_db['is_authentication']==2){
  46. $sort_num+= $this->gz_rz_weight;
  47. }
  48. if ($sort_num < 1) $sort_num = 1;
  49. //过滤重复加入的
  50. if ($this->redis->zAdd($this->video_viewer_level_db.$video_id,$sort_num,$user_id) > 0){
  51. /*
  52. //实际观众看人数+1
  53. $watch_number = $this->redis->hIncrBy($this->video_db.$video_id,'watch_number',1);
  54. //修复
  55. if($video['room_type'] == 1){
  56. $total_num = $this->redis->zCount($this->video_viewer_level_db.$video_id, '-inf', '+inf');
  57. if ($watch_number != $total_num){
  58. $this->redis->hSet($this->video_db.$video_id,'watch_number',$total_num);
  59. }
  60. }
  61. */
  62. $now_num += 1;
  63. $virtual_number = 0;
  64. //非私密直播,1个真实用户进来,带一些机器人;且只有观众列表数大于6时,才加
  65. if ($video['room_type'] != 1 && $now_num > 6&&intval($video['virtual_number'])>0){
  66. $start_num = intval($video['virtual_number']/2)?intval($video['virtual_number']/2):2;
  67. $virtual_number = rand($start_num,$video['virtual_number']);
  68. //添加虚拟人数
  69. $this->redis->hIncrBy($this->video_db.$video_id,'virtual_watch_number',$virtual_number);
  70. }
  71. //私密直播间主播进入不添加人数
  72. if($video['room_type'] != 1||($video['room_type'] == 1&&$user_id!=$video['user_id'])){
  73. //一个实际人数+虚拟人数
  74. $virtual_number += 1;
  75. }
  76. $this->redis->hIncrBy($this->video_db.$video_id,'max_watch_number',$virtual_number);
  77. }
  78. //实际观众数统计:累计观众列表和; [score 为负数是:机器人; 正数是:真实观众]
  79. if($video['room_type'] == 1 || $video['room_type'] == 3){
  80. $watch_number = $this->redis->zCount($this->video_viewer_level_db.$video_id, '1', '+inf');
  81. $this->redis->hSet($this->video_db.$video_id,'watch_number',$watch_number);
  82. }
  83. }
  84. return true;
  85. }
  86. /*
  87. * 子房间观众加入
  88. */
  89. public function child_room_member_join($post, $video_id)
  90. {
  91. $video = $this->redis->hMGet($this->video_db . $video_id,
  92. array('room_type', 'virtual_number', 'robot_num', 'watch_number'));
  93. //前台展示的观众列表数量
  94. $now_num = $video['robot_num'] + $video['watch_number'];
  95. //新入群成员列表
  96. foreach ($post['NewMemberList'] as $k => $v) {
  97. $user_id = $v['Member_Account'];
  98. $user_db = $this->redis->hMGet($this->user_db . $user_id,
  99. array('user_level', 'is_robot', 'is_authentication'));
  100. $sort_num = $user_db['user_level'] * $this->gz_level_weight;
  101. if ($user_db['is_robot'] == 0) {
  102. $sort_num += $this->gz_real_weight;
  103. }
  104. if ($user_db['is_authentication'] == 2) {
  105. $sort_num += $this->gz_rz_weight;
  106. }
  107. if ($sort_num < 1) {
  108. $sort_num = 1;
  109. }
  110. //过滤重复加入的
  111. if ($this->redis->zAdd($this->video_viewer_level_db . $video_id, $sort_num, $user_id) > 0) {
  112. $now_num += 1;
  113. $virtual_number = 0;
  114. //非私密直播,1个真实用户进来,带一些机器人;且只有观众列表数大于6时,才加
  115. if ($video['room_type'] != 1 && $now_num > 6 && intval($video['virtual_number']) > 0) {
  116. $start_num = intval($video['virtual_number'] / 2) ? intval($video['virtual_number'] / 2) : 2;
  117. $virtual_number = rand($start_num, $video['virtual_number']);
  118. //添加虚拟人数
  119. $this->redis->hIncrBy($this->video_db . $video_id, 'virtual_watch_number', $virtual_number);
  120. }
  121. //一个实际人数+虚拟人数
  122. $virtual_number += 1;
  123. $this->redis->hIncrBy($this->video_db . $video_id, 'max_watch_number', $virtual_number);
  124. }
  125. //实际观众数统计:累计观众列表和; [score 为负数是:机器人; 正数是:真实观众]
  126. if ($video['room_type'] == 1 || $video['room_type'] == 3) {
  127. $watch_number = $this->redis->zCount($this->video_viewer_level_db . $video_id, '1', '+inf');
  128. $this->redis->hSet($this->video_db . $video_id, 'watch_number', $watch_number);
  129. }
  130. }
  131. }
  132. /*
  133. * 会员离开
  134. */
  135. public function member_exit($post){
  136. $GroupId = $post['GroupId'];
  137. $video_id = $this->redis->hGet($this->video_group_db,$GroupId);
  138. if(!$video_id){
  139. return false;
  140. }
  141. $video = $this->redis->hMGet($this->video_db.$video_id,array('room_type','virtual_number','virtual_watch_number',));
  142. if(intval($video['virtual_number'])>0){
  143. $number = intval($video['virtual_number']/2)?intval($video['virtual_number']/2):2;
  144. }else{
  145. $number = 0;
  146. }
  147. $virtual_watch_number = intval($video['virtual_watch_number']);
  148. //退出群的成员列表
  149. foreach ( $post['ExitMemberList'] as $k => $v ){
  150. $user_id = $v['Member_Account'];
  151. //用户移除成功
  152. if ($this->redis->zRem($this->video_viewer_level_db.$video_id,$user_id) > 0){
  153. /*
  154. //实际观众看人数-1
  155. $watch_number = $this->redis->hIncrBy($this->video_db.$video_id,'watch_number',-1);
  156. //确保,实际观看人数,不为会负数 chenfq by add 20161025
  157. if ($watch_number < 0){
  158. $watch_number = 0;
  159. //zcount fanwe0000008:video_viewer_level:207 -inf +inf
  160. //
  161. $total_num = $this->redis->zCount($this->video_viewer_level_db.$video_id, '-inf', '+inf');
  162. //$robot_num = $this->redis->zCount($this->user_robot_db.$video_id, '-inf', '+inf');
  163. $robot_num = intval($this->redis->hGet($this->video_db.$video_id,'robot_num'));
  164. $watch_number = $total_num - $robot_num;
  165. if ($watch_number < 0){
  166. $watch_number = 0;
  167. }
  168. $this->redis->hSet($this->video_db.$video_id,'watch_number',$watch_number);
  169. }
  170. */
  171. if ($video['room_type'] != 1 && $virtual_watch_number > 0){
  172. //随机减少一些虚拟人数
  173. $virtual_number = rand(1,$number);
  174. if ($virtual_number > $virtual_watch_number){
  175. $virtual_number = $virtual_watch_number;
  176. }
  177. $this->redis->hIncrBy($this->video_db.$video_id,'virtual_watch_number',-$virtual_number);
  178. $virtual_watch_number = intval($this->redis->hGet($this->video_db.$video_id,'virtual_watch_number'));
  179. if ($virtual_watch_number < 0){
  180. $virtual_watch_number = 0;
  181. $this->redis->hSet($this->video_db.$video_id,'virtual_watch_number',0);
  182. }
  183. }
  184. }
  185. //实际观众数统计:累计观众列表和; [score 为负数是:机器人; 正数是:真实观众]
  186. if($video['room_type'] == 1 || $video['room_type'] == 3){
  187. $watch_number = $this->redis->zCount($this->video_viewer_level_db.$video_id, '1', '+inf');
  188. $this->redis->hSet($this->video_db.$video_id,'watch_number',$watch_number);
  189. }
  190. }
  191. if (defined('CHILD_ROOM') && CHILD_ROOM == 1) {
  192. // 退出则所有房间退出
  193. $list = $this->redis->sMembers('video_child_room_' . $video_id);
  194. foreach ($list as $child_id) {
  195. $this->child_room_member_exit($post, $child_id);
  196. }
  197. }
  198. }
  199. /*
  200. * 子房间会员离开
  201. */
  202. public function child_room_member_exit($post, $video_id)
  203. {
  204. $video = $this->redis->hMGet($this->video_db.$video_id,array('room_type','virtual_number','virtual_watch_number',));
  205. if (intval($video['virtual_number']) > 0) {
  206. $number = intval($video['virtual_number'] / 2) ? intval($video['virtual_number'] / 2) : 2;
  207. } else {
  208. $number = 0;
  209. }
  210. $virtual_watch_number = intval($video['virtual_watch_number']);
  211. //退出群的成员列表
  212. foreach ($post['ExitMemberList'] as $k => $v) {
  213. $user_id = $v['Member_Account'];
  214. //用户移除成功
  215. if ($this->redis->zRem($this->video_viewer_level_db . $video_id, $user_id) > 0) {
  216. if ($video['room_type'] != 1 && $virtual_watch_number > 0) {
  217. //随机减少一些虚拟人数
  218. $virtual_number = rand(1, $number);
  219. if ($virtual_number > $virtual_watch_number) {
  220. $virtual_number = $virtual_watch_number;
  221. }
  222. $this->redis->hIncrBy($this->video_db . $video_id, 'virtual_watch_number', -$virtual_number);
  223. $virtual_watch_number = intval($this->redis->hGet($this->video_db . $video_id,
  224. 'virtual_watch_number'));
  225. if ($virtual_watch_number < 0) {
  226. $virtual_watch_number = 0;
  227. $this->redis->hSet($this->video_db . $video_id, 'virtual_watch_number', 0);
  228. }
  229. }
  230. }
  231. }
  232. }
  233. /*
  234. * 获取热门视频
  235. */
  236. public function get_viewer_list($GroupId,$page=0,$page_size=200){
  237. $video_id = $this->redis->hGet($this->video_group_db,$GroupId);
  238. if(!$video_id){
  239. return array(
  240. 'list'=>array(),
  241. 'has_next'=>0,
  242. 'page'=>1,
  243. 'status'=>1
  244. );
  245. }else{
  246. return $this->get_viewer_list2($video_id,$page,$page_size);
  247. }
  248. /*
  249. $root = array();
  250. if($page==0){
  251. $page = 1;
  252. }
  253. $root['page'] = $page;
  254. $start = ($page-1)*$page_size;
  255. $end = $page*$page_size-1;
  256. $video_user_level_array = $this->redis->zRevRange($this->video_viewer_level_db.$video_id,$start,$end,true);
  257. $user_keys = array_keys($video_user_level_array);
  258. $user_list_array = $this->redis->hMGet($this->user_hash_db,$user_keys);
  259. $user_list = array();
  260. if(is_array($user_list_array)){
  261. foreach($user_list_array as $k=>$v){
  262. // $user = array();
  263. if($v){
  264. $user = json_decode($v,true);
  265. $user['video_viewer_level'] = $video_user_level_array[$k];
  266. $user['user_level'] = $user['user_level'];
  267. $user['user_id'] = $k;
  268. $user['head_image'] = get_spec_image($user['head_image']);
  269. $user['nick_name'] = $user['nick_name']?$user['nick_name']:'';
  270. $user['nick_name'] = htmlspecialchars_decode($user['nick_name']);
  271. $user['signature'] = $user['signature']?$user['signature']:'';
  272. $user['signature'] = htmlspecialchars_decode($user['signature']);
  273. $user_list[] = $user;
  274. }
  275. }
  276. }
  277. $root['list'] = $user_list;
  278. if($page == 0){
  279. $root['has_next'] = 0;
  280. }else{
  281. if((count($video_user_level_array)==$page_size) ){
  282. $root['has_next'] = 1;
  283. }else{
  284. $root['has_next'] = 0;
  285. }
  286. }
  287. $root['status'] = 1;
  288. //$root['watch_number'] = $this->redis->zScore($this->video_watch_sort,$video_id);
  289. $root['watch_number'] = $this->get_video_watch_num($video_id);
  290. return $root;
  291. */
  292. }
  293. /*
  294. * 是否在当前房间用户列表
  295. *
  296. */
  297. public function existence_viewer_list($video_id,$user_id){
  298. $root = array();
  299. $root['video_viewer_level_score'] = $this->redis->zScore($this->video_viewer_level_db.$video_id,$user_id);
  300. return $root;
  301. }
  302. /*
  303. * 获取热门视频
  304. */
  305. public function get_viewer_list2($video_id,$page=0,$page_size=200){
  306. $root = array();
  307. if($page==0){
  308. $page = 1;
  309. }
  310. $root['page'] = $page;
  311. $start = ($page-1)*$page_size;
  312. $end = $page*$page_size-1;
  313. $user_keys = $this->redis->zRevRange($this->video_viewer_level_db.$video_id,$start,$end,false);
  314. //echo $this->video_viewer_level_db.$video_id;
  315. //echo "<br>start:".$start.";end:".$end.";page_size:".$page_size;
  316. //$user_keys = array_keys($video_user_level_array);
  317. //print_r($user_keys);
  318. $user_list_array = $this->redis->hMGet($this->user_hash_db,$user_keys);
  319. $user_list = array();
  320. if(is_array($user_list_array)){
  321. foreach($user_list_array as $k=>$v){
  322. // $user = array();
  323. if($v){
  324. $user = json_decode($v,true);
  325. /*
  326. //$user['video_viewer_level'] = $video_user_level_array[$k];
  327. $user['user_level'] = $user['user_level'];
  328. $user['user_id'] = $k;
  329. $user['head_image'] = get_spec_image($user['head_image'],150,150);//get_spec_image($user['head_image']);
  330. $user['nick_name'] = $user['nick_name']?$user['nick_name']:'';
  331. $user['nick_name'] = htmlspecialchars_decode($user['nick_name']);
  332. $user['signature'] = $user['signature']?$user['signature']:'';
  333. $user['signature'] = htmlspecialchars_decode($user['signature']);
  334. $user_list[] = $user;
  335. */
  336. //移除异常数据
  337. if(!$k){
  338. $this->redis->zRem($this->video_viewer_level_db.$video_id,$k);
  339. continue;
  340. }
  341. $user2 = array();
  342. $user2['user_id'] = $k;
  343. $user2['user_level'] = $user['user_level'];
  344. $user2['is_robot'] = $user['is_robot'];
  345. $user2['nick_name'] = $user['nick_name']?$user['nick_name']:'';
  346. $user2['nick_name'] = htmlspecialchars_decode($user2['nick_name']);
  347. $user2['head_image'] = get_spec_image($user['head_image'],150,150);
  348. $user2['v_icon'] = $user['v_icon'];
  349. $user2['is_authentication'] = $user['is_authentication'];
  350. $user2['sex'] = intval($user['sex'])==2?2:1;
  351. $user_list[] = $user2;
  352. }
  353. }
  354. }
  355. $root['list'] = $user_list;
  356. if($page == 0){
  357. $root['has_next'] = 0;
  358. }else{
  359. if((count($user_keys)==$page_size) ){
  360. $root['has_next'] = 1;
  361. }else{
  362. $root['has_next'] = 0;
  363. }
  364. }
  365. $root['status'] = 1;
  366. //$root['watch_number'] = $this->redis->zScore($this->video_watch_sort,$video_id);
  367. $root['watch_number'] = $this->get_video_watch_num($video_id);
  368. if($root['watch_number']<=0){
  369. $root['watch_number']= intval(count($root['list']));
  370. }
  371. return $root;
  372. }
  373. }//类定义结束
  374. ?>