$params['ip'], 'port' => $params['port'], 'com_number' => $params['com_number'], ] )->first(); if ($query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_ALREADY_EXIST; return $result; } } if ($params['camera_source'] == CameraEnum::CAMERA_SOURCE_3) { $camera_url = $params['camera_url']; } else { $camera_url = self::makeCameraUrl($params); } //入库动作 $res = CameraList::insert( [ 'mine_id' => $params['mine_id'], 'ip' => $params['ip'], 'port' => $params['port'], 'user_name' => $params['user_name'], 'password' => $params['password'], 'com_number' => $params['com_number'], 'camera_name' => $params['camera_name'], 'revert_id' => CameraEnum::CAMERA_DEFAULT_REVERT_ID, // 'status' => $params['status'], 'camera_url' => $camera_url, 'sort' => $params['sort'], 'camera_type' => $params['camera_type'], 'camera_source' => $params['camera_source'], 'code_stream' => $params['code_stream'], 'cover_picture' => $params['cover_picture'], 'video_recorder' => $params['video_recorder'], 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ] ); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //生成摄像头请求链接 public static function makeCameraUrl($params) { if ($params['video_recorder'] == CameraEnum::VIDEO_RECORDER_HK) { if (isset($params['code_stream'])) { $code_stream = CameraEnum::CODE_STREAM_TRANS[$params['code_stream']]; } else { $code_stream = 'sub'; } if ($params['user_name'] && $params['password'] && $params['ip'] && $params['port'] && $params['com_number']) { $url = 'rtsp://' . $params['user_name'] . ':' . $params['password'] . '@'; $url .= $params['ip'] . ':' . $params['port'] . '/' . 'h264' . '/' . 'ch' . $params['com_number'] . '/'; $url .= $code_stream . '/av_stream'; //sub 子码流 main 主码流 } else { $url = ''; } } elseif($params['video_recorder'] == CameraEnum::VIDEO_RECORDER_DH){ if (isset($params['code_stream'])) { $code_stream = CameraEnum::CODE_STREAM_DH[$params['code_stream']]; } else { $code_stream = 'sub'; } if ($params['user_name'] && $params['password'] && $params['ip'] && $params['port'] && $params['com_number']) { $url = 'rtsp://' . $params['user_name'] . ':' . $params['password'] . '@'; $url .= $params['ip'] . ':' . $params['port'] . '/cam/realmonitor?channel=' . $params['com_number'] . '&'; $url .= 'subtype=' . $code_stream; } else { $url = ''; } }elseif($params['video_recorder'] == CameraEnum::VIDEO_RECORDER_YS){ if (isset($params['code_stream'])) { $code_stream = CameraEnum::CODE_STREAM_DH[$params['code_stream']]; } else { $code_stream = 'sub'; } if ($params['user_name'] && $params['password'] && $params['ip'] && $params['port'] && $params['com_number']) { $url = 'rtsp://' . $params['user_name'] . ':' . $params['password'] . '@'; $url .= $params['ip'] . ':' . $params['port'] . '/unicast/c' . $params['com_number'] . '/s'; $url .= $code_stream.'/live'; } else { $url = ''; } } return $url; } //编辑摄像头链接 public static function editCameraList($params) { $result['status'] = true; $result['msg'] = AdminEnum::RETURN_SUCCESS; if ($params['camera_source'] == CameraEnum::CAMERA_SOURCE_3) { $camera_url = $params['camera_url']; } else { $camera_url = self::makeCameraUrl($params); } //判断记录是否存在 $query = CameraList::find($params['id']); if (!$query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_NOT_EXIST; return $result; } //通过ip+端口+通道号作为唯一标识判断数据是否存在 if ($params['ip'] && $params['port'] && $params['com_number']) { $query = CameraList::where( [ 'ip' => $params['ip'], 'port' => $params['port'], 'com_number' => $params['com_number'], ] )->where('id', '!=', $params['id'])->first(); if ($query && !$params['cover_picture']) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_ALREADY_EXIST; return $result; } } //更新动作 $res = CameraList::where('id', $params['id'])->update( [ 'mine_id' => $params['mine_id'], 'ip' => $params['ip'], 'port' => $params['port'], 'user_name' => $params['user_name'], 'password' => $params['password'], 'com_number' => $params['com_number'], 'camera_name' => $params['camera_name'], // 'status' => $params['status'], 'camera_url' => $camera_url, 'sort' => $params['sort'], 'camera_type' => $params['camera_type'], 'camera_source' => $params['camera_source'], 'code_stream' => $params['code_stream'], 'cover_picture' => $params['cover_picture'], 'video_recorder' => $params['video_recorder'], 'updated_at' => date('Y-m-d H:i:s'), ] ); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //删除摄像头列表记录 public static function delCameraList($params) { $result['status'] = true; $result['msg'] = AdminEnum::RETURN_SUCCESS; //判断字段是否存在 $query = CameraList::find($params['id']); if (!$query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_NOT_EXIST; return $result; } $res = CameraList::where('id', $params['id'])->delete(); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //添加摄像头链接生成字段 public static function addCameraFieldList($params) { $result['status'] = true; $result['msg'] = AdminEnum::RETURN_SUCCESS; //判断字段是否已存在 $query = CameraFieldList::where('field_name', $params['field_name'])->first(); if ($query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_ALREADY_EXIST; return $result; } //入库动作 $res = CameraFieldList::insert( [ 'field_name' => $params['field_name'], 'created_at' => date('Y-m-d H:i:s'), 'updated_at' => date('Y-m-d H:i:s'), ] ); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //编辑摄像头链接生成字段 public static function editCameraFieldList($params) { $result['status'] = true; $result['msg'] = AdminEnum::RETURN_SUCCESS; //判断字段是否存在 $query = CameraFieldList::find($params['id']); if (!$query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_NOT_EXIST; return $result; } $res = CameraFieldList::where('id', $params['id'])->update( [ 'field_name' => $params['field_name'], 'updated_at' => date('Y-m-d H:i:s'), ] ); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //删除摄像头链接生成字段 public static function delCameraFieldList($params) { $result['status'] = true; $result['msg'] = AdminEnum::RETURN_SUCCESS; //判断字段是否存在 $query = CameraFieldList::find($params['id']); if (!$query) { $result['status'] = false; $result['msg'] = AdminEnum::RECORD_NOT_EXIST; return $result; } $res = CameraFieldList::where('id', $params['id'])->delete(); if (!$res) { $result['status'] = false; $result['msg'] = AdminEnum::DATABASE_ERROR; } return $result; } //根据矿区id获取摄像头列表 public static function getCameraListByMineId($mine_id, $camera_type = CameraEnum::CAMERA_TYPE_ALL, $parent_id, $surface_id = '') { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $query = CameraList::where('is_show', CameraEnum::IS_SHOW_YES)->orderBy('sort', 'desc'); if ($camera_type && $camera_type != CameraEnum::CAMERA_TYPE_ALL) { $query = $query->where('camera_type', $camera_type); } $query = $query->select( [ 'id as camera_id', 'mine_id', 'camera_name', 'cover_picture', 'camera_status', ] )->get()->toArray(); $surface_camera = []; if ($surface_id) { $surface_camera = WorkingSurfaceCamera::where('surface_id', $surface_id)->pluck('camera_id')->all(); } $arr = []; foreach ($query as $key => $val) { if ($surface_id && !in_array($val['camera_id'], $surface_camera)) { continue; } $val['parent_id'] = $parent_id; if ($camera_type && !in_array($camera_type, [CameraEnum::CAMERA_TYPE_ALL, CameraEnum::CAMERA_TYPE_NORMAL])) { $degree = MineList::where('id', $val['mine_id'])->value('degree'); if ($mine_id == explode('|', $degree)[0]) { $arr[] = $val; } } else { if ($mine_id == $val['mine_id']) { $arr[] = $val; } } } $result['data'] = $arr; return $result; } //根据摄像头id获取摄像头播放链接 public static function getCameraUrlByCameraId($camera_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $query = CameraList::where('id', $camera_id)->first(); if (!$query) { $result['status'] = false; $result['msg'] = ApiEnum::NO_CAMERA_URL; return $result; } $degree = MineList::where('id', $query->mine_id)->value('degree'); $mine_list = MineList::whereIn('id', explode('|', $degree))->select(['title'])->get()->toArray(); $path = ''; foreach ($mine_list as $key => $val) { $path .= '/' . $val['title']; } $path .= '/' . $query->camera_name . $camera_id; //标记摄像头为在线状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ONLINE]); //已有拉流id,直接返回拉流链接 $has_file = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME); if ($has_file) { $result['data'] = [ 'camera_id' => $camera_id, 'url' => env('VIDEO_SYSTEM_URL') . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME . '?' . time(), ]; return $result; } $data = [ 'url' => $query->camera_url, 'customPath' => $path, ]; Log::info('请求流媒体服务器参数------------'); Log::info($data); $curl = env('EASY_DARWIN_URL') . CameraEnum::API_STREAM_START . '?' . http_build_query($data); //请求流媒体服务器拉流 $curl_res = curl_request($curl); Log::info('请求流媒体服务器result------------'); Log::info($curl_res); if (strpos($curl_res,' ')) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::EASY_DAWIN_REQUEST_FAIL; return $result; } $result['data'] = [ 'camera_id' => $camera_id, 'url' => env('VIDEO_SYSTEM_URL') . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME . '?' . time(), ]; //sleep10秒生成文件 $i = 1; while ($i <= 10) { //判断m3u8文件是否存在 $file_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME); //判断ts文件是否存在 $ts_exists = glob(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::TS_FILE_SUFFIX); //查询是否存在封面图 $cover_picture = CameraList::where('id', $camera_id)->value('cover_picture'); if ($file_exists && $ts_exists) { //查询是否存在封面图 if (!$cover_picture) { //获取第一帧作为封面图 $file_name = time() . CameraEnum::COVER_PICTURE_NAME; $cover_exec = 'ffmpeg -i ' . public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME . ' -vf "select=between(mod(n\, 25)\, 0\, 0), setpts=N/24/TB" ' . public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . $file_name; exec($cover_exec); //判断图片是否存在 $picture_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/' . $file_name); if ($picture_exists) { //上传图片到oss并更新数据库 $picture_path = self::uploadOssFile($file_name, public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . date('Ymd', time()) . '/'); CameraList::where('id', $camera_id)->update(['cover_picture' => $picture_path]); } } //更新拉流id CameraList::where('id', $camera_id)->update( [ 'revert_id' => trim($curl_res, '"'), 'updated_at' => date('Y-m-d H:i:s'), ] ); return $result; } else { sleep(1); } $i++; } //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::EASY_DAWIN_REQUEST_FAIL; return $result; } //停止流媒体推流 public static function stopCameraStream() { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; //先查询流媒体推流列表 $data = [ // 'start' => 0, // 'limit' => 100, ]; $curl = env('EASY_DARWIN_URL') . CameraEnum::API_PUSHERS . '?' . http_build_query($data); //请求流媒体服务器获取推流列表 $curl_res = curl_request($curl); $curl_res = json_decode($curl_res, true); $success = 0; if ($curl_res['total'] > 0) { //根据返回id调停止推流接口 foreach ($curl_res['rows'] as $key => $val) { $data = [ 'id' => $val['id'] ]; $curl = env('EASY_DARWIN_URL') . CameraEnum::API_STREAM_STOP . '?' . http_build_query($data); //请求流媒体服务器停止推流 $stop_res = curl_request($curl); $stop_res = json_decode($stop_res, true); if ($stop_res == 'OK') { //更新拉流id为默认id CameraList::where('revert_id', $val['id'])->update( [ 'revert_id' => CameraEnum::CAMERA_DEFAULT_REVERT_ID, 'updated_at' => date('Y-m-d H:i:s'), ] ); $success++; } else { Log::info('流媒体服务器停止推流失败id:' . $val['id']); Log::info('流媒体服务器停止推流失败返回结果'); Log::info($stop_res); } } } if ($success == $curl_res['total']) { CameraList::where('revert_id', '!=', CameraEnum::CAMERA_DEFAULT_REVERT_ID)->update( [ 'revert_id' => CameraEnum::CAMERA_DEFAULT_REVERT_ID, 'updated_at' => date('Y-m-d H:i:s'), ] ); } //清空海康视频服务器已存在id CameraList::where('revert_id', CameraEnum::CAMERA_FILE_EXIST)->update(['revert_id' => CameraEnum::CAMERA_DEFAULT_REVERT_ID]); //递归删除目录 $dir = public_path() . '/files/video/m3u8/'; if (is_dir($dir)) { deldir($dir); } return $result; } //查询海康矿井摄像头列表 public static function getHaiKangCamera($parent_id, $mine_id, $camera_type) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $result['data'] = []; if ($camera_type != CameraEnum::CAMERA_TYPE_ALL) { return $result; } $query = MineListExt::where('mine_id', $parent_id)->first(); $list = []; Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, 'indexCode' => $mine_id, ] ); $haikang = new HaiKangController(); $result_hk = $haikang->getCamerasList(); if ($result_hk['data']['list']) { foreach ($result_hk['data']['list'] as $key => $val) { $list[$key]['mine_id'] = $mine_id; $list[$key]['camera_id'] = $val['cameraIndexCode']; $list[$key]['camera_name'] = $val['cameraName']; $list[$key]['trans_code'] = $val['encodeDevIndexCode']; $list[$key]['com_number'] = $val['channelNo']; } } $result['data'] = $list; return $result; } //查询海康摄像头编码设备列表 public static function getHaiKangTransList($parent_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $result['data'] = []; $query = MineListExt::where('mine_id', $parent_id)->first(); //先获取编码设备列表 Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, ] ); $haikang = new HaiKangController(); $result_hk = $haikang->getTranscodeList(); if ($result_hk['data']['list']) { $result['data'] = $result_hk['data']['list']; } return $result; } //查询海康矿井摄像头播放链接 public static function getHaiKangCameraUrl($parent_id, $camera_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $result['data'] = []; $query = MineListExt::where('mine_id', $parent_id)->first(); $slug = MineList::where('id', $parent_id)->value('slug'); $count = strpos($slug, 'MeiKuang'); if ($count) { $slug = substr_replace($slug, '', $count, 8); } $slug = strtolower($slug); Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, 'cameraIndexCode' => $camera_id, ] ); $haikang = new HaiKangController(); $result_hk = $haikang->getCamerasUrl(); if ($result_hk['data']['url']) { $url = CameraEnum::VIDEO_AGENCY_URL . $slug . '/video/' . strstr($result_hk['data']['url'], 'openUrl'); $result['data']['camera_id'] = $camera_id; $result['data']['url'] = $url; } return $result; } //查询海康矿井摄像头列表 public static function getHaiKangTransCode($parent_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $result['data'] = []; $query = MineListExt::where('mine_id', $parent_id)->first(); Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, ] ); $haikang = new HaiKangController(); $result_hk = $haikang->getTranscodeInfo(); if ($result_hk) { $result['data'] = json_decode($result_hk, true); } return $result; } //获取大南湖监控列表 public static function getLeChangeCamera() { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $token = self::getLeChangeToken(); if (!$token) { $result['status'] = false; $result['msg'] = ApiEnum::LECHANGE_REQUEST_FAIL; return $result; } $url = CameraEnum::LIVE_LIST_URL; $params = [ 'token' => $token, 'queryRange' => '1-10', ]; $data = self::getLeChangeSign($params); $ch = curl_init(); $res = curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $curl_res = curl_exec($ch); curl_close($ch); $curl_res = json_decode(iconv('utf-8', 'UTF-8', $curl_res), true); if ($curl_res == null || $curl_res['result']['msg'] != CameraEnum::LECHANGE_API_SUCCESS) { $result['status'] = false; $result['msg'] = ApiEnum::LECHANGE_REQUEST_FAIL; return $result; } foreach ($curl_res['result']['data']['lives'] as $key => $val) { $result['data'][$key] = [ 'camera_name' => $val['deviceId'], 'camera_url' => $val['streams'][3]['hls'] ]; } return $result; } //乐橙获取access_token public static function getLeChangeToken() { if (Cache::has(CameraEnum::ACCESS_TOKEN_CACHE_KEY)) { return Cache::get(CameraEnum::ACCESS_TOKEN_CACHE_KEY); } $url = CameraEnum::ACCESS_TOKEN_URL; $data = self::getLeChangeSign(); $ch = curl_init(); $res = curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $result = curl_exec($ch); curl_close($ch); $result = json_decode(nl2br(iconv('utf-8', 'UTF-8', $result)), true); if ($result == null || $result['result']['msg'] != CameraEnum::LECHANGE_API_SUCCESS) { return false; } $token = $result['result']['data']['accessToken']; $time = substr($result['result']['data']['expireTime'], 0, 2) . '0000'; Cache::put(CameraEnum::ACCESS_TOKEN_CACHE_KEY, $token, $time); return $token; } //乐橙数据接口验签 private static function getLeChangeSign($params = []) { $time = strtotime(date('Y-m-d H:i:s', time())); $nonce = md5(time()); $appId = CameraEnum::LECHANGE_APPID; $appSecret = CameraEnum::LECHANGE_APPSECRET; $signStr = "time:$time,nonce:$nonce,appSecret:$appSecret"; $sign = md5($signStr); $data = json_encode( [ 'system' => [ 'ver' => '1.0', 'sign' => $sign, 'appId' => $appId, 'time' => $time, 'nonce' => $nonce ], 'params' => empty($params) ? new \stdClass() : $params, 'id' => '88' ] ); return $data; } //通过rtmp同步m3u8文件并返回url public static function downloadCameraFiles($parent_id, $camera_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $query = MineListExt::where('mine_id', $parent_id)->first(); $camera = CameraList::find($camera_id); $degree = MineList::where('id', $camera->mine_id)->value('degree'); $degree = explode('|', $degree); $path = ''; foreach ($degree as $key => $val) { $path .= MineList::where('id', $val)->value('title') . '/'; } $path .= $camera->camera_name . '/' . date('Ymd'); //标记摄像头为在线状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ONLINE]); //如果m3u8文件已拉取,直接返回播放链接 if ($camera->revert_id == CameraEnum::CAMERA_FILE_EXIST) { $result['data'] = [ 'camera_id' => $camera_id, 'url' => env('VIDEO_SYSTEM_URL') . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::M3U8_FILE_NAME . '?' . time(), ]; return $result; } if ($camera->video_recorder == CameraEnum::VIDEO_RECORDER_HK) { //海康视频逻辑 Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, 'cameraIndexCode' => $camera->index_code, 'streamType' => CameraEnum::CODE_STREAM_HAK[$camera->code_stream], 'protocol' => 'rtmp' ] ); $haikang = new HaiKangController(); $result_hk = $haikang->getCamerasUrl(); if ($result_hk['data']['url']) { //先取当前码流 $res = self::getVideoStream($result_hk['data']['url'], $path, $camera_id); if (!$res) { $code_stream = self::exchangCodeStream($camera->code_stream); Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, 'cameraIndexCode' => $camera->index_code, 'streamType' => CameraEnum::CODE_STREAM_HAK[$code_stream], 'protocol' => 'rtmp', ] ); $haikang = new HaiKangController(); $result_hk_2 = $haikang->getCamerasUrl(); if (!$result_hk_2['data']['url']) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } $res = self::getVideoStream($result_hk_2['data']['url'], $path, $camera_id); if (!$res) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } else { //更新视频码流 CameraList::where('id', $camera_id)->update(['code_stream' => $code_stream]); $result['data'] = $res['data']; } } else { $result['data'] = $res['data']; } } else { //直接获取rtmp失败时切换码流重新获取 $code_stream = self::exchangCodeStream($camera->code_stream); Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'key' => $query->key, 'secret' => $query->secret, 'cameraIndexCode' => $camera->index_code, 'streamType' => CameraEnum::CODE_STREAM_HAK[$code_stream], 'protocol' => 'rtmp', ] ); $haikang = new HaiKangController(); $result_hk_2 = $haikang->getCamerasUrl(); if (!$result_hk_2['data']['url']) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } $res = self::getVideoStream($result_hk_2['data']['url'], $path, $camera_id); if (!$res) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } else { //更新视频码流 CameraList::where('id', $camera_id)->update(['code_stream' => $code_stream]); $result['data'] = $res['data']; } } } else if ($camera->video_recorder == CameraEnum::VIDEO_RECORDER_TD) { //天地伟业视频逻辑 Input::replace( [ 'url' => trim($query->ip, '/') . ':' . $query->port, 'username' => $query->key, 'password' => $query->secret, 'sysId' => 'PG', 'sId' => $camera->index_code, 'ip' => trim(trim($camera->ip, 'http://'), 'https://'), 'port' => $camera->port, ] ); $tdwy = new TdwyController(); $result_td = $tdwy->getRtspById(); if ($result_td['statusCode'] == CameraEnum::TDWY_API_STATUS_CODE_SUCCSS && $result_td['content']) { //执行取流动作 $res = self::getVideoStream($result_td['content'][0]['url'], $path, $camera_id); if (!$res) { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } else { $result['data'] = $res['data']; } } else { //标记摄像头为异常状态 CameraList::where('id', $camera_id)->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]); $result['status'] = false; $result['msg'] = ApiEnum::HK_REQUEST_FAIL; return $result; } } else { $result['status'] = false; $result['msg'] = ApiEnum::NONEXISTENT_VIDEO_RECORDER; return $result; } return $result; } //获取视频流 public static function getVideoStream($video_url, $path, $camera_id) { Log::info(1231230818237129873); Log::info($video_url); $result = []; if (!is_dir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path)) { mkdir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path, 0777, true); } //取流进程 $exec = 'nohup /usr/bin/ffmpeg -i "' . $video_url . '" -vcodec copy -acodec copy -vbsf h264_mp4toannexb -f hls -hls_flags delete_segments -segment_list_size 10 -hls_list_size 2 /www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::M3U8_FILE_NAME . ' >/dev/null &'; Log::info($exec); shell_exec($exec); //sleep10秒生成文件 $i = 1; while ($i <= 10) { //判断m3u8文件是否存在 $file_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::M3U8_FILE_NAME); //判断ts文件是否存在 $ts_exists = glob(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::TS_FILE_SUFFIX); //查询是否存在封面图 $cover_picture = CameraList::where('id', $camera_id)->value('cover_picture'); if ($file_exists && $ts_exists) { //查询是否存在封面图 if (!$cover_picture) { //获取第一帧作为封面图 $file_name = time() . CameraEnum::COVER_PICTURE_NAME; $cover_exec = 'ffmpeg -i ' . public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::M3U8_FILE_NAME . ' -vf "select=between(mod(n\, 25)\, 0\, 0), setpts=N/24/TB" ' . public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . $file_name; exec($cover_exec); //判断图片是否存在 $picture_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . $file_name); if ($picture_exists) { //上传图片到oss并更新数据库 $picture_path = self::uploadOssFile($file_name, public_path() . '/' . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/'); CameraList::where('id', $camera_id)->update(['cover_picture' => $picture_path]); } } $result['data'] = [ 'camera_id' => $camera_id, 'url' => env('VIDEO_SYSTEM_URL') . CameraEnum::M3U8_FILE_PATH . '/' . $path . '/' . CameraEnum::M3U8_FILE_NAME . '?' . time(), ]; CameraList::where('id', $camera_id)->update(['revert_id' => CameraEnum::CAMERA_FILE_EXIST]); return $result; } else { sleep(1); } $i++; } return false; } //切换视频码流 public static function exchangCodeStream($code_stream) { $return_code = CameraEnum::CODE_STREAM_MAIN; //子码流切主码流 if ($code_stream == CameraEnum::CODE_STREAM_SUB) { $return_code = CameraEnum::CODE_STREAM_MAIN; } //主码流切子码流 if ($code_stream == CameraEnum::CODE_STREAM_MAIN) { $return_code = CameraEnum::CODE_STREAM_SUB; } return $return_code; } //获取内网服务器摄像头播放地址 public static function getIntranetCameraUrl($camera_id) { $result['status'] = true; $result['msg'] = ApiEnum::RETURN_SUCCESS; $camera_url = CameraList::where('id', $camera_id)->value('camera_url'); if (!$camera_url) { $result['status'] = false; $result['msg'] = ApiEnum::NO_CAMERA_URL; return $result; } $result['data'] = [ 'camera_id' => $camera_id, 'url' => rtrim($camera_url, '/') . '/' . date('Ymd', time()) . '/' . CameraEnum::M3U8_FILE_NAME ]; return $result; } //上传文件到本地 public static function uploadFile($file) { $destinationPath = public_path() . '/filedownload/'; $extension = $file->getClientOriginalExtension(); $fileName = time() . '.' . $extension; $file->move($destinationPath, $fileName); return $fileName; } //oss上传文件 public static function uploadOssFile($file_name, $file_path) { try{ $oss = new OssClient( Config::get('filesystems.disks.oss_view.access_key'), Config::get('filesystems.disks.oss_view.secret_key'), Config::get('filesystems.disks.oss_view.endpoint') ); $res = $oss->uploadFile(Config::get('filesystems.disks.oss_view.bucket'), '摄像头封面/oss-' . $file_name, $file_path . $file_name); } catch(OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; } if (isset($res['info']['url']) && $res['info']['url']) { return urldecode($res['info']['url']); } else { return false; } } //删除临时上传文件 public static function delUploadFile($delDir = FALSE) { $path = public_path() . '/filedownload/'; $handle = opendir($path); if ($handle) { while (false !== ( $item = readdir($handle) )) { if ($item != "." && $item != "..") is_dir("$path/$item") ? delDirAndFile("$path/$item", $delDir) : unlink("$path/$item"); } closedir($handle); if ($delDir) return rmdir($path); }else { if (file_exists($path)) { return unlink($path); } else { return FALSE; } } } }