h5player.html 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>H5playerVue</title>
  8. <link rel="stylesheet" href="/static/css/antd.min.css">
  9. <style>
  10. body {
  11. padding: 0px;
  12. }
  13. #app {
  14. width: 100% !important;
  15. height: 100% !important;
  16. display: none;
  17. }
  18. .actions {
  19. padding-left: 8px;
  20. }
  21. .ant-form-item {
  22. margin-bottom: 8px
  23. }
  24. .ant-btn {
  25. margin-right: 2px;
  26. }
  27. .icon-wrapper {
  28. position: relative;
  29. padding-left: 20px;
  30. }
  31. .icon-wrapper .anticon {
  32. position: absolute;
  33. top: -2px;
  34. width: 16px;
  35. height: 16px;
  36. line-height: 1;
  37. font-size: 16px;
  38. left: 0;
  39. }
  40. ::-webkit-media-controls {
  41. display: none !important;
  42. }
  43. #player {
  44. width: 100% !important;
  45. height: 100% !important;
  46. }
  47. .control-wrapper {
  48. position: fixed;
  49. z-index: 2025;
  50. bottom: 4%;
  51. left: 4%;
  52. /* width:20%; */
  53. width: 140px;
  54. height: 140px;
  55. margin: 0 auto;
  56. border-radius: 50%;
  57. }
  58. .control-btn {
  59. position: absolute;
  60. cursor: pointer;
  61. width: 38%;
  62. height: 38%;
  63. display: flex;
  64. align-items: center;
  65. justify-content: center;
  66. border: 1px solid #78aee4;
  67. box-sizing: border-box;
  68. transition: all .3s linear;
  69. }
  70. .control-btn:after {
  71. content: '';
  72. position: absolute;
  73. width: 60%;
  74. height: 60%;
  75. background: #FFFFFF;
  76. z-index: 2;
  77. }
  78. .control-btn:before {
  79. content: '';
  80. position: relative;
  81. display: block;
  82. /* width: 16px; */
  83. /* height: 16px; */
  84. width: 14%;
  85. height: 14%;
  86. border-top: 3px solid #78aee4;
  87. border-right: 3px solid #78aee4;
  88. border-radius: 0 4px 0 0;
  89. box-sizing: border-box;
  90. z-index: 2;
  91. }
  92. .control-top {
  93. top: 0;
  94. left: 50%;
  95. background-color: #FFFFFF;
  96. transform: translateX(-50%) rotate(-45deg);
  97. border-radius: 4px 100% 4px 4px;
  98. }
  99. .control-top:before {
  100. transform: translate(30%, -25%);
  101. }
  102. .control-top:after {
  103. left: 0;
  104. bottom: 0;
  105. border-top: 1px solid #78aee4;
  106. border-right: 1px solid #78aee4;
  107. border-radius: 0 100% 0 0;
  108. }
  109. .control-bottom {
  110. left: 50%;
  111. bottom: 0;
  112. background-color: #FFFFFF;
  113. transform: translateX(-50%) rotate(45deg);
  114. border-radius: 4px 4px 100% 4px;
  115. }
  116. .control-bottom:before {
  117. transform: translate(25%, 25%) rotate(90deg);
  118. }
  119. .control-bottom:after {
  120. top: 0;
  121. left: 0;
  122. border-bottom: 1px solid #78aee4;
  123. border-right: 1px solid #78aee4;
  124. border-radius: 0 0 100% 0;
  125. }
  126. .control-left {
  127. top: 50%;
  128. left: 0;
  129. background-color: #FFFFFF;
  130. transform: translateY(-50%) rotate(45deg);
  131. border-radius: 4px 4px 4px 100%;
  132. }
  133. .control-left:before {
  134. transform: translate(-25%, 30%) rotate(180deg);
  135. }
  136. .control-left:after {
  137. right: 0;
  138. top: 0;
  139. border-bottom: 1px solid #78aee4;
  140. border-left: 1px solid #78aee4;
  141. border-radius: 0 0 0 100%;
  142. }
  143. .control-right {
  144. top: 50%;
  145. right: 0;
  146. background: #FFFFFF;
  147. transform: translateY(-50%) rotate(45deg);
  148. border-radius: 4px 100% 4px 4px;
  149. }
  150. .control-right:before {
  151. transform: translate(30%, -25%);
  152. }
  153. .control-right:after {
  154. left: 0;
  155. bottom: 0;
  156. border-top: 1px solid #78aee4;
  157. border-right: 1px solid #78aee4;
  158. border-radius: 0 100% 0 0;
  159. }
  160. .control-round {
  161. position: absolute;
  162. cursor: pointer;
  163. top: 50%;
  164. left: 50%;
  165. transform: translate(-50%, -50%);
  166. width: 51.2%;
  167. height: 51.2%;
  168. background: #FFFFFF;
  169. border-radius: 50%;
  170. }
  171. .control-round-inner {
  172. position: absolute;
  173. top: 50%;
  174. left: 50%;
  175. transform: translate(-50%, -50%);
  176. display: flex;
  177. justify-content: center;
  178. align-items: center;
  179. width: 66%;
  180. height: 66%;
  181. border: 1px solid #78aee4;
  182. border-radius: 50%;
  183. }
  184. .control-round-inner:after {
  185. content: "| |";
  186. display: flex;
  187. align-items: center;
  188. justify-content: center;
  189. width: 50%;
  190. height: 50%;
  191. font-size: 80%;
  192. text-align: center;
  193. background: #78aee4;
  194. font-weight: bolder;
  195. color: #fff;
  196. border-radius: 50%;
  197. }
  198. </style>
  199. </head>
  200. <body>
  201. <div id="app" >
  202. <div id="player"></div>
  203. <div class="control-wrapper" id="turntable">
  204. <div class="control-btn control-top" @click="goTop"></div>
  205. <div class="control-btn control-left" @click="goLeft"></div>
  206. <div class="control-btn control-bottom" @click="goBottom"></div>
  207. <div class="control-btn control-right" @click="goRight"></div>
  208. <div class="control-round">
  209. <div class="control-round-inner" @click="goStop"></div>
  210. </div>
  211. </div>
  212. </div>
  213. <template id="play-log">
  214. <div></div>
  215. </template>
  216. <!-- 移动端调试 -->
  217. <script src="/static/js/vconsole.min.js"></script>
  218. <!-- <script>
  219. if (IS_MOVE_DEVICE) {
  220. const vc = new VConsole()
  221. }
  222. </script> -->
  223. <script src="/static/js/moment.js"></script>
  224. <script src="/static/js/vue.js"></script>
  225. <script src="/static/js/antd.min.js"></script>
  226. <script src="/static/js/antd-with-locales.min.js"></script>
  227. <script src="/static/h5player.min.js"></script>
  228. <script>
  229. const {
  230. LocaleProvider,
  231. locales
  232. } = window.antd
  233. moment.locale('/static/js/zh-cn.js')
  234. const IS_MOVE_DEVICE = document.body.clientWidth < 992 // 是否移动设备
  235. const MSE_IS_SUPPORT = !!window.MediaSource // 是否支持mse
  236. // if (IS_MOVE_DEVICE) {
  237. // const vc = new VConsole()
  238. // }
  239. let control = {{.control}}
  240. if (control === true){
  241. document.getElementById('turntable').style.display = 'block'
  242. }else {
  243. document.getElementById('turntable').style.display = 'none'
  244. }
  245. // function streamcb(data) {
  246. // console.log(data);
  247. // }
  248. const app = new Vue({
  249. el: '#app',
  250. // components: { Log },
  251. data() {
  252. return {
  253. command: '',
  254. zh_CN: locales.zh_CN,
  255. isMoveDevice: IS_MOVE_DEVICE,
  256. player: null,
  257. splitNum: 1,
  258. mseSupport: MSE_IS_SUPPORT,
  259. tabActive: MSE_IS_SUPPORT ? 'mse' : 'decoder',
  260. labelCol: {
  261. span: 5
  262. },
  263. wrapperCol: {
  264. span: 18
  265. },
  266. urls: {
  267. realplay: {{.wsurl}},
  268. talk: {{.wsurl}},
  269. playback: {{.wsurl}},
  270. },
  271. playback: {
  272. startTime: '2023-08-16T00:00:00',
  273. endTime: '2023-08-16T23:00:00',
  274. valueFormat: moment.HTML5_FMT.DATETIME_LOCAL_SECONDS,
  275. seekStart: '2023-08-16T10:00:00',
  276. rate: ''
  277. },
  278. SmoothDragTime: '2023-08-16T07:47:36.000+08:00',
  279. ThumbnailsTime: '2023-08-16T07:47:36.000+08:00',
  280. judgeurlname: 'wss://10.19.147.57:6014/proxy/10.19.147.57:559/EUrl/KjuVUic',
  281. rate: 1,
  282. audioType: 2,
  283. muted: true,
  284. volume: 50,
  285. InstantParam: 10,
  286. token: "",
  287. volumeOnSvg: {
  288. template: '<svg t="1624453273744" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1421" width="200" height="200"><path d="M597.994667 138.005333q130.005333 28.010667 213.994667 132.992t84.010667 241.002667-84.010667 241.002667-213.994667 132.992l0-88q93.994667-28.010667 153.002667-106.005333t59.008-180.010667-59.008-180.010667-153.002667-106.005333l0-88zM704 512q0 120-106.005333 172.010667l0-344q106.005333 52.010667 106.005333 172.010667zM128 384l170.005333 0 213.994667-213.994667 0 684.010667-213.994667-213.994667-170.005333 0 0-256z" p-id="1422"></path></svg>'
  289. },
  290. volumeOffSvg: {
  291. template: '<svg t="1624453193279" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9147" width="200" height="200"><path d="M512 170.005333l0 180.010667-90.005333-90.005333zM181.994667 128l714.005333 714.005333-53.994667 53.994667-88-88q-74.005333 58.005333-156.010667 77.994667l0-88q50.005333-13.994667 96-50.005333l-181.994667-181.994667 0 288-213.994667-213.994667-170.005333 0 0-256 202.005333 0-202.005333-202.005333zM810.005333 512q0-101.994667-59.008-180.010667t-153.002667-106.005333l0-88q130.005333 28.010667 213.994667 132.992t84.010667 241.002667q0 96-44.010667 178.005333l-64-66.005333q21.994667-53.994667 21.994667-112zM704 512q0 18.005333-2.005333 26.005333l-104-104 0-93.994667q106.005333 52.010667 106.005333 172.010667z" p-id="9148"></path></svg>'
  292. },
  293. zoom: {
  294. rotate: 0,
  295. ratio: 'fill'
  296. },
  297. watermarkConfig: {
  298. text: 'h5player',
  299. color: 'rgba(255, 255, 255, 0.5)',
  300. font: '24px 微软雅黑',
  301. rotateDegree: -15,
  302. space: 240
  303. }
  304. }
  305. },
  306. computed: {
  307. mode: function() {
  308. return this.tabActive === 'mse' ? 0 : 1
  309. }
  310. },
  311. methods: {
  312. init() {
  313. // 设置播放容器的宽高并监听窗口大小变化
  314. window.addEventListener('resize', () => {
  315. this.player.JS_Resize()
  316. })
  317. },
  318. // 向上
  319. goTop() {
  320. console.log('向上')
  321. let arr = {
  322. action: 0,
  323. command: 'UP',
  324. }
  325. this.command = 'UP'
  326. this.sendControl(arr)
  327. },
  328. // 向左
  329. goLeft() {
  330. console.log('向左')
  331. let arr = {
  332. action: 0,
  333. command: 'LEFT',
  334. }
  335. this.command = 'LEFT'
  336. this.sendControl(arr)
  337. },
  338. // 向下
  339. goBottom() {
  340. console.log('向下')
  341. let arr = {
  342. action: 0,
  343. command: 'DOWN',
  344. }
  345. this.command = 'DOWN'
  346. this.sendControl(arr)
  347. },
  348. // 向右
  349. goRight() {
  350. console.log('向右')
  351. let arr = {
  352. action: 0,
  353. command: 'RIGHT',
  354. }
  355. this.command = 'RIGHT'
  356. this.sendControl(arr)
  357. },
  358. // 停止
  359. goStop() {
  360. let arr = {
  361. action: 1,
  362. command: this.command,
  363. }
  364. this.sendControl(arr)
  365. },
  366. // 发送云台控制
  367. sendControl(value) {
  368. let cameraIndexCode = {{.cameraIndexCode}}
  369. const url =
  370. './controlling?cameraIndexCode=' + cameraIndexCode +
  371. '&action=' + value.action + '&command=' + value.command;
  372. // 使用fetch发送GET请求
  373. fetch(url)
  374. .then(response => response.json())
  375. .then(data => {
  376. console.log('成功', data);
  377. })
  378. .catch(error => {
  379. console.error('请求出错:', error);
  380. });
  381. },
  382. createPlayer() {
  383. this.player = new JSPlugin({
  384. szId: 'player', //父窗口id,需要英文字母开头 必填
  385. szBasePath: "./", // 必填,与h5player.min.js的引用路径一致
  386. iMaxSplit: 1,
  387. iCurrentSplit: IS_MOVE_DEVICE ? 1 : 2,
  388. // openDebug: false,
  389. mseWorkerEnable: false, //是否开启多线程解码,分辨率大于1080P建议开启,否则可能卡顿
  390. bSupporDoubleClickFull: true, //是否支持双击全屏,true-双击是全屏;false-双击无响应
  391. oStyle: {
  392. borderSelect: IS_MOVE_DEVICE ? '#000' : '#FFCC00',
  393. }
  394. })
  395. // 事件回调绑定
  396. this.player.JS_SetWindowControlCallback({
  397. windowEventSelect: function(iWndIndex) { //插件选中窗口回调
  398. console.log('windowSelect callback: ', iWndIndex);
  399. },
  400. pluginErrorHandler: function(iWndIndex, iErrorCode, oError) { //插件错误回调
  401. console.log('pluginError callback: ', iWndIndex, iErrorCode, oError);
  402. },
  403. windowEventOver: function(iWndIndex) { //鼠标移过回调
  404. //console.log(iWndIndex);
  405. },
  406. windowEventOut: function(iWndIndex) { //鼠标移出回调
  407. //console.log(iWndIndex);
  408. },
  409. windowEventUp: function(iWndIndex) { //鼠标mouseup事件回调
  410. //console.log(iWndIndex);
  411. },
  412. windowFullCcreenChange: function(bFull) { //全屏切换回调
  413. console.log('fullScreen callback: ', bFull);
  414. },
  415. firstFrameDisplay: function(iWndIndex, iWidth, iHeight) { //首帧显示回调
  416. console.log('firstFrame loaded callback: ', iWndIndex, iWidth, iHeight);
  417. },
  418. performanceLack: function(iWndIndex) { //性能不足回调
  419. console.log('performanceLack callback: ', iWndIndex);
  420. },
  421. StreamEnd: function(iWndIndex) { //性能不足回调
  422. console.log('recv StreamEnd: ', iWndIndex);
  423. },
  424. StreamHeadChanged: function(iWndIndex) {
  425. console.log('recv StreamHeadChanged: ', iWndIndex);
  426. },
  427. ThumbnailsEvent: (iWndIndex, eventType, eventCode) => {
  428. console.log('recv ThumbnailsEvent: ' + iWndIndex + ", eventType:" +
  429. eventType + ", eventCode:" + eventCode);
  430. },
  431. InterruptStream: (iWndIndex, iTime) => {
  432. console.log('recv InterruptStream: ' + iWndIndex + ", iTime:" + iTime);
  433. },
  434. ElementChanged: (iWndIndex, szElementType) => { //回调采用的是video还是canvas
  435. console.log('recv ElementChanged: ' + iWndIndex + ", szElementType:" +
  436. szElementType);
  437. },
  438. });
  439. },
  440. arrangeWindow() {
  441. let splitNum = this.splitNum
  442. this.player.JS_ArrangeWindow(splitNum).then(
  443. () => {
  444. console.log(`arrangeWindow to ${splitNum}x${splitNum} success`)
  445. },
  446. e => {
  447. console.error(e)
  448. }
  449. )
  450. },
  451. wholeFullScreen() {
  452. this.player.JS_FullScreenDisplay(true).then(
  453. () => {
  454. console.log(`wholeFullScreen success`)
  455. },
  456. e => {
  457. console.error(e)
  458. }
  459. )
  460. },
  461. singleFullScreen() {
  462. this.player.JS_FullScreenSingle(this.player.currentWindowIndex).then(
  463. () => {
  464. console.log(`singleFullScreen success`)
  465. },
  466. e => {
  467. console.error(e)
  468. }
  469. )
  470. },
  471. /* 预览&对讲 */
  472. realplay() {
  473. let {
  474. player,
  475. mode,
  476. urls,
  477. token
  478. } = this,
  479. index = player.currentWindowIndex,
  480. playURL = urls.realplay
  481. player.JS_SetTraceId(index, true)
  482. player.JS_Play(playURL, {
  483. playURL,
  484. mode,
  485. keepDecoder: 0,
  486. token
  487. }, index).then(
  488. () => {
  489. console.log('realplay success');
  490. player.JS_GetTraceId(index).then((id) => {
  491. console.log("traceid:", id)
  492. })
  493. },
  494. e => {
  495. console.error(e)
  496. }
  497. )
  498. },
  499. stopPlay() {
  500. this.player.JS_Stop().then(
  501. () => {
  502. this.playback.rate = 0;
  503. console.log('stop realplay success')
  504. },
  505. e => {
  506. console.error(e)
  507. }
  508. )
  509. },
  510. stopAllPlay() {
  511. this.player.JS_StopRealPlayAll().then(
  512. () => {
  513. this.playback.rate = 0;
  514. console.log('stopAllPlay success')
  515. },
  516. e => {
  517. console.error(e)
  518. }
  519. )
  520. },
  521. streamcb(data) {
  522. console.log(data);
  523. },
  524. jsdecoderVersion() {
  525. let v = this.player.JS_GetSdkVersion();
  526. console.log("JS_GetSdkVersion:", v);
  527. },
  528. },
  529. mounted() {
  530. this.$el.style.setProperty('display', 'block')
  531. this.init()
  532. this.createPlayer()
  533. this.realplay()
  534. }
  535. })
  536. </script>
  537. </body>
  538. </html>