<?php /** * 直播活动详情接口 * Created by PhpStorm. * User: yingcai * Date: 2018/1/9 * Time: 上午10:45 */ namespace Api\Controller\Room; use Com\LiveSDK; use Common\Common\Constant; use Common\Common\Order; use Common\Common\User; use Common\Service\MainService; use Common\Service\ParticipateService; use Common\Service\RangeService; use Common\Service\RoleService; use Common\Service\StudioFileService; use Common\Service\StudioPlaybackService; use Common\Service\StudioService; use Org\Util\DistributedRedisLock; use VcySDK\Enterprise; use VcySDK\Service; class DetailController extends AbstractController { /** * Detail * @author houyingcai * @desc 直播活动详情接口 * @param Int lm_id:true:1 直播活动ID * @return array|bool 直播列表 array( 'live_status' => 1, // 直播状态(1:草稿,2:未开始,3:进行中,4:已结束) 'watched_total' => 123, // 当前进入直播间的人数 'start_time' => 1515407868910, // 直播开始时间 'name' => '产品培训讲解', // 直播名称 'estimated_duration' => 45, // 预计时长(单位:分钟) 'live_desc' => '直播描述', // 直播描述 'pic' => 'b3ddbc502e307665f346cbd6e52cc10d', // 封面图ID 'pic_url' => 'http://qy.vchangyi.org', // 封面图片URL 'lecturer' => '王宇', // 讲师姓名 'avatar' => 'http://qy.vchangyi.org', // 讲师头像URL 'lecturer_title' => '金牌讲师', // 讲师头衔 'lecturer_desc' => '讲师简介', // 讲师简介 'end_time' => 12312312312, // 结束时间 'has_playback' => true, // 是否有回放 true 有 false 无 ) */ public function Index_post() { $lmId = I('post.lm_id', 0, 'rintval'); // 直播ID不能为空 if (!$lmId) { E('_EMPTY_LIVE_ID'); } // 获取直播信息 $mainService = new MainService(); $mainDetail = $mainService->get($lmId); // 直播信息不存在 if (empty($mainDetail)) { E('_ERR_LIVE_NOT_EXISTS'); } // 获取讲师信息 $roleService = new RoleService(); $roleInfo = $roleService->get_by_conds([ 'lm_id' => $lmId ]); // 判断是否有观看权限 $rangeService = new RangeService(); $user = $this->_login->user; $checkRes = $rangeService->checkUserRange($user, $lmId); if (!$checkRes && $this->uid != $roleInfo['obj_id']) { E('_ERR_NOT_WATCHED_RANGE'); } // 格式化直播状态 $live_status = $mainService->live_status($mainDetail['live_status'], $mainDetail['start_time']); if ($roleInfo['type'] == Constant::LIVE_ROLE_TYPE_DEFAULT) { $lecturer = $roleInfo['obj_id']; // 系统管理员没有头像 $avatar = ''; } else { // 获取讲师个人信息 $userService = &User::instance(); $lecturerInfo = $userService->getByUid($roleInfo['obj_id']); $lecturer = $lecturerInfo['memUsername']; $avatar = $userService->avatar($roleInfo['obj_id'], $lecturerInfo); } // 先判断当前用户有没有观看记录 $participateServ = new ParticipateService(); $isParRes = $participateServ->count_by_conds([ 'lm_id' => $lmId, 'obj_id' => $this->uid, ]); // 获取直播地址 $liveSdk = new LiveSDK(); $studioServ = new StudioService(); $studioDetail = $studioServ->get_by_conds(['lm_id' => $mainDetail['lm_id']]); $playURLList = $liveSdk->getPlayUrl($studioDetail['stream_id']); $playUrl = $playURLList[2]; // 初始化 Redis $redis = new \Redis(); $redis->connect(cfg('REDIS_HOST'), cfg('REDIS_PORT')); if (cfg('REDIS_PWD')) { $redis->auth(cfg('REDIS_PWD')); } // 是否在线 $userInRedisKey = 'Live_' . $lmId . '_USER_' . $this->uid; // 不在 在线列表内 并且 直播活动没有结束 if (!$redis->exists($userInRedisKey) && $mainDetail['live_status'] != Constant::LIVE_STATUS_OVER) { // 获取锁 $redLock = new DistributedRedisLock([$redis], 500, 10); $lock = $redLock->lock('Live_' . $lmId . '_Lock_Update_Peak', 1000); if (!$lock) { E('_ERR_PLEASE_TRY_AGAIN_LATER'); } // 获取当前在线人数 $onlineMemberNum = count($redis->keys('Live_' . $lmId . '_USER_*')); // 获取峰值 $redisKeyNamePeak = 'Live_' . $lmId . '_PEAK'; $peakMemberNum = $redis->get($redisKeyNamePeak) ?: $mainDetail['online_peak']; // 在线人数超过峰值 if ((++ $onlineMemberNum) > $peakMemberNum) { // isStandard -- 企业是否使用标准产品 : 0:非标准, 1:标准产品 $sdk = new Enterprise(Service::instance()); $epDetail = $sdk->detail(); if (1 == $epDetail['isStandard']) { // 扣减并发人数 $orderUtil = new Order(); $deductionsSuccess = $orderUtil->LiveCaseExpend([ 'liveCastId' => $studioDetail['stream_id'], 'lcelSpendAmout' => 1 ]); \Think\Log::record('扣减结果:::' . var_export($deductionsSuccess, true)); // 扣减失败 if (!$deductionsSuccess) { E('_ERR_PLEASE_TRY_AGAIN_LATER'); } } // 单个用户进来只会增加一个峰值 $redis->incr($redisKeyNamePeak); $redis->expire($redisKeyNamePeak, Constant::PEAK_SURVIVAL_TIME); // 增加峰值 $mainService->update($lmId, ['online_peak = online_peak + ?' => 1]); } // 释放锁 $redLock->unlock($lock); } // 算进在线人数内 $redis->set($userInRedisKey, '', Constant::ONLINE_SURVIVAL_TIME); // 没有观看记录 if (!$isParRes) { // 新增一条观看记录 $insertData = [ 'lm_id' => $lmId, 'obj_id' => $this->uid, ]; $participateServ->insert($insertData); // 更新主表观看人数字段 $mainService->update($lmId, ['watched_total = watched_total + ?' => 1]); $mainDetail['watched_total'] = $mainDetail['watched_total'] + 1; } else { // 更新最后观看记录时间 $participateServ->update_by_conds( [ 'lm_id' => $lmId, 'obj_id' => $this->uid, ], ['updated' => MILLI_TIME] ); } // 直播已经结束 if ($mainDetail['live_status'] == Constant::LIVE_STATUS_OVER) { // 获取回放地址 $studioPlayBackServ = new StudioPlaybackService(); $playBackList = $studioPlayBackServ->list_by_conds(['lm_id' => $lmId]); if (!empty($playBackList)) { $playBackList = array_combine_by_key($playBackList, 'number'); ksort($playBackList); } $playUrl = array_column($playBackList, 'sd'); } // 返回数据 $this->_result = [ 'live_status' => intval($live_status), 'watched_total' => $mainDetail['watched_total'], 'start_time' => $mainDetail['start_time'], 'end_time' => $mainDetail['end_time'], 'name' => $mainDetail['name'], 'estimated_duration' => $mainDetail['estimated_duration'], 'live_desc' => $mainDetail['desc'], 'pic' => $mainDetail['pic'], 'pic_url' => $mainService->formatCover($mainDetail['pic']), 'lecturer' => $lecturer, 'avatar' => $avatar, 'lecturer_title' => $roleInfo['title'], 'lecturer_desc' => $roleInfo['desc'], // 结束了回放 'play_url' => $playUrl, // 是否有回放 true 有 false 无 'has_playback' => !empty($playUrl), 'push_total_time' => $mainDetail['push_total_time'] ]; return true; } }