// +---------------------------------------------------------------------- namespace App\Services; use AlibabaCloud\Tea\Exception\TeaUnableRetryError; use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi; use App\Models\LiveModel; use App\Models\MemberModel; use App\Services\Api\MemberCollectService; use Darabonba\OpenApi\Models\Config; use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest; use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions; use Illuminate\Support\Facades\DB; /** * 在线直播服务管理-服务类 * @author laravel开发员 * @since 2020/11/11 * Class LiveService * @package App\Services */ class LiveService extends BaseService { // 静态对象 protected static $instance = null; /** * 构造函数 * @author laravel开发员 * @since 2020/11/11 * ConfigService constructor. */ public function __construct() { $this->model = new LiveModel(); } /** * 静态入口 * @return SmsService|static|null */ public static function make() { if (!self::$instance) { self::$instance = new static(); } return self::$instance; } public function getInfo($id, $userId) { $info = $this->model->with(['member'])->where(['id'=> $id,'mark'=>1])->first(); if($info && isset($info['member'])){ if(isset($info['member']['avatar'])){ $info['member']['avatar'] = $info['member']['avatar']? $info['member']['avatar'] : '/images/member/logo.png'; $info['member']['avatar'] = get_image_url($info['member']['avatar']); } if($info['user_id'] == $userId){ $info['is_foolow'] = 1; }else{ $checkFollow = MemberCollectService::make()->checkCollect($userId, $info['user_id'], 1); $info['is_follow'] = $checkFollow? 1 : 0; } // 观看权限 $info['view_limit'] = 0; // 更新播放量 if(!RedisService::get("caches:live:player:{$userId}_{$id}")){ $this->model->where(['id'=> $id])->update(['views'=>DB::raw('views + 1'),'update_time'=>time()]); RedisService::set("caches:live:player:{$userId}_{$id}", ['user_id'=> $userId,'id'=>$id], rand(600, 1800)); $info['views'] += 1; } } return $info; } /** * 获取直播推流/拉流地址 * @param $streamName * @param string $appName * @param string $playType * @param int $expireTime * @return array */ public function getLiveUrl($streamName, $appName = 'xlapp', $playType = 'rtmp', $expireTime = 1440) { $cachekey = "caches:live:urls:{$streamName}_{$appName}_{$playType}"; $datas = RedisService::get($cachekey); if($datas){ return $datas; } $playUrls = []; //未开启鉴权Key的情况下 $pushDomain = ConfigService::make()->getConfigByCode('live_push_url'); $playDomain = ConfigService::make()->getConfigByCode('live_play_url'); $pushKey = ConfigService::make()->getConfigByCode('push_url_key'); $playKey = ConfigService::make()->getConfigByCode('play_url_key'); $timeStamp = time() + $expireTime * 60; if ($pushKey == '') { $pushUrl = 'rtmp://' . $pushDomain . '/' . $appName . '/' . $streamName; } else { $sstring = '/' . $appName . '/' . $streamName . '-' . $timeStamp . '-0-0-' . $pushKey; $md5hash = md5($sstring); $pushUrl = 'rtmp://' . $pushDomain . '/' . $appName . '/' . $streamName . '?auth_key=' . $timeStamp . '-0-0-' . $md5hash; } if ($playKey == '') { $playUrls['rtmp'] = 'rtmp://' . $playDomain . '/' . $appName . '/' . $streamName; $playUrls['flv'] = 'http://' . $playDomain . '/' . $appName . '/' . $streamName . '.flv'; $playUrls['hls'] = 'http://' . $playDomain . '/' . $appName . '/' . $streamName . '.m3u8'; } else { $rtmpSstring = '/' . $appName . '/' . $streamName . '-' . $timeStamp . '-0-0-' . $playKey; $rtmpMd5hash = md5($rtmpSstring); $playUrls['rtmp'] = 'rtmp://' . $playDomain . '/' . $appName . '/' . $streamName . '?auth_key=' . $timeStamp . '-0-0-' . $rtmpMd5hash; $flvSstring = '/' . $appName . '/' . $streamName . '.flv-' . $timeStamp . '-0-0-' . $playKey; $flvMd5hash = md5($flvSstring); $playUrls['flv'] = 'http://' . $playDomain . '/' . $appName . '/' . $streamName . '.flv?auth_key=' . $timeStamp . '-0-0-' . $flvMd5hash; $hlsSstring = '/' . $appName . '/' . $streamName . '.m3u8-' . $timeStamp . '-0-0-' . $playKey; $hlsMd5hash = md5($hlsSstring); $playUrls['hls'] = 'http://' . $playDomain . '/' . $appName . '/' . $streamName . '.m3u8?auth_key=' . $timeStamp . '-0-0-' . $hlsMd5hash; } $datas = [ 'push_url' => $pushUrl, 'play_url' => isset($playUrls[$playType]) ? $playUrls[$playType] : '', 'play_urls' => $playUrls, ]; RedisService::set($cachekey, $datas, 1800); return $datas; } /** * 创建直播间 * @param $userId 直逼用户 * @param $params * @return array|false */ public function create($userId, $params) { $liveLevel = ConfigService::make()->getConfigByCode('live_open_level'); $liveLevel = $liveLevel > 0 ? $liveLevel : 0; $userInfo = MemberModel::where(['id' => $userId, 'mark' => 1])->select(['id', 'nickname', 'member_level', 'status'])->first(); $status = isset($userInfo['status']) ? $userInfo['status'] : 0; $nickname = isset($userInfo['nickname']) ? $userInfo['nickname'] : ''; $memberLevel = isset($userInfo['member_level']) ? $userInfo['member_level'] : 0; if (empty($userInfo) || $status != 1) { $this->error = 2024; return false; } if($memberLevel < $liveLevel){ $this->error = 2040; return false; } // 验证是否有开播中断播的继续播 $data = [ 'type' => isset($params['type']) ? intval($params['type']) : 1, 'user_id' => $userId, 'title' => isset($params['title']) && $params['title'] ? trim($params['title']) : $nickname.'正在直播', 'description' => isset($params['description']) && $params['description'] ? trim($params['description']) : '我正在直播,快来看看吧', 'category' => isset($params['category']) ? intval($params['category']) : 0, 'visible_type' => isset($params['visible_type']) ? intval($params['visible_type']) : 0, 'visible_users' => isset($params['visible_users']) ? trim($params['visible_users']) : '', 'chat_type' => isset($params['chat_type']) ? intval($params['chat_type']) : 0, 'chat_status' => isset($params['chat_status']) ? intval($params['chat_status']) : 1, 'pay_status' => isset($params['pay_status']) ? intval($params['pay_status']) : 1, 'open_area' => isset($params['open_area']) ? intval($params['open_area']) : 1, 'view_allow' => isset($params['view_allow']) ? intval($params['view_allow']) : 1, 'push_url' => isset($params['push_url']) ? trim($params['push_url']) : '', 'play_url' => isset($params['play_url']) ? trim($params['play_url']) : '', 'update_time'=> time(), 'status' =>1, 'mark'=>1, ]; if($liveId = $this->model->where(['user_id'=> $userId,'status'=>1,'mark'=>1])->orderBy('create_time','desc')->value('id')){ if(!$this->model->where(['user_id'=> $userId,'status'=>1,'mark'=>1])->update($data)){ $this->error = 2042; return false; } }else{ $data['create_time'] = time(); $this->model->where(['user_id'=> $userId,'mark'=>1])->update(['status'=>2,'update_time'=>time()]); if(!$liveId = $this->model->insertGetId($data)){ $this->error = 2042; return false; } } $data['id'] = $liveId; $data['member'] = MemberModel::where(['id'=> $userId])->select(['id','nickname','avatar','status'])->first(); $data['member'] = $data['member']? $data['member'] : []; $data['member']['is_follow'] = 1; if(isset($data['member']['avatar'])){ $data['member']['avatar'] = $data['member']['avatar']? $data['member']['avatar'] : '/images/member/logo.png'; $data['member']['avatar'] = get_image_url($data['member']['avatar']); } $this->error = 2041; return $data; } }