HaiKangController.php 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: qiuzijian
  5. * Date: 2021-04-28
  6. * Time: 20:59
  7. */
  8. namespace Modules\Camera\Http\Controllers\Api;
  9. use App\Enum\ApiEnum;
  10. use App\Http\Controllers\Api\BaseController;
  11. use Illuminate\Http\Request;
  12. use Illuminate\Support\Facades\Input;
  13. use Illuminate\Support\Facades\Log;
  14. use Modules\Camera\Entities\CameraList;
  15. use Modules\Camera\Enum\CameraEnum;
  16. use Modules\Mine\Entities\MineList;
  17. use Modules\Mine\Services\MineServices;
  18. use Modules\Camera\Services\CameraServices;
  19. use DB;
  20. class HaiKangController extends BaseController
  21. {
  22. protected $pre_url; // 海康接口地址
  23. protected $app_key; // 海康app_key
  24. protected $app_secret; // 海康app_secret
  25. protected $sign;// 签名
  26. protected $time;// 时间戳
  27. protected $artemis;// OpenAPI接口的上下文
  28. public function __construct()
  29. {
  30. // if ($request->has('mine')) {
  31. // $this->pre_url = config('haikang.' . $request->input('mine') . '.pre_url'); // https://120.253.79.51:4433
  32. // $this->app_key = config('haikang.' . $request->input('mine') . '.app_key'); // 25720460
  33. // $this->app_secret = config('haikang.' . $request->input('mine') . '.app_secret'); // qqP7NLcIDwO9MgtYmp8L
  34. // $this->artemis = config('haikang.' . $request->input('mine') . '.artemis'); // /artemis
  35. // } else {
  36. // $this->pre_url = env('HAI_KANG_URL'); // https://120.253.79.51:4433
  37. // $this->app_key = env('HAI_KANG_APP_KEY'); // 25720460
  38. // $this->app_secret = env('HAI_KANG_APP_SECRET'); // qqP7NLcIDwO9MgtYmp8L
  39. // $this->artemis = env('HAI_KANG_ARTEMIS_PATH'); // /artemis
  40. // }
  41. // $this->pre_url = 'https://10.71.252.64:4433'; // https://120.253.79.51:4433
  42. // $this->app_key = '25720460'; // 25720460
  43. // $this->app_secret = 'qqP7NLcIDwO9MgtYmp8L'; // qqP7NLcIDwO9MgtYmp8L
  44. // $this->artemis = '/artemis'; // /artemis
  45. $this->pre_url = Input::get('url'); // https://120.253.79.51:4433
  46. $this->app_key = Input::get('key'); // 25720460
  47. $this->app_secret = Input::get('secret'); // qqP7NLcIDwO9MgtYmp8L
  48. $this->artemis = '/artemis'; // /artemis
  49. list($msec, $sec) = explode(' ', microtime());
  50. $this->time = (float)sprintf('%.0f', (floatval($msec) + floatval($sec)) * 1000);
  51. }
  52. //视频质量诊断
  53. public function videoQuality(){
  54. $indexCode = Input::get('indexCode');
  55. $url = $this->artemis . '/api/nms/v1/vqd/list';
  56. //请求参数
  57. $params = [];
  58. $params['pageNo'] = 1;
  59. $params['pageSize'] = 20;
  60. $params['indexCodes'] = [$indexCode];
  61. $this->sign = $this->get_sign($url);
  62. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  63. $result = json_decode($result, true);
  64. return $result;
  65. }
  66. //根据区域编号获取下一级区域列表
  67. public function getChildMineList(){
  68. $url = $this->artemis . '/api/resource/v2/regions/subRegions';
  69. //请求参数
  70. $params = [];
  71. $params['parentIndexCode'] = Input::get('index_code');
  72. $params['resourceType'] = 'camera';
  73. $params['pageNo'] = 1;
  74. $params['pageSize'] = 1000;
  75. $params['cascadeFlag'] = 0;
  76. $this->sign = $this->get_sign($url);
  77. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  78. $result = json_decode($result, true);
  79. dd($result);
  80. }
  81. /**
  82. * 获取区域列表
  83. * @return bool|mixed|string
  84. */
  85. public function getRegionsList()
  86. {
  87. $url = $this->artemis . '/api/resource/v1/regions';
  88. //请求参数
  89. $params = [];
  90. // $params['pageNo'] = $request->has('pageNo') ? intval($request->input('pageNo')) : 1;
  91. // $params['pageSize'] = $request->has('pageSize') ? intval($request->input('pageSize')) : 1000;
  92. $params['pageNo'] = 1;
  93. $params['pageSize'] = 1000;
  94. $this->sign = $this->get_sign($url);
  95. $type = Input::get('type');
  96. $mine_id = Input::get('mine_id');
  97. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  98. $result = json_decode($result, true);
  99. //超出1000条数据
  100. if(isset($result['data']['list']) && count((array)$result['data']['list']) == 1000){
  101. $params['pageNo'] = 2;
  102. $result2 = $this->curlPost($this->pre_url . $url, json_encode($params));
  103. $result2 = json_decode($result2, true);
  104. }
  105. $area_list = [];
  106. if (isset($result['code']) && $result['code'] == 0 && isset($result['data']['list'])) {
  107. if(isset($result2)){
  108. $list = array_merge($result['data']['list'],$result2['data']['list']);
  109. }else{
  110. $list = $result['data']['list'];
  111. }
  112. foreach ($list as $key => $item) {
  113. $area_list[] = $item['indexCode'];
  114. if ($item['parentIndexCode'] == '-1') {
  115. unset($list[$key]);
  116. }
  117. }
  118. $result['data']['list'] = array_values($list);
  119. }else{
  120. $result['data']['list'] = [];
  121. }
  122. if ($type == CameraEnum::REQUEST_TYPE_API) {
  123. $result['data']['list'] = $this->regionsTree($result['data']['list']);
  124. } else {
  125. //先删除不存在的区域
  126. if ($area_list) {
  127. MineList::where('degree', 'like', $mine_id . '|%')->whereNotIn('index_code', $area_list)->delete();
  128. }
  129. //更新区域
  130. $result['data']['list'] = $this->saveTree($result['data']['list'], $mine_id);
  131. }
  132. return $result;
  133. }
  134. protected function regionsTree($regions, $pid = 'root000000')
  135. {
  136. $arr = [];
  137. if (empty($regions)) {
  138. return [];
  139. }
  140. foreach ($regions as $key => $value) {
  141. if (isset($value['parentIndexCode']) && $value['parentIndexCode'] == $pid) {
  142. $arr[$key]['indexCode'] = $value['indexCode'];
  143. $arr[$key]['mine_id'] = $value['indexCode'];
  144. $arr[$key]['name'] = $value['name'];
  145. $arr[$key]['parentIndexCode'] = $value['parentIndexCode'];
  146. $arr[$key]['treeCode'] = $value['treeCode'];
  147. $arr[$key]['children'] = array_values(self::regionsTree($regions, $value['indexCode']));
  148. unset($arr[$key]['indexCode']);
  149. unset($arr[$key]['parentIndexCode']);
  150. unset($arr[$key]['treeCode']);
  151. if (count($arr[$key]['children']) == 0) {
  152. unset($arr[$key]['children']);
  153. }
  154. }
  155. }
  156. return array_values($arr);
  157. }
  158. protected function saveTree($regions, $parent_id, $pid = 'root000000')
  159. {
  160. $arr = [];
  161. if (empty($regions)) {
  162. return [];
  163. }
  164. $mineService = new MineServices();
  165. $mineService->initMineList();
  166. $arr_count = count($regions);
  167. foreach ($regions as $key => $value) {
  168. if (isset($value['parentIndexCode']) && $value['parentIndexCode'] == $pid) {
  169. $arr[$key]['indexCode'] = $value['indexCode'];
  170. $arr[$key]['mine_id'] = $value['indexCode'];
  171. $arr[$key]['name'] = str_replace('#', '号', $value['name']);
  172. $arr[$key]['parentIndexCode'] = $value['parentIndexCode'];
  173. $arr[$key]['treeCode'] = $value['treeCode'];
  174. $id = MineList::where('index_code', $value['indexCode'])->value('id');
  175. $params = [
  176. 'id' => $id,
  177. 'parent_id' => $parent_id,
  178. 'title' => $value['name'],
  179. 'sort' => $arr_count - $key,
  180. 'index_code' => $value['indexCode'],
  181. ];
  182. $result = $mineService->add($params);
  183. $mine_id = $result->id;
  184. $arr[$key]['children'] = array_values(self::saveTree($regions, $mine_id, $value['indexCode']));
  185. if (count($arr[$key]['children']) == 0) {
  186. unset($arr[$key]['children']);
  187. }
  188. }
  189. }
  190. return array_values($arr);
  191. }
  192. /**
  193. * 获取区域监控列表
  194. * @return bool|mixed|string
  195. */
  196. public function getCamerasList()
  197. {
  198. if (!Input::has('indexCode')) {
  199. return $this->error(1, '缺少必要参数');
  200. }
  201. $url = $this->artemis . '/api/resource/v1/regions/regionIndexCode/cameras';
  202. //请求参数
  203. $params = [];
  204. $params['regionIndexCode'] = Input::get('indexCode');
  205. // $params['pageNo'] = $request->has('pageNo') ? intval($request->input('pageNo')) : 1;
  206. // $params['pageSize'] = $request->has('pageSize') ? intval($request->input('pageSize')) : 1000;
  207. $params['pageNo'] = 1;
  208. $params['pageSize'] = 1000;
  209. $this->sign = $this->get_sign($url);
  210. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  211. $result = json_decode($result, true);
  212. return $result;
  213. }
  214. //查询区域列表v2
  215. public function getMineInfo($mine_name)
  216. {
  217. if (!Input::has('indexCode')) {
  218. return $this->error(1, '缺少必要参数');
  219. }
  220. $url = $this->artemis . '/api/irds/v2/region/nodesByParams';
  221. //请求参数
  222. $params = [];
  223. $params['resourceType'] = 'region';
  224. $params['pageNo'] = 1;
  225. $params['pageSize'] = 1000;
  226. $params['regionName'] = $mine_name;
  227. $this->sign = $this->get_sign($url);
  228. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  229. $result = json_decode($result, true);
  230. if(isset($result['data']['list'][0]['updateTime'])){
  231. $mine_update_time = strtotime($result['data']['list'][0]['updateTime']);
  232. $mine_update_time = number_format((time() - $mine_update_time)/(60*60*24),2);
  233. if($mine_update_time < 1){
  234. return true;
  235. }else{
  236. return false;
  237. }
  238. }else{
  239. return false;
  240. }
  241. }
  242. public function getCameraStatus($indexCode){
  243. $url = $this->artemis . '/api/nms/v1/online/camera/get';
  244. $params = [];
  245. $params['regionId'] = 'root000000';
  246. $params['includeSubNode'] = '1';
  247. $params['indexCodes'] = [$indexCode];
  248. // $params['status'] = '1';
  249. $params['pageNo'] = 1;
  250. $params['pageSize'] = 20;
  251. $this->sign = $this->get_sign($url);
  252. $result_status = $this->curlPost($this->pre_url . $url, json_encode($params));
  253. $result_status = json_decode($result_status, true);
  254. if(isset($result_status['data']['list'][0]['online']) && $result_status['data']['list'][0]['online'] == 0){
  255. return 2;//离线
  256. }else{
  257. return 1;//在线
  258. }
  259. }
  260. //洗选执法记录仪
  261. public function getWssCameraUrl(){
  262. if (!Input::has('cameraIndexCode')) {
  263. return $this->error(1, '缺少必要参数');
  264. }
  265. $parent_id = Input::get('parent_id');
  266. $protocol = Input::get('protocol', 'hls');
  267. $streamType = Input::get('streamType', 1);
  268. $type = Input::get('type', '');
  269. $url = $this->artemis . '/api/video/v2/cameras/previewURLs';
  270. // $cameras_info = json_decode($this->getCamerasInfo(Input::all()), true);
  271. //请求参数
  272. $params = [];
  273. // $params['regionIndexCode'] = $request->input('regionIndexCode');
  274. $params['cameraIndexCode'] = Input::get('cameraIndexCode');
  275. $params['streamType'] = $streamType; //0主码流 1子码流 2第三码流
  276. if($type == 'pc'){
  277. $params['protocol'] = 'ws';
  278. }else{
  279. $params['protocol'] = 'wss';
  280. }
  281. $params['transmode'] = 1; //0:UDP 1:TCP
  282. $params['expand'] = 'streamform=rtp';
  283. $this->sign = $this->get_sign($url);
  284. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  285. $result = json_decode($result, true);
  286. if (isset($result['code']) && $result['code'] == 0 && $parent_id != 353) { // 将内网地址替换为外网地址,除了羊二
  287. $video_url = $result['data']['url'];
  288. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  289. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  290. $result['data']['url'] = str_replace($res, $res_n, $video_url);
  291. }
  292. return $result;
  293. }
  294. //鹰骏一矿ws
  295. public function getWsCameraUrl(){
  296. if (!Input::has('cameraIndexCode')) {
  297. return $this->error(1, '缺少必要参数');
  298. }
  299. $parent_id = Input::get('parent_id');
  300. $protocol = Input::get('protocol', 'hls');
  301. $streamType = Input::get('streamType', 1);
  302. $url = $this->artemis . '/api/video/v2/cameras/previewURLs';
  303. // $cameras_info = json_decode($this->getCamerasInfo(Input::all()), true);
  304. //请求参数
  305. $params = [];
  306. // $params['regionIndexCode'] = $request->input('regionIndexCode');
  307. $params['cameraIndexCode'] = Input::get('cameraIndexCode');
  308. $params['streamType'] = $streamType; //0主码流 1子码流 2第三码流
  309. $params['protocol'] = 'ws';
  310. $params['transmode'] = 1; //0:UDP 1:TCP
  311. $params['expand'] = 'streamform=rtp';
  312. $this->sign = $this->get_sign($url);
  313. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  314. $result = json_decode($result, true);
  315. if (isset($result['code']) && $result['code'] == 0 && $parent_id != 353) { // 将内网地址替换为外网地址,除了羊二
  316. $video_url = $result['data']['url'];
  317. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  318. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  319. $result['data']['url'] = str_replace($res, $res_n, $video_url);
  320. }
  321. return $result;
  322. }
  323. //洗选执法记录仪对讲
  324. public function getHikTalkUrl(){
  325. if (!Input::has('cameraIndexCode')) {
  326. return $this->error(1, '缺少必要参数');
  327. }
  328. $parent_id = Input::get('parent_id');
  329. $protocol = Input::get('protocol', 'hls');
  330. $streamType = Input::get('streamType', 1);
  331. $url = $this->artemis . '/api/video/v1/cameras/talkURLs';
  332. // $cameras_info = json_decode($this->getCamerasInfo(Input::all()), true);
  333. //请求参数
  334. $params = [];
  335. // $params['regionIndexCode'] = $request->input('regionIndexCode');
  336. $params['cameraIndexCode'] = Input::get('cameraIndexCode');
  337. $params['transmode'] = 1; //0:UDP 1:TCP
  338. $params['expand'] = 'streamform=ps';
  339. $params['protocol'] = 'wss';
  340. $this->sign = $this->get_sign($url);
  341. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  342. $result = json_decode($result, true);
  343. if (isset($result['code']) && $result['code'] == 0 && $parent_id != 353) { // 将内网地址替换为外网地址,除了羊二
  344. $video_url = $result['data']['url'];
  345. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  346. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  347. $result['data']['url'] = str_replace($res, $res_n, $video_url);
  348. }
  349. return $result;
  350. }
  351. /**
  352. * 获取摄像头码流url
  353. * @return array|mixed
  354. */
  355. public function getCamerasUrl()
  356. {
  357. if (!Input::has('cameraIndexCode')) {
  358. return $this->error(1, '缺少必要参数');
  359. }
  360. $parent_id = Input::get('parent_id');
  361. $protocol = Input::get('protocol', 'hls');
  362. $streamType = Input::get('streamType', 1);
  363. $url = $this->artemis . '/api/video/v1/cameras/previewURLs';
  364. // $cameras_info = json_decode($this->getCamerasInfo(Input::all()), true);
  365. //请求参数
  366. $params = [];
  367. // $params['regionIndexCode'] = $request->input('regionIndexCode');
  368. $params['cameraIndexCode'] = Input::get('cameraIndexCode');
  369. $params['streamType'] = $streamType; //0主码流 1子码流 2第三码流
  370. $params['protocol'] = $protocol;
  371. $params['transmode'] = 1; //0:UDP 1:TCP
  372. $params['expand'] = 'transcode=1&systemformat=ps&videotype=h264';
  373. $this->sign = $this->get_sign($url);
  374. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  375. $result = json_decode($result, true);
  376. if (isset($result['code']) && $result['code'] == 0 && $parent_id != 353) { // 将内网地址替换为外网地址,除了羊二
  377. $video_url = $result['data']['url'];
  378. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  379. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  380. $result['data']['url'] = str_replace($res, $res_n, $video_url);
  381. }
  382. return $result;
  383. }
  384. /**
  385. * 获取摄像头详情
  386. * @param array $data
  387. * @return array|bool|string
  388. */
  389. public function getCamerasInfo($data)
  390. {
  391. $url = $this->artemis . '/api/resource/v1/cameras/indexCode';
  392. //请求参数
  393. $params = [];
  394. $params['cameraIndexCode'] = $data['cameraIndexCode'];
  395. $this->sign = $this->get_sign($url);
  396. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  397. return $result;
  398. }
  399. //获取编码设备信息
  400. public function getTranscodeInfo()
  401. {
  402. $url = $this->artemis . '/api/resource/v1/encodeDevice/get';
  403. //请求参数
  404. $params = [];
  405. $params['pageNo'] = 1;
  406. $params['pageSize'] = 1;
  407. $this->sign = $this->get_sign($url);
  408. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  409. return $result;
  410. }
  411. //根据区域获取下级编码设备列表
  412. public function getTest()
  413. {
  414. $url = $this->artemis . '/api/resource/v1/encodeDevice/subResources';
  415. //请求参数
  416. $params = [];
  417. $params['pageNo'] = 1;
  418. $params['pageSize'] = 1000;
  419. $params['regionIndexCode'] = Input::get('indexCode');
  420. $this->sign = $this->get_sign($url);
  421. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  422. $result = json_decode($result, true);
  423. return $result;
  424. }
  425. //获取编码设备列表
  426. public function getTranscodeList()
  427. {
  428. $url = $this->artemis . '/api/resource/v1/encodeDevice/subResources';
  429. //请求参数
  430. $params['regionIndexCode'] = 'root000000';
  431. $params['pageNo'] = 1;
  432. $params['pageSize'] = 100;
  433. $this->sign = $this->get_sign($url);
  434. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  435. $result = json_decode($result, true);
  436. return $result;
  437. }
  438. public function getRegionsInfo()
  439. {
  440. $url = $this->artemis . '/api/resource/v1/region/regionCatalog/regionInfo';
  441. //请求参数
  442. $params = [];
  443. $indexCodes = Input::get('indexCodes');
  444. $params['indexCodes'] = $indexCodes;
  445. $this->sign = $this->get_sign($url);
  446. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  447. $result = json_decode($result, true);
  448. // if (isset($result['code']) && $result['code'] == 0) {
  449. // }
  450. return $result;
  451. }
  452. public function getPlaybackRtsp(){
  453. $result['status'] = true;
  454. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  455. $camera_id = Input::get('camera_id');
  456. $start_time = Input::get('start_time');
  457. $end_time = Input::get('end_time');
  458. $query = CameraList::where('id', $camera_id)->first();
  459. // $url = $this->artemis.'/api/video/v2/cameras/playbackURLs';
  460. // $params['cameraIndexCode'] = $query->index_code;
  461. // $params['recordLocation'] = 0;
  462. // $params['protocol'] = 'rtsp';//rtsp
  463. // $params['transmode'] = 0;
  464. // $params['beginTime'] = $start_time;
  465. // $params['endTime'] = $end_time;
  466. // $params['uuid'] = '';
  467. // $params['expand'] = 'transcode=0';
  468. // $params['streamform'] = 'ps';
  469. // $params['lockType'] = 0;
  470. $url = $this->artemis.'/api/video/v1/cameras/playbackURLs';
  471. $params['cameraIndexCode'] = $query->index_code;
  472. $params['recordLocation'] = 0;
  473. $params['protocol'] = 'rtsp';//rtsp
  474. // $params['transmode'] = 0;
  475. $params['beginTime'] = $start_time;
  476. $params['endTime'] = $end_time;
  477. // $params['uuid'] = '';
  478. // $params['expand'] = 'streamform=ps';
  479. $params['streamType'] = 1; //0主码流 1子码流 2第三码流
  480. $params['transmode'] = 1; //0:UDP 1:TCP
  481. $params['expand'] = 'transcode=1&systemformat=ps&videotype=h264';
  482. $this->sign = $this->get_sign($url);
  483. $data = $this->curlPost($this->pre_url . $url, json_encode($params));
  484. $data = json_decode($data, true);
  485. if (isset($data['code']) && $data['code'] == 0) { // 将内网地址替换为外网地址
  486. $video_url = $data['data']['url'];
  487. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  488. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  489. $data['data']['url'] = str_replace($res, $res_n, $video_url);
  490. }
  491. if ($data['data']['url']) {
  492. $result['camera_id'] = $camera_id;
  493. $result['url'] = $data['data']['url'];
  494. } else {
  495. $result['status'] = false;
  496. $result['msg'] = ApiEnum::HK_REQUEST_FAIL;
  497. }
  498. return $result;
  499. }
  500. public function getPlaybackByEasy(){
  501. $result['status'] = true;
  502. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  503. $camera_id = Input::get('camera_id');
  504. $start_time = Input::get('start_time');
  505. $end_time = Input::get('end_time');
  506. $old_time = Input::get('time');
  507. $query = CameraList::where('id', $camera_id)->first();
  508. $degree = MineList::where('id', $query->mine_id)->value('degree');
  509. $degree = explode('|', $degree);
  510. $mine_list = MineList::whereIn('id', $degree)->select(['title'])->get()->toArray();
  511. $time = explode('T',$start_time);
  512. $time = substr($time[1],0,5);
  513. $time = str_replace(":","",$time);
  514. $path = '';
  515. $path = '/'.$mine_list[0]['title'];
  516. $new_camera_name = str_replace('-','',$query->camera_name);
  517. $new_camera_name = str_replace('#','号',$new_camera_name);
  518. $path .= '/' . $new_camera_name.'回放'.$time;
  519. $playback = DB::table('playback')
  520. ->where('camera_id',$camera_id)
  521. ->where('start_time',$old_time['start_time'])
  522. ->where('end_time',$old_time['end_time'])
  523. ->where('deleted_at',null)->get();
  524. //已有拉流id,直接返回拉流链接
  525. if(count($playback)>0){
  526. if($playback[0]->revert_back_id != 'NullId'){
  527. $result['data'] = [
  528. 'camera_id' => $camera_id,
  529. 'url' => env('EASY_DARWIN_JF_RTSP') . $path
  530. ];
  531. return $result;
  532. }
  533. }
  534. $url = $this->artemis.'/api/video/v1/cameras/playbackURLs';
  535. $params['cameraIndexCode'] = $query->index_code;
  536. $params['recordLocation'] = 0;
  537. $params['protocol'] = 'rtsp';//rtsp
  538. $params['beginTime'] = $start_time;
  539. $params['endTime'] = $end_time;
  540. $params['streamType'] = 1; //0主码流 1子码流 2第三码流
  541. $params['transmode'] = 1; //0:UDP 1:TCP
  542. $params['expand'] = 'streamform=rtp';
  543. $this->sign = $this->get_sign($url);
  544. $data = $this->curlPost($this->pre_url . $url, json_encode($params));
  545. $data = json_decode($data, true);
  546. if(!$data['data']['url']){//切换码流
  547. $params['streamType'] = 0;
  548. $this->sign = $this->get_sign($url);
  549. $data = $this->curlPost($this->pre_url . $url, json_encode($params));
  550. $data = json_decode($data, true);
  551. }
  552. if(!$data['data']['url']){
  553. $result['status'] = false;
  554. $result['msg'] = ApiEnum::HK_REQUEST_FAIL;
  555. return $result;
  556. }
  557. $data = [
  558. 'url' => $data['data']['url'].'?beginTime='.$start_time.'&endTime='.$end_time.'&playBackMode=1',
  559. 'customPath' => $path,
  560. ];
  561. //请求流媒体服务器拉流
  562. $curl = env('EASY_DARWIN_JF_URL') . CameraEnum::API_STREAM_START . '?' . http_build_query($data);
  563. $curl_res = curl_request($curl);
  564. if(strpos($curl_res,' ')){
  565. $result['status'] = false;
  566. $result['msg'] = ApiEnum::EASY_DAWIN_REQUEST_FAIL;
  567. return $result;
  568. }
  569. //更新拉流id
  570. // CameraList::where('id', $camera_id)->update(
  571. // [
  572. // 'revert_back_id' => trim($curl_res, '"'),
  573. // ]
  574. // );
  575. if(count($playback)>0){
  576. $back_data['revert_back_id'] = trim($curl_res, '"');
  577. DB::table('playback')->where('id',$playback[0]->id)->update($back_data);
  578. }
  579. $result['data'] = [
  580. 'camera_id' => Input::get('camera_id'),
  581. 'url' => env('EASY_DARWIN_JF_RTSP') . $path
  582. ];
  583. return $result;
  584. }
  585. public function getPlaybackRtmp(){
  586. $camera_id = Input::get('camera_id');
  587. $start_time = Input::get('start_time');
  588. $end_time = Input::get('end_time');
  589. $stream_type = Input::get('stream_type');
  590. $query = CameraList::where('id', $camera_id)->first();
  591. // $url = $this->artemis.'/api/video/v2/cameras/playbackURLs';
  592. // $params['cameraIndexCode'] = $query->index_code;
  593. // $params['recordLocation'] = 0;
  594. // $params['protocol'] = 'rtsp';//rtsp
  595. // $params['transmode'] = 0;
  596. // $params['beginTime'] = $start_time;
  597. // $params['endTime'] = $end_time;
  598. // $params['uuid'] = '';
  599. // $params['expand'] = 'transcode=0';
  600. // $params['streamform'] = 'ps';
  601. // $params['lockType'] = 0;
  602. $url = $this->artemis.'/api/video/v1/cameras/playbackURLs';
  603. $params['cameraIndexCode'] = $query->index_code;
  604. $params['recordLocation'] = 0;
  605. $params['protocol'] = 'rtmp';//rtsp
  606. // $params['transmode'] = 0;
  607. $params['beginTime'] = $start_time;
  608. $params['endTime'] = $end_time;
  609. $params['streamType'] = $stream_type; //0主码流 1子码流 2第三码流
  610. $params['transmode'] = 1; //0:UDP 1:TCP
  611. $params['expand'] = 'transcode=1&systemformat=ps&videotype=h264';
  612. // $params['uuid'] = '';
  613. // $params['expand'] = 'streamform=ps';
  614. $this->sign = $this->get_sign($url);
  615. $data = $this->curlPost($this->pre_url . $url, json_encode($params));
  616. $data = json_decode($data, true);
  617. if (isset($data['code']) && $data['code'] == 0) { // 将内网地址替换为外网地址
  618. $video_url = $data['data']['url'].'?beginTime='.$start_time.'&endTime='.$end_time.'&playBackMode=1';
  619. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $video_url, $res); // 提取内网ip
  620. preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/i', $this->pre_url, $res_n); // 提取外网ip
  621. $data['data']['url'] = str_replace($res, $res_n, $video_url);
  622. }
  623. return $data;
  624. }
  625. //海康获取rtsp
  626. public function getHikRtsp(){
  627. $result['status'] = true;
  628. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  629. $query = CameraList::where('id',Input::get('camera_id'))->first();
  630. if (!$query) {
  631. $result['status'] = false;
  632. $result['msg'] = ApiEnum::NO_CAMERA_URL;
  633. return $result;
  634. }
  635. $degree = MineList::where('id', $query->mine_id)->value('degree');
  636. $mine_list = MineList::whereIn('id', explode('|', $degree))->select(['title'])->get()->toArray();
  637. $path = '';
  638. foreach ($mine_list as $key => $val) {
  639. $path .= '/' . $val['title'];
  640. }
  641. $new_camera_name = str_replace('-','',$query->camera_name);
  642. $new_camera_name = str_replace('#','号',$new_camera_name);
  643. $path .= '/' . $new_camera_name;
  644. if($query->code_stream == 2){
  645. $code_stream = 0;
  646. }else{
  647. $code_stream = 1;
  648. }
  649. $url = $this->artemis.'/api/video/v1/cameras/previewURLs';
  650. $params['cameraIndexCode'] = $query->index_code;
  651. $params['streamType'] = $code_stream; //0主码流 1子码流 2第三码流
  652. $params['protocol'] = 'rtsp';//rtsp
  653. $params['transmode'] = 1; //0:UDP 1:TCP
  654. $params['expand'] = 'streamform=rtp';
  655. $this->sign = $this->get_sign($url);
  656. $rtsp = $this->curlPost($this->pre_url . $url, json_encode($params));
  657. $rtsp = json_decode($rtsp, true);
  658. if($rtsp['data']['url']){
  659. //访问记录
  660. $log['mine_id'] = $query->mine_id;
  661. $log['camera_id'] = Input::get('camera_id');
  662. $log['log'] = '海康接口返回rtsp成功';
  663. $log['status'] = 0;//正常
  664. $log['created_at'] = date('Y-m-d H:i:s');
  665. $log['updated_at'] = date('Y-m-d H:i:s');
  666. DB::table('log')->insert($log);
  667. }else{
  668. //访问记录
  669. $log['mine_id'] = $query->mine_id;
  670. $log['camera_id'] = Input::get('camera_id');
  671. $log['log'] = '海康接口返回rtsp失败';
  672. $log['status'] = 1;//异常
  673. $log['created_at'] = date('Y-m-d H:i:s');
  674. $log['updated_at'] = date('Y-m-d H:i:s');
  675. DB::table('log')->insert($log);
  676. }
  677. $ffmpeg_rtsp = $rtsp['data']['url'];
  678. $rtsp['data']['url'] = substr_replace($rtsp['data']['url'],env('NMJT_IP'),7,12);
  679. $result['data'] = [
  680. 'camera_id' => Input::get('camera_id'),
  681. 'url' => $rtsp['data']['url']
  682. ];
  683. //查询是否存在封面图
  684. $cover_picture = CameraList::where('id', Input::get('camera_id'))->value('cover_picture');
  685. if (!$cover_picture) {
  686. register_shutdown_function(array($this, "getFirstPicture"),$path,$ffmpeg_rtsp);
  687. }
  688. return $result;
  689. }
  690. //获取摄像头质量
  691. public function checkCameraQuality(){
  692. if (!Input::has('indexCode')) {
  693. return $this->error(1, '缺少必要参数');
  694. }
  695. $url = $this->artemis . '/api/nms/v1/vqd/list';
  696. //请求参数
  697. $params = [];
  698. $params['indexCodes'] = [Input::get('indexCode')];
  699. $params['pageNo'] = 1;
  700. $params['pageSize'] = 20;
  701. $this->sign = $this->get_sign($url);
  702. $result = $this->curlPost($this->pre_url . $url, json_encode($params));
  703. $result = json_decode($result, true);
  704. return $result;
  705. }
  706. //海康获取rtmp
  707. public function getHikHls(){
  708. $result['status'] = true;
  709. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  710. $query = CameraList::where('id',Input::get('camera_id'))->first();
  711. if (!$query) {
  712. $result['status'] = false;
  713. $result['msg'] = ApiEnum::NO_CAMERA_URL;
  714. return $result;
  715. }
  716. $degree = MineList::where('id', $query->mine_id)->value('degree');
  717. $mine_list = MineList::whereIn('id', explode('|', $degree))->select(['title'])->get()->toArray();
  718. $path = '';
  719. foreach ($mine_list as $key => $val) {
  720. $path .= '/' . $val['title'];
  721. }
  722. $new_camera_name = str_replace('-','',$query->camera_name);
  723. $new_camera_name = str_replace('#','号',$new_camera_name);
  724. $path .= '/' . $new_camera_name;
  725. if($query->code_stream == 2){
  726. $code_stream = 0;
  727. }else{
  728. $code_stream = 1;
  729. }
  730. $url = $this->artemis.'/api/video/v1/cameras/previewURLs';
  731. $params['cameraIndexCode'] = $query->index_code;
  732. $params['streamType'] = 0; //0主码流 1子码流 2第三码流
  733. $params['protocol'] = 'ws';//rtmp
  734. $params['transmode'] = 1; //0:UDP 1:TCP
  735. $params['expand'] = 'streamform=rtp';
  736. $this->sign = $this->get_sign($url);
  737. $rtmp = $this->curlPost($this->pre_url . $url, json_encode($params));
  738. $rtmp = json_decode($rtmp, true);
  739. if($rtmp['data']['url']){
  740. //访问记录
  741. $log['mine_id'] = $query->mine_id;
  742. $log['camera_id'] = Input::get('camera_id');
  743. $log['log'] = '海康接口返回rtsp成功';
  744. $log['status'] = 0;//正常
  745. $log['created_at'] = date('Y-m-d H:i:s');
  746. $log['updated_at'] = date('Y-m-d H:i:s');
  747. DB::table('log')->insert($log);
  748. }else{
  749. //访问记录
  750. $log['mine_id'] = $query->mine_id;
  751. $log['camera_id'] = Input::get('camera_id');
  752. $log['log'] = '海康接口返回rtsp失败';
  753. $log['status'] = 1;//异常
  754. $log['created_at'] = date('Y-m-d H:i:s');
  755. $log['updated_at'] = date('Y-m-d H:i:s');
  756. DB::table('log')->insert($log);
  757. }
  758. $ffmpeg_rtmp = $rtmp['data']['url'];
  759. $pattern = '/^(ws:\/\/[^\/]+)/';
  760. if (preg_match($pattern, $ffmpeg_rtmp, $matches)) {
  761. $protocolHost = $matches[1];
  762. $rtmp['data']['url'] = str_replace($protocolHost, env('HK_HLS_JF'), $ffmpeg_rtmp);
  763. } else {
  764. $rtmp['data']['url'] = substr_replace($rtmp['data']['url'],env('HK_HLS_JF'),0,21);
  765. }
  766. $result['data'] = [
  767. 'camera_id' => Input::get('camera_id'),
  768. 'url' => $rtmp['data']['url']
  769. ];
  770. //查询是否存在封面图
  771. $cover_picture = CameraList::where('id', Input::get('camera_id'))->value('cover_picture');
  772. if (!$cover_picture) {
  773. // register_shutdown_function(array($this, "getFirstPicture"),$path,$ffmpeg_rtmp);
  774. $this->getPictureByHk($query);
  775. }
  776. return $result;
  777. }
  778. //海康ws协议获取url
  779. public function getHikWs(){
  780. $result['status'] = true;
  781. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  782. $query = CameraList::where('id',Input::get('camera_id'))->first();
  783. if (!$query) {
  784. $result['status'] = false;
  785. $result['msg'] = ApiEnum::NO_CAMERA_URL;
  786. return $result;
  787. }
  788. $degree = MineList::where('id', $query->mine_id)->value('degree');
  789. $mine_list = MineList::whereIn('id', explode('|', $degree))->select(['title'])->get()->toArray();
  790. $path = '';
  791. foreach ($mine_list as $key => $val) {
  792. $path .= '/' . $val['title'];
  793. }
  794. $new_camera_name = str_replace('-','',$query->camera_name);
  795. $new_camera_name = str_replace('#','号',$new_camera_name);
  796. $path .= '/' . $new_camera_name;
  797. if($query->code_stream == 2){
  798. $code_stream = 0;
  799. }else{
  800. $code_stream = 1;
  801. }
  802. $url = $this->artemis.'/api/video/v1/cameras/previewURLs';
  803. $params['cameraIndexCode'] = $query->index_code;
  804. $params['streamType'] = 0; //0主码流 1子码流 2第三码流
  805. $params['protocol'] = 'ws';//rtmp
  806. $params['transmode'] = 1; //0:UDP 1:TCP
  807. $params['expand'] = 'streamform=rtp';
  808. $this->sign = $this->get_sign($url);
  809. $rtmp = $this->curlPost($this->pre_url . $url, json_encode($params));
  810. $rtmp = json_decode($rtmp, true);
  811. if($rtmp['data']['url']){
  812. //访问记录
  813. $log['mine_id'] = $query->mine_id;
  814. $log['camera_id'] = Input::get('camera_id');
  815. $log['log'] = '海康接口返回rtsp成功';
  816. $log['status'] = 0;//正常
  817. $log['created_at'] = date('Y-m-d H:i:s');
  818. $log['updated_at'] = date('Y-m-d H:i:s');
  819. DB::table('log')->insert($log);
  820. }else{
  821. //访问记录
  822. $log['mine_id'] = $query->mine_id;
  823. $log['camera_id'] = Input::get('camera_id');
  824. $log['log'] = '海康接口返回rtsp失败';
  825. $log['status'] = 1;//异常
  826. $log['created_at'] = date('Y-m-d H:i:s');
  827. $log['updated_at'] = date('Y-m-d H:i:s');
  828. DB::table('log')->insert($log);
  829. }
  830. $ffmpeg_rtmp = $rtmp['data']['url'];
  831. $rtmp['data']['url'] = substr_replace($rtmp['data']['url'],env('HK_HLS_JF'),0,20);
  832. $result['data'] = [
  833. 'camera_id' => Input::get('camera_id'),
  834. 'url' => $rtmp['data']['url']
  835. ];
  836. //查询是否存在封面图
  837. $cover_picture = CameraList::where('id', Input::get('camera_id'))->value('cover_picture');
  838. if (!$cover_picture) {
  839. // register_shutdown_function(array($this, "getFirstPicture"),$path,$ffmpeg_rtmp);
  840. $this->getPictureByHk($query);
  841. }
  842. return $result;
  843. }
  844. //宁煤通过海康接口获取首桢图片
  845. public function getPictureByHk($query){
  846. $url = $this->artemis.'/api/video/v1/manualCapture';
  847. $params['cameraIndexCode'] = $query->index_code;
  848. $this->sign = $this->get_sign($url);
  849. $picture = $this->curlPost($this->pre_url . $url, json_encode($params));
  850. $picture = json_decode($picture, true);
  851. if(isset($picture['data']['picUrl'])){
  852. if (!is_dir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH.'/img/' )) {
  853. mkdir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH.'/img/', 0777, true);
  854. }
  855. $path = '/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH.'/img/';
  856. $cms = new CameraServices();
  857. $file_name = $cms->downloadFile($picture['data']['picUrl'],$path);
  858. //判断图片是否存在
  859. $picture_exists = file_exists($path . '/' . $file_name);
  860. if ($picture_exists) {
  861. //上传图片到oss并更新数据库
  862. $picture_path = $cms->uploadOssFile($file_name, $path);
  863. CameraList::where('id',$query->id)->update(['cover_picture' => $picture_path]);
  864. }
  865. }
  866. }
  867. //宁煤集团获取rtsp流后获取首帧图片
  868. public function getFirstPicture($path,$ffmpeg_rtsp){
  869. if (!is_dir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path)) {
  870. mkdir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path, 0777, true);
  871. }
  872. // dd($result_td['content'][0]['url']);
  873. $exec = 'nohup /usr/bin/ffmpeg -i "' . $ffmpeg_rtsp . '" -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 &';
  874. shell_exec($exec);
  875. //sleep10秒生成文件
  876. $i = 1;
  877. while ($i <= 10) {
  878. //判断m3u8文件是否存在
  879. $file_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . CameraEnum::M3U8_FILE_NAME);
  880. //判断ts文件是否存在
  881. $ts_exists = glob(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . CameraEnum::TS_FILE_SUFFIX);
  882. if ($file_exists && $ts_exists) {
  883. //获取第一帧作为封面图
  884. $file_name = time() . CameraEnum::COVER_PICTURE_NAME;
  885. $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;
  886. exec($cover_exec);
  887. //判断图片是否存在
  888. $picture_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . $file_name);
  889. if ($picture_exists) {
  890. $cms = new CameraServices();
  891. //上传图片到oss并更新数据库
  892. $picture_path = $cms->uploadOssFile($file_name, public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/');
  893. CameraList::where('id', Input::get('camera_id'))->update(['cover_picture' => $picture_path]);
  894. }
  895. } else {
  896. sleep(1);
  897. }
  898. $i++;
  899. }
  900. }
  901. //海康easy_drawin获取rtsp并推流
  902. public function getRtspByCameraId(){
  903. $result['status'] = true;
  904. $result['msg'] = ApiEnum::RETURN_SUCCESS;
  905. $query = CameraList::where('id',Input::get('camera_id'))->first();
  906. if (!$query) {
  907. $result['status'] = false;
  908. $result['msg'] = ApiEnum::NO_CAMERA_URL;
  909. return $result;
  910. }
  911. $degree = MineList::where('id', $query->mine_id)->value('degree');
  912. $mine_list = MineList::whereIn('id', explode('|', $degree))->select(['title'])->get()->toArray();
  913. $path = '';
  914. // foreach ($mine_list as $key => $val) {
  915. // $path .= '/' . $val['title'];
  916. // }
  917. $path = '/'.$mine_list[0]['title'];
  918. $new_camera_name = str_replace('-','',$query->camera_name);
  919. $new_camera_name = str_replace('#','号',$new_camera_name);
  920. $path .= '/' . $new_camera_name;
  921. //标记摄像头为在线状态
  922. CameraList::where('id', Input::get('camera_id'))->update(['camera_status' => CameraEnum::CAMERA_STATUS_ONLINE]);
  923. //已有拉流id,直接返回拉流链接
  924. if($query->revert_id != 'NullId'){
  925. $result['data'] = [
  926. 'camera_id' => Input::get('camera_id'),
  927. 'url' => env('EASY_DARWIN_JF_RTSP') . $path
  928. ];
  929. return $result;
  930. }
  931. if($query->code_stream == 2){
  932. $code_stream = 0;
  933. }else{
  934. $code_stream = 1;
  935. }
  936. $url = $this->artemis.'/api/video/v1/cameras/previewURLs';
  937. $params['cameraIndexCode'] = $query->index_code;
  938. $params['streamType'] = $code_stream; //0主码流 1子码流 2第三码流
  939. $params['protocol'] = 'rtsp';
  940. $params['transmode'] = 1; //0:UDP 1:TCP
  941. $params['expand'] = 'streamform=rtp';
  942. $this->sign = $this->get_sign($url);
  943. $rtsp = $this->curlPost($this->pre_url . $url, json_encode($params));
  944. $rtsp = json_decode($rtsp, true);
  945. $data = [
  946. 'url' => $rtsp['data']['url'],
  947. 'customPath' => $path,
  948. ];
  949. // dd($data);
  950. Log::info('请求流媒体服务器参数------------');
  951. Log::info($data);
  952. $curl = env('EASY_DARWIN_JF_URL') . CameraEnum::API_STREAM_START . '?' . http_build_query($data);
  953. //请求流媒体服务器拉流
  954. $curl_res = curl_request($curl);
  955. // DB::table('camera_list')->where('id',$camera_id)->update($res);
  956. // dd($res);
  957. Log::info('请求流媒体服务器result------------');
  958. Log::info($curl_res);
  959. if (strpos($curl_res,' ')) {
  960. //切换码流重新获取rtsp
  961. if($code_stream == 1){
  962. $code_stream = 0;
  963. }else{
  964. $code_stream = 1;
  965. }
  966. $params['streamType'] = $code_stream; //0主码流 1子码流 2第三码流
  967. $rtsp = $this->curlPost($this->pre_url . $url, json_encode($params));
  968. $rtsp = json_decode($rtsp, true);
  969. $data = [
  970. 'url' => $rtsp['data']['url'],
  971. 'customPath' => $path,
  972. ];
  973. // dd($data);
  974. Log::info('请求流媒体服务器参数------------');
  975. Log::info($data);
  976. $curl = env('EASY_DARWIN_JF_URL') . CameraEnum::API_STREAM_START . '?' . http_build_query($data);
  977. //请求流媒体服务器拉流
  978. $curl_res = curl_request($curl);
  979. if(strpos($curl_res,' ')){
  980. //标记摄像头为异常状态
  981. CameraList::where('id', Input::get('camera_id'))->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]);
  982. $result['status'] = false;
  983. $result['msg'] = ApiEnum::EASY_DAWIN_REQUEST_FAIL;
  984. return $result;
  985. }
  986. }
  987. //更新拉流id
  988. CameraList::where('id', Input::get('camera_id'))->update(
  989. [
  990. 'revert_id' => trim($curl_res, '"'),
  991. 'updated_at' => date('Y-m-d H:i:s'),
  992. ]
  993. );
  994. $result['data'] = [
  995. 'camera_id' => Input::get('camera_id'),
  996. 'url' => env('EASY_DARWIN_JF_RTSP') . $path
  997. ];
  998. //查询是否存在封面图
  999. $cover_picture = CameraList::where('id', Input::get('camera_id'))->value('cover_picture');
  1000. if (!$cover_picture) {
  1001. if (!is_dir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path)) {
  1002. mkdir('/www/wwwroot/video.nxjiewei.com/public/' . CameraEnum::M3U8_FILE_PATH . '/' . $path, 0777, true);
  1003. }
  1004. // dd($result_td['content'][0]['url']);
  1005. $exec = 'nohup /usr/bin/ffmpeg -i "' . $rtsp['data']['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 &';
  1006. shell_exec($exec);
  1007. //sleep10秒生成文件
  1008. $i = 1;
  1009. while ($i <= 10) {
  1010. //判断m3u8文件是否存在
  1011. $file_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . CameraEnum::M3U8_FILE_NAME);
  1012. //判断ts文件是否存在
  1013. $ts_exists = glob(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . CameraEnum::TS_FILE_SUFFIX);
  1014. if ($file_exists && $ts_exists) {
  1015. //获取第一帧作为封面图
  1016. $file_name = time() . CameraEnum::COVER_PICTURE_NAME;
  1017. $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;
  1018. exec($cover_exec);
  1019. //判断图片是否存在
  1020. $picture_exists = file_exists(public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/' . $file_name);
  1021. if ($picture_exists) {
  1022. $cms = new CameraServices();
  1023. //上传图片到oss并更新数据库
  1024. $picture_path = $cms->uploadOssFile($file_name, public_path() . '/' . CameraEnum::M3U8_FILE_PATH . $path . '/');
  1025. CameraList::where('id', Input::get('camera_id'))->update(['cover_picture' => $picture_path]);
  1026. }
  1027. return $result;
  1028. } else {
  1029. sleep(1);
  1030. }
  1031. $i++;
  1032. }
  1033. }else{
  1034. return $result;
  1035. }
  1036. //标记摄像头为异常状态
  1037. CameraList::where('id', Input::get('camera_id'))->update(['camera_status' => CameraEnum::CAMERA_STATUS_ERROR]);
  1038. $result['status'] = false;
  1039. $result['msg'] = ApiEnum::EASY_DAWIN_REQUEST_FAIL;
  1040. return $result;
  1041. }
  1042. /**
  1043. * 以appSecret为密钥,使用HmacSHA256算法对签名字符串生成消息摘要,对消息摘要使用BASE64算法生成签名(签名过程中的编码方式全为UTF-8)
  1044. */
  1045. protected function get_sign($url)
  1046. {
  1047. $sign_str = $this->get_sign_str($url); //签名字符串
  1048. $priKey = $this->app_secret;
  1049. $sign = hash_hmac('sha256', $sign_str, $priKey, true); //生成消息摘要
  1050. $result = base64_encode($sign);
  1051. return $result;
  1052. }
  1053. /**
  1054. * 生成签名
  1055. * @param $url
  1056. * @return string
  1057. */
  1058. protected function get_sign_str($url)
  1059. {
  1060. // $next = "\n";
  1061. $next = "\n";
  1062. $str = "POST" . $next . '*/*' . $next . 'application/json' . $next;
  1063. $str .= "x-ca-key:" . $this->app_key . $next;
  1064. $str .= "x-ca-timestamp:" . $this->time . $next;
  1065. $str .= $url;
  1066. return $str;
  1067. }
  1068. /**
  1069. * 发送请求
  1070. * @param string $url
  1071. * @param string $postData
  1072. * @param array $options
  1073. * @return bool|string
  1074. */
  1075. public function curlPost($url = '', $postData = '', $options = array())
  1076. {
  1077. if (is_array($postData)) {
  1078. $postData = http_build_query($postData);
  1079. }
  1080. $ch = curl_init();
  1081. curl_setopt($ch, CURLOPT_URL, $url);
  1082. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  1083. curl_setopt($ch, CURLOPT_POST, 1);
  1084. curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
  1085. curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
  1086. curl_setopt_array($ch, array(
  1087. CURLOPT_HTTPHEADER => array(
  1088. "Accept:" . '*/*',
  1089. "Content-Type:" . 'application/json',
  1090. "x-Ca-Key:" . $this->app_key,
  1091. "X-Ca-Signature:" . $this->sign,
  1092. "X-Ca-Timestamp:" . $this->time,
  1093. "X-Ca-Signature-Headers:" . "x-ca-key,x-ca-timestamp",
  1094. )
  1095. ));
  1096. //https请求 不验证证书和host
  1097. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  1098. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  1099. $data = curl_exec($ch);
  1100. curl_close($ch);
  1101. return $data;
  1102. }
  1103. }