h52dgp.html 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. <!DOCTYPE html>
  2. <html lang=zh-CN>
  3. <head>
  4. <meta charset="utf-8" />
  5. <meta name="viewport"
  6. content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
  7. <title>监控详情页</title>
  8. <link href="https://unpkg.com/video.js@7.10.2/dist/video-js.min.css" rel="stylesheet" />
  9. <link rel="stylesheet" href="./font/iconfont.css" />
  10. <style type="text/css">
  11. body {
  12. margin: 0;
  13. background-color: #f3f3f3;
  14. }
  15. span.vjs-control-text {
  16. display: none;
  17. }
  18. /* iframe {
  19. width: 375px;
  20. height: 667px;
  21. background-color: #fff;
  22. box-sizing: content-box;
  23. border: none;
  24. } */
  25. .btn-box {
  26. margin-top: 20px;
  27. display: flex;
  28. flex-direction: row;
  29. justify-content: space-around;
  30. align-items: center;
  31. }
  32. .btn-container {
  33. position: relative;
  34. }
  35. .videoBtnPlay {
  36. position: absolute;
  37. height: 100px;
  38. width: 100px;
  39. top: 50%;
  40. left: 50%;
  41. transform: translate(-50%, -50%);
  42. }
  43. .more,
  44. .less {
  45. flex: 1
  46. }
  47. img {
  48. width: 100%;
  49. }
  50. .direc {
  51. width: 150px;
  52. height: 150px;
  53. background: url('https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/1.png');
  54. background-size: 100% auto;
  55. background-repeat: no-repeat;
  56. position: relative;
  57. display: flex;
  58. justify-content: center;
  59. align-items: center;
  60. }
  61. .direc div {
  62. width: 50px;
  63. height: 50px;
  64. position: absolute;
  65. }
  66. .photo {
  67. font-size: 30px;
  68. color: #4ec467;
  69. padding: 16px;
  70. }
  71. .top {
  72. top: 0;
  73. left: 50px
  74. }
  75. .bottom {
  76. bottom: 0;
  77. left: 50px
  78. }
  79. .left {
  80. left: 0;
  81. top: 50px
  82. }
  83. .right {
  84. right: 0;
  85. top: 50px
  86. }
  87. #box {
  88. height: 300px;
  89. width: 100%;
  90. background: #000;
  91. overflow: hidden;
  92. }
  93. #dialog {
  94. display: none;
  95. min-width: 200px;
  96. line-height: 80px;
  97. background: rgba(0, 0, 0, .8);
  98. color: #fff;
  99. text-align: center;
  100. position: absolute;
  101. left: 50%;
  102. margin-left: -100px;
  103. border-radius: 4px;
  104. z-index: 999;
  105. top: 50%;
  106. margin-top: -40px;
  107. }
  108. .imgBtn {
  109. position: absolute;
  110. width: 100%;
  111. padding: 10px;
  112. bottom: 0;
  113. left: 0;
  114. text-align: center;
  115. color: #338cd9;
  116. font-size: 16px;
  117. box-sizing: border-box;
  118. display: flex;
  119. justify-content: center;
  120. gap: 16px;
  121. }
  122. .imgBtn div {
  123. /* padding: 0 16px; */
  124. }
  125. .imgBtn img {
  126. display: inline-block;
  127. width: 20px;
  128. height: 20px;
  129. vertical-align: middle;
  130. margin-right: 2px;
  131. margin-bottom: 3px;
  132. }
  133. </style>
  134. </head>
  135. <body>
  136. <div class="btn-container">
  137. <div id="box"> </div>
  138. <div class="videoBtnPlay">
  139. <img src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/wxplayer.png" />
  140. </div>
  141. </div>
  142. <div id="dialog">
  143. </div>
  144. <div class="btn-box">
  145. <div class="more" ontouchstart="_configCamera('move', 8)" ontouchend="_stopConfigCamera()">
  146. <image src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/3.png" mode="widthFix">
  147. </image>
  148. </div>
  149. <div class="direc">
  150. <div class="top" ontouchstart="_configCamera('move', 0)" ontouchend="_stopConfigCamera()">
  151. </div>
  152. <div class="bottom" ontouchstart="_configCamera('move', 1)" ontouchend="_stopConfigCamera()">
  153. </div>
  154. <p class="photo yficonfont icon-paizhao-xianxing" ontouchstart="_configCamera('takephoto', '')">
  155. </p>
  156. <div class="left" ontouchstart="_configCamera('move', 2)" ontouchend="_stopConfigCamera()">
  157. </div>
  158. <div class="right" ontouchstart="_configCamera('move', 3)" ontouchend="_stopConfigCamera()">
  159. </div>
  160. </div>
  161. <div class="less" ontouchstart="_configCamera('move', 9)" ontouchend="_stopConfigCamera()">
  162. <image src="https://s3.hnyfwlw.com/webstaticimg/bigdata_app/image/monitor/2.png" mode="widthFix">
  163. </image>
  164. </div>
  165. </div>
  166. <div class="imgBtn">
  167. <div class="imgBtnCamrea"> <img src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/img_icon.png" />查看图片</div>
  168. <div class="imgBtnDgp"><img src="https://webstaticimg.oss-cn-hangzhou.aliyuncs.com/bigdata_app/img/img_icon.png" />查看光谱图片</div>
  169. </div>
  170. </body>
  171. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  172. <!-- 微信 JS-SDK 如果不需要兼容小程序,则无需引用此 JS 文件。 -->
  173. <!-- <script type="text/javascript" src="//res.wx.qq.com/open/js/jweixin-1.4.0.js"></script> -->
  174. <!-- uni 的 SDK -->
  175. <script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.1.5.2.js"></script>
  176. <script src="https://unpkg.com/video.js@7.10.2/dist/video.min.js"></script>
  177. <script type="module">
  178. import Player from './videoPlayer/videoPlay-js.js'
  179. const host = "http://218.28.198.186:10508"
  180. // 检测HLS支持
  181. function checkHLSSupport() {
  182. const video = document.createElement('video');
  183. return video.canPlayType('application/vnd.apple.mpegurl') !== '' ||
  184. video.canPlayType('application/x-mpegURL') !== '';
  185. }
  186. // 加载HLS.js库(如果需要)
  187. function loadHLSJS() {
  188. return new Promise((resolve, reject) => {
  189. if (window.Hls) {
  190. resolve();
  191. return;
  192. }
  193. const script = document.createElement('script');
  194. script.src = 'https://cdn.jsdelivr.net/npm/hls.js@latest';
  195. script.onload = () => {
  196. console.log('HLS.js加载完成,版本:', window.Hls.version);
  197. resolve();
  198. };
  199. script.onerror = () => {
  200. console.error('HLS.js加载失败');
  201. reject(new Error('HLS.js加载失败'));
  202. };
  203. document.head.appendChild(script);
  204. });
  205. }
  206. // 尝试使用HLS.js播放
  207. function tryHLSJSPlayer(videoSrc) {
  208. if (!window.Hls) {
  209. console.error('HLS.js未加载');
  210. return false;
  211. }
  212. if (!Hls.isSupported()) {
  213. console.error('浏览器不支持HLS.js');
  214. return false;
  215. }
  216. const video = document.getElementById('myPlayer');
  217. if (!video) {
  218. console.error('视频元素不存在');
  219. return false;
  220. }
  221. const hls = new Hls({
  222. debug: true,
  223. enableWorker: true,
  224. lowLatencyMode: true
  225. });
  226. hls.loadSource(videoSrc);
  227. hls.attachMedia(video);
  228. hls.on(Hls.Events.MANIFEST_PARSED, function() {
  229. console.log('HLS.js: 清单解析完成');
  230. video.play().catch(e => {
  231. console.error('HLS.js播放失败:', e);
  232. showError('HLS.js播放失败: ' + e.message);
  233. });
  234. });
  235. hls.on(Hls.Events.ERROR, function(event, data) {
  236. console.error('HLS.js错误:', event, data);
  237. if (data.fatal) {
  238. switch(data.type) {
  239. case Hls.ErrorTypes.NETWORK_ERROR:
  240. showError('网络错误,无法加载视频流');
  241. break;
  242. case Hls.ErrorTypes.MEDIA_ERROR:
  243. showError('媒体错误,视频格式可能不支持');
  244. break;
  245. default:
  246. showError('HLS播放器致命错误');
  247. break;
  248. }
  249. }
  250. });
  251. return true;
  252. }
  253. let player = null
  254. let stopTimer = 0
  255. // 更安全的URL参数解析
  256. function getUrlParam(name) {
  257. const urlParams = new URLSearchParams(window.location.search)
  258. return urlParams.get(name) || ''
  259. }
  260. var device_id = getUrlParam('device_id')
  261. var accessToken = getUrlParam('accessToken')
  262. var videoType = getUrlParam('videoType')
  263. var token = accessToken
  264. console.log('解析结果:', { device_id, accessToken, videoType })
  265. console.log('视频类型检查:', videoType, videoType === 'dgp')
  266. // 通用错误处理函数
  267. function showError(message, duration = 3000) {
  268. $('#dialog').html(message).stop().show(500).delay(duration).hide(500);
  269. $('.videoBtnPlay').show();
  270. }
  271. // 安全的JSON解析
  272. function safeParseJSON(str) {
  273. try {
  274. return JSON.parse(str);
  275. } catch(e) {
  276. console.warn('JSON解析失败,尝试eval:', e);
  277. try {
  278. return eval('(' + str + ')');
  279. } catch(e2) {
  280. console.error('数据解析完全失败:', e2);
  281. return null;
  282. }
  283. }
  284. }
  285. // 验证API响应
  286. function validateAPIResponse(res, apiName = 'API') {
  287. console.log(`${apiName}响应:`, res);
  288. if (!res) {
  289. console.error(`${apiName}响应为空`);
  290. return { valid: false, error: '服务器无响应' };
  291. }
  292. if (res.message && res.message !== '') {
  293. console.error(`${apiName}返回错误:`, res.message);
  294. return { valid: false, error: res.message };
  295. }
  296. if (!res.data) {
  297. console.error(`${apiName}返回数据为空`);
  298. return { valid: false, error: '返回数据为空' };
  299. }
  300. return { valid: true, data: res.data };
  301. }
  302. // 获取可用的视频源
  303. function getAvailableVideoSource(data, preferredType = 'hls') {
  304. const sources = {
  305. hls: data.hls,
  306. hlsHd: data.hlsHd,
  307. rtmp: data.rtmp,
  308. rtsp: data.rtsp
  309. };
  310. console.log('可用视频源:', sources);
  311. // 优先使用指定类型
  312. if (sources[preferredType] && sources[preferredType] !== 'undefined' && sources[preferredType] !== '') {
  313. return { source: sources[preferredType], type: preferredType };
  314. }
  315. // 按优先级查找可用源
  316. const priority = ['hls', 'hlsHd', 'rtmp', 'rtsp'];
  317. for (const type of priority) {
  318. if (sources[type] && sources[type] !== 'undefined' && sources[type] !== '') {
  319. return { source: sources[type], type: type };
  320. }
  321. }
  322. return { source: null, type: null };
  323. }
  324. // 检查设备状态
  325. function checkDeviceStatus() {
  326. console.log('检查设备状态...');
  327. $('#dialog').html('检查设备状态...').stop().show();
  328. return $.ajax({
  329. type: "POST",
  330. url: `${host}/api/api_gateway?method=device.device_manage.get_device_info`,
  331. data: {
  332. device_id: device_id,
  333. token: token
  334. },
  335. timeout: 5000
  336. }).then((res) => {
  337. console.log('设备状态响应:', res);
  338. if (res && res.message === '' && res.data) {
  339. const deviceInfo = typeof res.data === 'string' ? safeParseJSON(res.data) : res.data;
  340. console.log('设备信息:', deviceInfo);
  341. return deviceInfo;
  342. } else {
  343. throw new Error(res.message || '获取设备信息失败');
  344. }
  345. }).catch((error) => {
  346. console.error('设备状态检查失败:', error);
  347. showError('设备状态检查失败: ' + (error.message || '网络错误'));
  348. throw error;
  349. });
  350. }
  351. window._configCamera = configCamera;
  352. window._stopConfigCamera = stopConfigCamera;
  353. window._postPic = postPic;
  354. // 确保DOM加载完成后再执行jQuery操作
  355. $(document).ready(function() {
  356. // 初始化HLS支持
  357. if (!checkHLSSupport()) {
  358. console.log('浏览器不支持原生HLS,加载HLS.js');
  359. loadHLSJS().catch(e => {
  360. console.error('HLS.js加载失败:', e);
  361. });
  362. }
  363. if (videoType == 'dgp') {
  364. $('.imgBtnDgp').show()
  365. } else {
  366. $('.imgBtnDgp').hide()
  367. }
  368. $('.photo').click(() => {
  369. // 拍照功能
  370. })
  371. })
  372. function configCamera(ctrl, movenum) {
  373. if (ctrl == "takephoto") {
  374. if (player) {
  375. // 云联的拍照特殊处理
  376. player.screenshot('yunlianPlayer')
  377. } else {
  378. $('#dialog').html('拍照指令正在下发,请等待...').stop().show(50)
  379. let url =`${host}/api/api_gateway?method=camera.camera_manage.camera_takephoto`
  380. if (videoType == 'dgp') {
  381. url = `${host}/api/api_gateway?method=camera.camera_manage.multi_camera_takephoto`
  382. }
  383. $.ajax({
  384. type: "POST",
  385. url: url,
  386. data: {
  387. device_id: device_id,
  388. token
  389. }
  390. }).then((res) => {
  391. if (res.data == true) {
  392. $('#dialog').html('拍照成功').stop().show(500).delay(1000).hide(500)
  393. } else {
  394. $('#dialog').html(res.message).stop().show(500).delay(1000).hide(500)
  395. }
  396. });
  397. }
  398. } else {
  399. let url = `${host}/api/api_gateway?method=camera.camera_manage.ctrl_camera`
  400. let postData = {
  401. device_id: device_id,
  402. token
  403. }
  404. if (videoType == 'dgp') {
  405. url = `${host}/api/api_gateway?method=camera.camera_manage.multi_ctrl_camera`
  406. postData.ctrl = movenum
  407. } else {
  408. postData.ctrl = ctrl
  409. postData.movenum = movenum
  410. }
  411. //上下左右、放大、缩小
  412. $.ajax({
  413. type: "POST",
  414. url: url,
  415. data: postData
  416. }).then((res) => {
  417. $('#dialog').html('指令下发成功,请等待...').stop().show(500).delay(3000).hide(500)
  418. })
  419. }
  420. }
  421. function stopConfigCamera() {
  422. if (videoType == 'dgp') {
  423. if(stopTimer) clearTimeout(stopTimer)
  424. stopTimer = setTimeout(()=>{
  425. $.ajax({
  426. type: "POST",
  427. url: `${host}/api/api_gateway?method=camera.camera_manage.mulit_stop_move`,
  428. data: {
  429. device_id: device_id,
  430. token
  431. },
  432. });
  433. },3000)
  434. } else {
  435. $.ajax({
  436. type: "POST",
  437. url: `${host}/api/api_gateway?method=camera.camera_manage.ctrl_camera`,
  438. data: {
  439. device_id: device_id,
  440. ctrl: "stop",
  441. token
  442. },
  443. });
  444. }
  445. }
  446. function postPic(file) {
  447. let form = new FormData()
  448. form.append('img_file', file)
  449. form.append('device_id', device_id)
  450. form.append('token', token)
  451. $.ajax({
  452. type: "POST",
  453. url: `${host}/api/api_gateway?method=camera.camera_manage.save_camera_photo`,
  454. contentType: false,
  455. processData: false,
  456. data: form
  457. }).then((res) => {
  458. if (res.message == '') {
  459. $('#dialog').html('拍照成功').stop().show(500).delay(1500).hide(500)
  460. } else {
  461. $('#dialog').html(res.data.message).stop().show(500).delay(1500).hide(500)
  462. }
  463. });
  464. }
  465. async function initYunlianPlayer(videoURL) {
  466. var playHtml =
  467. `<div id="yunlianPlayer" style="width: 100%;height: 300px;overflow: hidden;"></div>`;
  468. $("#box").html(playHtml)
  469. player = new Player(['yunlianPlayer'], {
  470. playFileOver: () => {
  471. console.log('播放结束')
  472. },
  473. playError: (id, e) => {
  474. console.log('播放错误', id, e)
  475. },
  476. talkStart: () => {
  477. console.log('对讲开始')
  478. },
  479. runtimeInitializedCallBack: () => {
  480. console.log('播放器初始化完成')
  481. },
  482. captureCallback: (id, data) => {
  483. // console.log('截图返回的数据', data.buffer)
  484. const blob = new Blob([data], {
  485. type: 'image/jpeg'
  486. })
  487. _postPic(blob)
  488. }
  489. })
  490. await player.init()
  491. setTimeout(() => {
  492. player.play('yunlianPlayer', {
  493. streamURL: videoURL,
  494. channelId: '0',
  495. bitStream: '0',
  496. isLive: true
  497. })
  498. }, 1000)
  499. }
  500. $('.videoBtnPlay').click(function() {
  501. $('.videoBtnPlay').hide()
  502. console.log(videoType,'videoTypevideoType')
  503. // 显示加载提示
  504. $('#dialog').html('正在获取视频流...').stop().show();
  505. // 先检查设备状态(可选,如果API支持的话)
  506. // checkDeviceStatus().then(() => {
  507. if (videoType == 'dgp') {
  508. $.ajax({
  509. type: "POST",
  510. url: `${host}/api/api_gateway?method=camera.camera_manage.multi_addr_camera`,
  511. data: {
  512. device_id: device_id,
  513. token
  514. },
  515. timeout: 15000 // 15秒超时
  516. }).then((res) => {
  517. $('#dialog').hide(); // 隐藏加载提示
  518. const validation = validateAPIResponse(res, 'DGP视频流API');
  519. if (!validation.valid) {
  520. showError(validation.error);
  521. return;
  522. }
  523. let data = validation.data;
  524. if (typeof data == 'string') {
  525. data = safeParseJSON(data);
  526. if (!data) {
  527. showError('DGP数据解析失败');
  528. return;
  529. }
  530. }
  531. console.log('DGP解析后的数据:', data);
  532. // 获取可用的视频源(DGP优先使用rtmp)
  533. const videoSource = getAvailableVideoSource(data, 'rtmp');
  534. if (!videoSource.source) {
  535. console.error('DGP没有找到可用的视频源');
  536. showError('设备可能离线或未配置视频流,请检查设备状态');
  537. return;
  538. }
  539. console.log(`使用${videoSource.type}视频源:`, videoSource.source);
  540. console.log(`使用${videoSource.type}视频源:`, videoSource.source);
  541. const hlsHdSrc = videoSource.source;
  542. // 根据视频源类型选择合适的播放器
  543. if (videoSource.type === 'rtmp') {
  544. // RTMP流使用Flash播放器或转换为HLS
  545. console.log('检测到RTMP流,尝试使用备用播放方案');
  546. // 尝试查找HLS备用源
  547. const hlsBackup = getAvailableVideoSource(data, 'hls');
  548. if (hlsBackup.source) {
  549. console.log('使用HLS备用源:', hlsBackup.source);
  550. createVideoJSPlayer(hlsBackup.source, 'application/x-mpegURL');
  551. } else {
  552. // 如果没有HLS源,显示RTMP不支持的提示
  553. showError('当前设备使用RTMP流,浏览器不支持直接播放。请联系管理员配置HLS流。');
  554. }
  555. } else {
  556. // HLS/其他格式使用Video.js
  557. const mimeType = videoSource.type === 'hls' || videoSource.type === 'hlsHd'
  558. ? 'application/x-mpegURL'
  559. : 'video/mp4';
  560. createVideoJSPlayer(hlsHdSrc, mimeType);
  561. }
  562. }).catch((error) => {
  563. console.error('DGP视频请求失败:', error);
  564. showError('DGP网络请求失败: ' + (error.message || '请检查网络连接'));
  565. });
  566. // 创建Video.js播放器的通用函数
  567. function createVideoJSPlayer(videoSrc, mimeType) {
  568. console.log('创建播放器,源:', videoSrc, '类型:', mimeType);
  569. var playHtml =
  570. `<video id="myPlayer" poster='' controls playsInline webkit-playsinline style="width:100%; height:100%;"></video>`;
  571. $("#box").html(playHtml)
  572. // 如果是HLS格式且HLS.js可用,优先使用HLS.js
  573. if (mimeType === 'application/x-mpegURL' && window.Hls && Hls.isSupported()) {
  574. console.log('使用HLS.js播放器');
  575. if (tryHLSJSPlayer(videoSrc)) {
  576. return; // HLS.js成功初始化
  577. }
  578. }
  579. // 使用Video.js作为fallback
  580. console.log('使用Video.js播放器');
  581. var myVideo = videojs(`myPlayer`, {
  582. controls: true,
  583. autoplay: false,
  584. preload: 'metadata',
  585. sources: [{
  586. type: mimeType,
  587. src: videoSrc,
  588. }],
  589. html5: {
  590. hls: {
  591. enableLowInitialPlaylist: true,
  592. smoothQualityChange: true,
  593. overrideNative: false // 让HLS.js处理
  594. }
  595. }
  596. }, function onPlayerReady() {
  597. console.log('Video.js播放器准备完成');
  598. // 延迟播放,确保源加载完成
  599. setTimeout(() => {
  600. myVideo.play().catch(e => {
  601. console.error('Video.js播放失败:', e);
  602. showError('视频播放失败: ' + e.message);
  603. });
  604. }, 1000);
  605. });
  606. // 添加错误处理
  607. myVideo.on('error', function(e) {
  608. console.error('Video.js错误:', e, myVideo.error());
  609. const error = myVideo.error();
  610. let errorMsg = '视频播放出错';
  611. if (error) {
  612. switch(error.code) {
  613. case 1:
  614. errorMsg = '视频加载被中止';
  615. break;
  616. case 2:
  617. errorMsg = '网络错误导致视频下载失败,请检查网络连接';
  618. break;
  619. case 3:
  620. errorMsg = '视频解码失败,可能是格式不支持';
  621. break;
  622. case 4:
  623. errorMsg = '视频格式不支持。源: ' + videoSrc + ' 类型: ' + mimeType;
  624. // 如果Video.js失败,尝试原生播放器
  625. console.log('Video.js失败,尝试原生播放器');
  626. tryNativePlayer(videoSrc);
  627. return;
  628. default:
  629. errorMsg = '未知播放错误 (错误码: ' + error.code + ')';
  630. }
  631. }
  632. showError(errorMsg);
  633. });
  634. myVideo.on('play', function() {
  635. console.log('Video.js开始播放')
  636. });
  637. myVideo.on('loadstart', function() {
  638. console.log('Video.js开始加载视频');
  639. });
  640. myVideo.on('canplay', function() {
  641. console.log('Video.js视频可以播放');
  642. });
  643. myVideo.on('loadedmetadata', function() {
  644. console.log('Video.js视频元数据加载完成');
  645. });
  646. }
  647. // 尝试原生播放器
  648. function tryNativePlayer(videoSrc) {
  649. console.log('尝试原生播放器');
  650. var playHtml = `<video id="nativePlayer" controls playsInline webkit-playsinline style="width:100%; height:100%;" src="${videoSrc}"></video>`;
  651. $("#box").html(playHtml);
  652. const video = document.getElementById('nativePlayer');
  653. video.addEventListener('error', function(e) {
  654. console.error('原生播放器也失败了:', e);
  655. showError('所有播放器都无法播放此视频源,请联系管理员检查视频流配置');
  656. });
  657. video.addEventListener('canplay', function() {
  658. console.log('原生播放器可以播放');
  659. });
  660. }
  661. } else {
  662. $.ajax({
  663. type: "POST",
  664. // url: "http://47.110.79.22:9000/api/api_gateway?method=camera.camera_manage.multi_addr_camera",
  665. url: `${host}/api/api_gateway?method=camera.camera_manage.multi_addr_camera`,
  666. data: {
  667. device_id: device_id,
  668. token
  669. // device_id: 'FA8690323-1',
  670. // token: localStorage.getItem('session_key')
  671. }
  672. }).then((res) => {
  673. console.log('API响应:', res);
  674. if (res && res.message == '') {
  675. var data = null
  676. if (typeof res.data == 'string') {
  677. data = safeParseJSON(res.data);
  678. } else {
  679. data = res.data;
  680. }
  681. if (!data) {
  682. showError('数据解析失败');
  683. return;
  684. }
  685. console.log('解析后的数据:', data);
  686. console.log('数据字段检查:', {
  687. type_id: data.type_id,
  688. hls: data.hls,
  689. hlsHd: data.hlsHd,
  690. rtsp: data.rtsp,
  691. rtmp: data.rtmp
  692. });
  693. if (data.type_id == 2) {
  694. // 大华云联
  695. if (!data.rtsp || data.rtsp === 'undefined' || data.rtsp === '') {
  696. console.error('RTSP视频源无效:', data.rtsp);
  697. showError('RTSP视频源获取失败,请检查设备配置');
  698. return;
  699. }
  700. initYunlianPlayer(data.rtsp)
  701. } else {
  702. // 获取可用的视频源
  703. const videoSource = getAvailableVideoSource(data, data.type_id == 0 ? 'hls' : 'hlsHd');
  704. if (!videoSource.source) {
  705. console.error('没有找到可用的视频源');
  706. showError('设备可能离线或未配置视频流,请检查设备状态');
  707. return;
  708. }
  709. console.log(`使用${videoSource.type}视频源:`, videoSource.source);
  710. // 使用通用播放器创建函数
  711. const mimeType = videoSource.type === 'hls' || videoSource.type === 'hlsHd'
  712. ? 'application/x-mpegURL'
  713. : 'video/mp4';
  714. createVideoJSPlayer(videoSource.source, mimeType);
  715. }
  716. } else {
  717. alert(res.message)
  718. }
  719. })
  720. }
  721. })
  722. document.addEventListener('UniAppJSBridgeReady', function() {
  723. $('.imgBtnCamrea').click(function() {
  724. // if (player) {
  725. // player.close('yunlianPlayer')
  726. // player = null
  727. // }
  728. uni.navigateTo({
  729. url: '/pages/monitor/imagelist?id=' + device_id
  730. })
  731. })
  732. $('.imgBtnDgp').click(function() {
  733. // if (player) {
  734. // player.close('yunlianPlayer')
  735. // player = null
  736. // }
  737. uni.navigateTo({
  738. url: '/pages/monitor/dgpImagelist?id=' + device_id
  739. })
  740. })
  741. });
  742. </script>
  743. </html>