Commit 34d9ab96ba84808fb56548f19914fce60b75ec87
Merge branch 'perf/video-player-change' into 'main_dev'
perf: 变更视频组件&&支持h265 See merge request yunteng/thingskit-view!223
Showing
18 changed files
with
719 additions
and
688 deletions
@@ -57,7 +57,11 @@ | @@ -57,7 +57,11 @@ | ||
57 | "vue-router": "4.0.12", | 57 | "vue-router": "4.0.12", |
58 | "vue3-lazyload": "^0.2.5-beta", | 58 | "vue3-lazyload": "^0.2.5-beta", |
59 | "vue3-sketch-ruler": "^1.3.3", | 59 | "vue3-sketch-ruler": "^1.3.3", |
60 | - "vuedraggable": "^4.1.0" | 60 | + "vuedraggable": "^4.1.0", |
61 | + "xgplayer": "^3.0.14", | ||
62 | + "xgplayer-flv": "^3.0.14", | ||
63 | + "xgplayer-hls": "^3.0.14", | ||
64 | + "xgplayer-mp4": "^3.0.14" | ||
61 | }, | 65 | }, |
62 | "devDependencies": { | 66 | "devDependencies": { |
63 | "@commitlint/cli": "^17.0.2", | 67 | "@commitlint/cli": "^17.0.2", |
1 | -lockfileVersion: '6.1' | 1 | +lockfileVersion: '6.0' |
2 | 2 | ||
3 | settings: | 3 | settings: |
4 | autoInstallPeers: true | 4 | autoInstallPeers: true |
@@ -11,6 +11,9 @@ dependencies: | @@ -11,6 +11,9 @@ dependencies: | ||
11 | '@amap/amap-jsapi-types': | 11 | '@amap/amap-jsapi-types': |
12 | specifier: ^0.0.8 | 12 | specifier: ^0.0.8 |
13 | version: 0.0.8 | 13 | version: 0.0.8 |
14 | + '@fingerprintjs/fingerprintjs': | ||
15 | + specifier: ^3.4.1 | ||
16 | + version: 3.4.2 | ||
14 | '@types/color': | 17 | '@types/color': |
15 | specifier: ^3.0.3 | 18 | specifier: ^3.0.3 |
16 | version: 3.0.3 | 19 | version: 3.0.3 |
@@ -41,6 +44,9 @@ dependencies: | @@ -41,6 +44,9 @@ dependencies: | ||
41 | dom-helpers: | 44 | dom-helpers: |
42 | specifier: ^5.2.1 | 45 | specifier: ^5.2.1 |
43 | version: 5.2.1 | 46 | version: 5.2.1 |
47 | + echarts-gl: | ||
48 | + specifier: ^2.0.9 | ||
49 | + version: 2.0.9(echarts@5.3.3) | ||
44 | echarts-liquidfill: | 50 | echarts-liquidfill: |
45 | specifier: ^3.1.0 | 51 | specifier: ^3.1.0 |
46 | version: 3.1.0(echarts@5.3.3) | 52 | version: 3.1.0(echarts@5.3.3) |
@@ -50,6 +56,9 @@ dependencies: | @@ -50,6 +56,9 @@ dependencies: | ||
50 | echarts-wordcloud: | 56 | echarts-wordcloud: |
51 | specifier: ^2.0.0 | 57 | specifier: ^2.0.0 |
52 | version: 2.0.0(echarts@5.3.3) | 58 | version: 2.0.0(echarts@5.3.3) |
59 | + flv.js: | ||
60 | + specifier: ^1.6.2 | ||
61 | + version: 1.6.2 | ||
53 | gsap: | 62 | gsap: |
54 | specifier: ^3.11.3 | 63 | specifier: ^3.11.3 |
55 | version: 3.11.3 | 64 | version: 3.11.3 |
@@ -89,6 +98,9 @@ dependencies: | @@ -89,6 +98,9 @@ dependencies: | ||
89 | video.js: | 98 | video.js: |
90 | specifier: ^7.20.3 | 99 | specifier: ^7.20.3 |
91 | version: 7.21.4 | 100 | version: 7.21.4 |
101 | + videojs-flvjs-es6: | ||
102 | + specifier: ^1.0.1 | ||
103 | + version: 1.0.1 | ||
92 | vue: | 104 | vue: |
93 | specifier: ^3.2.31 | 105 | specifier: ^3.2.31 |
94 | version: 3.2.37 | 106 | version: 3.2.37 |
@@ -113,6 +125,18 @@ dependencies: | @@ -113,6 +125,18 @@ dependencies: | ||
113 | vuedraggable: | 125 | vuedraggable: |
114 | specifier: ^4.1.0 | 126 | specifier: ^4.1.0 |
115 | version: 4.1.0(vue@3.2.37) | 127 | version: 4.1.0(vue@3.2.37) |
128 | + xgplayer: | ||
129 | + specifier: ^3.0.14 | ||
130 | + version: 3.0.14(core-js@3.36.1) | ||
131 | + xgplayer-flv: | ||
132 | + specifier: ^3.0.14 | ||
133 | + version: 3.0.14(core-js@3.36.1)(xgplayer@3.0.14) | ||
134 | + xgplayer-hls: | ||
135 | + specifier: ^3.0.14 | ||
136 | + version: 3.0.14(core-js@3.36.1)(xgplayer@3.0.14) | ||
137 | + xgplayer-mp4: | ||
138 | + specifier: ^3.0.14 | ||
139 | + version: 3.0.14(core-js@3.36.1)(xgplayer@3.0.14) | ||
116 | 140 | ||
117 | devDependencies: | 141 | devDependencies: |
118 | '@commitlint/cli': | 142 | '@commitlint/cli': |
@@ -1158,6 +1182,12 @@ packages: | @@ -1158,6 +1182,12 @@ packages: | ||
1158 | - supports-color | 1182 | - supports-color |
1159 | dev: true | 1183 | dev: true |
1160 | 1184 | ||
1185 | + /@fingerprintjs/fingerprintjs@3.4.2: | ||
1186 | + resolution: {integrity: sha512-3Ncze6JsJpB7BpYhqIgvBpfvEX1jsEKrad5hQBpyRQxtoAp6hx3+R46zqfsuQG4D9egQZ+xftQ0u4LPFMB7Wmg==} | ||
1187 | + dependencies: | ||
1188 | + tslib: 2.6.2 | ||
1189 | + dev: false | ||
1190 | + | ||
1161 | /@humanwhocodes/config-array@0.9.5: | 1191 | /@humanwhocodes/config-array@0.9.5: |
1162 | resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} | 1192 | resolution: {integrity: sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==} |
1163 | engines: {node: '>=10.10.0'} | 1193 | engines: {node: '>=10.10.0'} |
@@ -2409,6 +2439,10 @@ packages: | @@ -2409,6 +2439,10 @@ packages: | ||
2409 | engines: {node: '>=6.0'} | 2439 | engines: {node: '>=6.0'} |
2410 | dev: true | 2440 | dev: true |
2411 | 2441 | ||
2442 | + /claygl@1.3.0: | ||
2443 | + resolution: {integrity: sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ==} | ||
2444 | + dev: false | ||
2445 | + | ||
2412 | /clean-css@5.3.2: | 2446 | /clean-css@5.3.2: |
2413 | resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} | 2447 | resolution: {integrity: sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==} |
2414 | engines: {node: '>= 10.0'} | 2448 | engines: {node: '>= 10.0'} |
@@ -2540,6 +2574,12 @@ packages: | @@ -2540,6 +2574,12 @@ packages: | ||
2540 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} | 2574 | resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} |
2541 | dev: true | 2575 | dev: true |
2542 | 2576 | ||
2577 | + /concat-typed-array@1.0.2: | ||
2578 | + resolution: {integrity: sha512-aC878bxeWSlrY6h60cCDwBUXpKwovZrB7+C4+VHNO1CIXW2gBLxbQ757jWtOXUscLGgYI8R84N6uy9fTJPe+0g==} | ||
2579 | + engines: {node: '>=0.10.0'} | ||
2580 | + deprecated: 'WARNING: This package has been renamed to typed-array-concat.' | ||
2581 | + dev: false | ||
2582 | + | ||
2543 | /connect-history-api-fallback@1.6.0: | 2583 | /connect-history-api-fallback@1.6.0: |
2544 | resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} | 2584 | resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} |
2545 | engines: {node: '>=0.8'} | 2585 | engines: {node: '>=0.8'} |
@@ -2605,6 +2645,11 @@ packages: | @@ -2605,6 +2645,11 @@ packages: | ||
2605 | safe-buffer: 5.1.2 | 2645 | safe-buffer: 5.1.2 |
2606 | dev: true | 2646 | dev: true |
2607 | 2647 | ||
2648 | + /core-js@3.36.1: | ||
2649 | + resolution: {integrity: sha512-BTvUrwxVBezj5SZ3f10ImnX2oRByMxql3EimVqMysepbC9EeMUOpLwdy6Eoili2x6E4kf+ZUB5k/+Jv55alPfA==} | ||
2650 | + requiresBuild: true | ||
2651 | + dev: false | ||
2652 | + | ||
2608 | /cosmiconfig-typescript-loader@2.0.1(@types/node@17.0.43)(cosmiconfig@7.0.1)(typescript@4.7.3): | 2653 | /cosmiconfig-typescript-loader@2.0.1(@types/node@17.0.43)(cosmiconfig@7.0.1)(typescript@4.7.3): |
2609 | resolution: {integrity: sha512-B9s6sX/omXq7I6gC6+YgLmrBFMJhPWew7ty/X5Tuwtd2zOSgWaUdXjkuVwbe3qqcdETo60+1nSVMekq//LIXVA==} | 2654 | resolution: {integrity: sha512-B9s6sX/omXq7I6gC6+YgLmrBFMJhPWew7ty/X5Tuwtd2zOSgWaUdXjkuVwbe3qqcdETo60+1nSVMekq//LIXVA==} |
2610 | engines: {node: '>=12', npm: '>=6'} | 2655 | engines: {node: '>=12', npm: '>=6'} |
@@ -2646,6 +2691,10 @@ packages: | @@ -2646,6 +2691,10 @@ packages: | ||
2646 | which: 2.0.2 | 2691 | which: 2.0.2 |
2647 | dev: true | 2692 | dev: true |
2648 | 2693 | ||
2694 | + /crypto-es@1.2.7: | ||
2695 | + resolution: {integrity: sha512-UUqiVJ2gUuZFmbFsKmud3uuLcNP2+Opt+5ysmljycFCyhA0+T16XJmo1ev/t5kMChMqWh7IEvURNCqsg+SjZGQ==} | ||
2696 | + dev: false | ||
2697 | + | ||
2649 | /crypto-js@4.1.1: | 2698 | /crypto-js@4.1.1: |
2650 | resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} | 2699 | resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} |
2651 | dev: false | 2700 | dev: false |
@@ -2692,6 +2741,20 @@ packages: | @@ -2692,6 +2741,20 @@ packages: | ||
2692 | resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} | 2741 | resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} |
2693 | dev: false | 2742 | dev: false |
2694 | 2743 | ||
2744 | + /d@1.0.2: | ||
2745 | + resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} | ||
2746 | + engines: {node: '>=0.12'} | ||
2747 | + dependencies: | ||
2748 | + es5-ext: 0.10.64 | ||
2749 | + type: 2.7.2 | ||
2750 | + dev: false | ||
2751 | + | ||
2752 | + /danmu.js@1.1.13: | ||
2753 | + resolution: {integrity: sha512-knFd0/cB2HA4FFWiA7eB2suc5vCvoHdqio33FyyCSfP7C+1A+zQcTvnvwfxaZhrxsGj4qaQI2I8XiTqedRaVmg==} | ||
2754 | + dependencies: | ||
2755 | + event-emitter: 0.3.5 | ||
2756 | + dev: false | ||
2757 | + | ||
2695 | /dargs@7.0.0: | 2758 | /dargs@7.0.0: |
2696 | resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} | 2759 | resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} |
2697 | engines: {node: '>=8'} | 2760 | engines: {node: '>=8'} |
@@ -2765,6 +2828,11 @@ packages: | @@ -2765,6 +2828,11 @@ packages: | ||
2765 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} | 2828 | resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} |
2766 | dev: true | 2829 | dev: true |
2767 | 2830 | ||
2831 | + /deepmerge@2.2.1: | ||
2832 | + resolution: {integrity: sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==} | ||
2833 | + engines: {node: '>=0.10.0'} | ||
2834 | + dev: false | ||
2835 | + | ||
2768 | /deepmerge@4.2.2: | 2836 | /deepmerge@4.2.2: |
2769 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} | 2837 | resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} |
2770 | engines: {node: '>=0.10.0'} | 2838 | engines: {node: '>=0.10.0'} |
@@ -2807,6 +2875,10 @@ packages: | @@ -2807,6 +2875,10 @@ packages: | ||
2807 | engines: {node: '>=0.4.0'} | 2875 | engines: {node: '>=0.4.0'} |
2808 | dev: false | 2876 | dev: false |
2809 | 2877 | ||
2878 | + /delegate@3.2.0: | ||
2879 | + resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} | ||
2880 | + dev: false | ||
2881 | + | ||
2810 | /detect-file@1.0.0: | 2882 | /detect-file@1.0.0: |
2811 | resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} | 2883 | resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} |
2812 | engines: {node: '>=0.10.0'} | 2884 | engines: {node: '>=0.10.0'} |
@@ -2900,6 +2972,20 @@ packages: | @@ -2900,6 +2972,20 @@ packages: | ||
2900 | engines: {node: '>=12'} | 2972 | engines: {node: '>=12'} |
2901 | dev: true | 2973 | dev: true |
2902 | 2974 | ||
2975 | + /downloadjs@1.4.7: | ||
2976 | + resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==} | ||
2977 | + dev: false | ||
2978 | + | ||
2979 | + /echarts-gl@2.0.9(echarts@5.3.3): | ||
2980 | + resolution: {integrity: sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==} | ||
2981 | + peerDependencies: | ||
2982 | + echarts: ^5.1.2 | ||
2983 | + dependencies: | ||
2984 | + claygl: 1.3.0 | ||
2985 | + echarts: 5.3.3 | ||
2986 | + zrender: 5.3.2 | ||
2987 | + dev: false | ||
2988 | + | ||
2903 | /echarts-liquidfill@3.1.0(echarts@5.3.3): | 2989 | /echarts-liquidfill@3.1.0(echarts@5.3.3): |
2904 | resolution: {integrity: sha512-5Dlqs/jTsdTUAsd+K5LPLLTgrbbNORUSBQyk8PSy1Mg2zgHDWm83FmvA4s0ooNepCJojFYRITTQ4GU1UUSKYLw==} | 2990 | resolution: {integrity: sha512-5Dlqs/jTsdTUAsd+K5LPLLTgrbbNORUSBQyk8PSy1Mg2zgHDWm83FmvA4s0ooNepCJojFYRITTQ4GU1UUSKYLw==} |
2905 | peerDependencies: | 2991 | peerDependencies: |
@@ -3021,6 +3107,37 @@ packages: | @@ -3021,6 +3107,37 @@ packages: | ||
3021 | is-symbol: 1.0.4 | 3107 | is-symbol: 1.0.4 |
3022 | dev: true | 3108 | dev: true |
3023 | 3109 | ||
3110 | + /es5-ext@0.10.64: | ||
3111 | + resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} | ||
3112 | + engines: {node: '>=0.10'} | ||
3113 | + requiresBuild: true | ||
3114 | + dependencies: | ||
3115 | + es6-iterator: 2.0.3 | ||
3116 | + es6-symbol: 3.1.4 | ||
3117 | + esniff: 2.0.1 | ||
3118 | + next-tick: 1.1.0 | ||
3119 | + dev: false | ||
3120 | + | ||
3121 | + /es6-iterator@2.0.3: | ||
3122 | + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} | ||
3123 | + dependencies: | ||
3124 | + d: 1.0.2 | ||
3125 | + es5-ext: 0.10.64 | ||
3126 | + es6-symbol: 3.1.4 | ||
3127 | + dev: false | ||
3128 | + | ||
3129 | + /es6-promise@4.2.8: | ||
3130 | + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} | ||
3131 | + dev: false | ||
3132 | + | ||
3133 | + /es6-symbol@3.1.4: | ||
3134 | + resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} | ||
3135 | + engines: {node: '>=0.12'} | ||
3136 | + dependencies: | ||
3137 | + d: 1.0.2 | ||
3138 | + ext: 1.7.0 | ||
3139 | + dev: false | ||
3140 | + | ||
3024 | /esbuild@0.11.3: | 3141 | /esbuild@0.11.3: |
3025 | resolution: {integrity: sha512-BzVRHcCtFepjS9WcqRjqoIxLqgpK21a8J4Zi4msSGxDxiXVO1IbcqT1KjhdDDnJxKfe7bvzZrvMEX+bVO0Elcw==} | 3142 | resolution: {integrity: sha512-BzVRHcCtFepjS9WcqRjqoIxLqgpK21a8J4Zi4msSGxDxiXVO1IbcqT1KjhdDDnJxKfe7bvzZrvMEX+bVO0Elcw==} |
3026 | hasBin: true | 3143 | hasBin: true |
@@ -3265,6 +3382,16 @@ packages: | @@ -3265,6 +3382,16 @@ packages: | ||
3265 | - supports-color | 3382 | - supports-color |
3266 | dev: true | 3383 | dev: true |
3267 | 3384 | ||
3385 | + /esniff@2.0.1: | ||
3386 | + resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} | ||
3387 | + engines: {node: '>=0.10'} | ||
3388 | + dependencies: | ||
3389 | + d: 1.0.2 | ||
3390 | + es5-ext: 0.10.64 | ||
3391 | + event-emitter: 0.3.5 | ||
3392 | + type: 2.7.2 | ||
3393 | + dev: false | ||
3394 | + | ||
3268 | /espree@9.3.2: | 3395 | /espree@9.3.2: |
3269 | resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} | 3396 | resolution: {integrity: sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==} |
3270 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} | 3397 | engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} |
@@ -3310,6 +3437,17 @@ packages: | @@ -3310,6 +3437,17 @@ packages: | ||
3310 | engines: {node: '>=0.10.0'} | 3437 | engines: {node: '>=0.10.0'} |
3311 | dev: true | 3438 | dev: true |
3312 | 3439 | ||
3440 | + /event-emitter@0.3.5: | ||
3441 | + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} | ||
3442 | + dependencies: | ||
3443 | + d: 1.0.2 | ||
3444 | + es5-ext: 0.10.64 | ||
3445 | + dev: false | ||
3446 | + | ||
3447 | + /eventemitter3@4.0.7: | ||
3448 | + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} | ||
3449 | + dev: false | ||
3450 | + | ||
3313 | /events@3.3.0: | 3451 | /events@3.3.0: |
3314 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} | 3452 | resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} |
3315 | engines: {node: '>=0.8.x'} | 3453 | engines: {node: '>=0.8.x'} |
@@ -3341,6 +3479,12 @@ packages: | @@ -3341,6 +3479,12 @@ packages: | ||
3341 | homedir-polyfill: 1.0.3 | 3479 | homedir-polyfill: 1.0.3 |
3342 | dev: true | 3480 | dev: true |
3343 | 3481 | ||
3482 | + /ext@1.7.0: | ||
3483 | + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} | ||
3484 | + dependencies: | ||
3485 | + type: 2.7.2 | ||
3486 | + dev: false | ||
3487 | + | ||
3344 | /extend@3.0.2: | 3488 | /extend@3.0.2: |
3345 | resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} | 3489 | resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} |
3346 | dev: true | 3490 | dev: true |
@@ -3490,6 +3634,13 @@ packages: | @@ -3490,6 +3634,13 @@ packages: | ||
3490 | resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} | 3634 | resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} |
3491 | dev: true | 3635 | dev: true |
3492 | 3636 | ||
3637 | + /flv.js@1.6.2: | ||
3638 | + resolution: {integrity: sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==} | ||
3639 | + dependencies: | ||
3640 | + es6-promise: 4.2.8 | ||
3641 | + webworkify-webpack: 2.1.5 | ||
3642 | + dev: false | ||
3643 | + | ||
3493 | /follow-redirects@1.15.1: | 3644 | /follow-redirects@1.15.1: |
3494 | resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} | 3645 | resolution: {integrity: sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==} |
3495 | engines: {node: '>=4.0'} | 3646 | engines: {node: '>=4.0'} |
@@ -4590,6 +4741,10 @@ packages: | @@ -4590,6 +4741,10 @@ packages: | ||
4590 | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} | 4741 | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} |
4591 | dev: true | 4742 | dev: true |
4592 | 4743 | ||
4744 | + /next-tick@1.1.0: | ||
4745 | + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} | ||
4746 | + dev: false | ||
4747 | + | ||
4593 | /no-case@3.0.4: | 4748 | /no-case@3.0.4: |
4594 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} | 4749 | resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} |
4595 | dependencies: | 4750 | dependencies: |
@@ -5732,6 +5887,10 @@ packages: | @@ -5732,6 +5887,10 @@ packages: | ||
5732 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} | 5887 | resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} |
5733 | dev: true | 5888 | dev: true |
5734 | 5889 | ||
5890 | + /tslib@2.6.2: | ||
5891 | + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} | ||
5892 | + dev: false | ||
5893 | + | ||
5735 | /tsutils@3.21.0(typescript@4.6.3): | 5894 | /tsutils@3.21.0(typescript@4.6.3): |
5736 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} | 5895 | resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} |
5737 | engines: {node: '>= 6'} | 5896 | engines: {node: '>= 6'} |
@@ -5774,6 +5933,10 @@ packages: | @@ -5774,6 +5933,10 @@ packages: | ||
5774 | engines: {node: '>=8'} | 5933 | engines: {node: '>=8'} |
5775 | dev: true | 5934 | dev: true |
5776 | 5935 | ||
5936 | + /type@2.7.2: | ||
5937 | + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} | ||
5938 | + dev: false | ||
5939 | + | ||
5777 | /typescript@4.6.3: | 5940 | /typescript@4.6.3: |
5778 | resolution: {integrity: sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==} | 5941 | resolution: {integrity: sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==} |
5779 | engines: {node: '>=4.2.0'} | 5942 | engines: {node: '>=4.2.0'} |
@@ -5912,6 +6075,10 @@ packages: | @@ -5912,6 +6075,10 @@ packages: | ||
5912 | videojs-vtt.js: 0.15.4 | 6075 | videojs-vtt.js: 0.15.4 |
5913 | dev: false | 6076 | dev: false |
5914 | 6077 | ||
6078 | + /videojs-flvjs-es6@1.0.1: | ||
6079 | + resolution: {integrity: sha512-wAI5ff2tZVW+uftTLyPmS38F4SHmMlxqBFOgXEBqMs2X0N4uIVQK0iCCv5XACXH+oc+mP70D23mJmT8KsoHx0g==} | ||
6080 | + dev: false | ||
6081 | + | ||
5915 | /videojs-font@3.2.0: | 6082 | /videojs-font@3.2.0: |
5916 | resolution: {integrity: sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==} | 6083 | resolution: {integrity: sha512-g8vHMKK2/JGorSfqAZQUmYYNnXmfec4MLhwtEFS+mMs2IDY398GLysy6BH6K+aS1KMNu/xWZ8Sue/X/mdQPliA==} |
5917 | dev: false | 6084 | dev: false |
@@ -6261,6 +6428,10 @@ packages: | @@ -6261,6 +6428,10 @@ packages: | ||
6261 | - uglify-js | 6428 | - uglify-js |
6262 | dev: true | 6429 | dev: true |
6263 | 6430 | ||
6431 | + /webworkify-webpack@2.1.5: | ||
6432 | + resolution: {integrity: sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==} | ||
6433 | + dev: false | ||
6434 | + | ||
6264 | /which-boxed-primitive@1.0.2: | 6435 | /which-boxed-primitive@1.0.2: |
6265 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} | 6436 | resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} |
6266 | dependencies: | 6437 | dependencies: |
@@ -6308,6 +6479,101 @@ packages: | @@ -6308,6 +6479,101 @@ packages: | ||
6308 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} | 6479 | resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} |
6309 | dev: true | 6480 | dev: true |
6310 | 6481 | ||
6482 | + /xgplayer-flv@3.0.14(core-js@3.36.1)(xgplayer@3.0.14): | ||
6483 | + resolution: {integrity: sha512-9mSBUbbzkJhFjQOaU8SvnEzDj4Y9tkHsW0IaIxCDi/DlDcHzSubdiuuTVNf1A5cgUSTnFHxwDJtzqVm6FhmTeg==} | ||
6484 | + peerDependencies: | ||
6485 | + core-js: '>=3.12.1' | ||
6486 | + xgplayer: '>=3.0.1' | ||
6487 | + dependencies: | ||
6488 | + core-js: 3.36.1 | ||
6489 | + eventemitter3: 4.0.7 | ||
6490 | + xgplayer: 3.0.14(core-js@3.36.1) | ||
6491 | + xgplayer-streaming-shared: 3.0.14(core-js@3.36.1) | ||
6492 | + xgplayer-transmuxer: 3.0.14(core-js@3.36.1) | ||
6493 | + dev: false | ||
6494 | + | ||
6495 | + /xgplayer-hls@3.0.14(core-js@3.36.1)(xgplayer@3.0.14): | ||
6496 | + resolution: {integrity: sha512-UiVDiDcIzQ6kiDZitbyXqRx5nX/Pi69S9Vfh5lc+6R8SsA2ZyvxWtGOQ6XfpZyXYHfl56JMbyNObOgMT1iRNLw==} | ||
6497 | + peerDependencies: | ||
6498 | + core-js: '>=3.12.1' | ||
6499 | + xgplayer: 3.0.14 | ||
6500 | + dependencies: | ||
6501 | + core-js: 3.36.1 | ||
6502 | + eventemitter3: 4.0.7 | ||
6503 | + xgplayer: 3.0.14(core-js@3.36.1) | ||
6504 | + xgplayer-streaming-shared: 3.0.14(core-js@3.36.1) | ||
6505 | + xgplayer-transmuxer: 3.0.14(core-js@3.36.1) | ||
6506 | + dev: false | ||
6507 | + | ||
6508 | + /xgplayer-mp4-loader@3.0.14(core-js@3.36.1): | ||
6509 | + resolution: {integrity: sha512-cCPH7I/i+saP5i+vivfnu7Bekxm1sS3JlTzaqX2crUL9a4MfWi/r7Yumqsn52lyQGyb+lGKOsvbHeR3wTwUx1w==} | ||
6510 | + peerDependencies: | ||
6511 | + core-js: '>=3.12.1' | ||
6512 | + dependencies: | ||
6513 | + core-js: 3.36.1 | ||
6514 | + eventemitter3: 4.0.7 | ||
6515 | + xgplayer-streaming-shared: 3.0.14(core-js@3.36.1) | ||
6516 | + xgplayer-transmuxer: 3.0.14(core-js@3.36.1) | ||
6517 | + dev: false | ||
6518 | + | ||
6519 | + /xgplayer-mp4@3.0.14(core-js@3.36.1)(xgplayer@3.0.14): | ||
6520 | + resolution: {integrity: sha512-EEZ3KtG7JbOBL33P+Uv98PaIft9tI9zw2rfyS7Sip57hT/9tJ2az4qz9qNSRcrrlLTo0DTYGR/JzADu7l/IyUQ==} | ||
6521 | + peerDependencies: | ||
6522 | + core-js: '>=3.12.1' | ||
6523 | + xgplayer: '>=3.0.0' | ||
6524 | + dependencies: | ||
6525 | + concat-typed-array: 1.0.2 | ||
6526 | + core-js: 3.36.1 | ||
6527 | + deepmerge: 2.2.1 | ||
6528 | + eventemitter3: 4.0.7 | ||
6529 | + xgplayer: 3.0.14(core-js@3.36.1) | ||
6530 | + xgplayer-mp4-loader: 3.0.14(core-js@3.36.1) | ||
6531 | + xgplayer-streaming-shared: 3.0.14(core-js@3.36.1) | ||
6532 | + xgplayer-transmuxer: 3.0.14(core-js@3.36.1) | ||
6533 | + dev: false | ||
6534 | + | ||
6535 | + /xgplayer-streaming-shared@3.0.14(core-js@3.36.1): | ||
6536 | + resolution: {integrity: sha512-XBXNjnMfFDl15kQfXNgmAkaDqRdN0PhxVFBm7+TezillpTdLmqj+HD90F6BargdZVJ4I20/YHYdb9qBg+hUDhg==} | ||
6537 | + peerDependencies: | ||
6538 | + core-js: '>=3.12.1' | ||
6539 | + dependencies: | ||
6540 | + core-js: 3.36.1 | ||
6541 | + eventemitter3: 4.0.7 | ||
6542 | + dev: false | ||
6543 | + | ||
6544 | + /xgplayer-subtitles@3.0.14(core-js@3.36.1): | ||
6545 | + resolution: {integrity: sha512-w6H1h+g3kOI477kv2QBRMZe3M/1dHLXttHBwq4LwKTPGVQ19fLIDGwkfn+HeKwe1ocGDaaq96bS+l+BadnP9TA==} | ||
6546 | + peerDependencies: | ||
6547 | + core-js: '>=3.12.1' | ||
6548 | + dependencies: | ||
6549 | + core-js: 3.36.1 | ||
6550 | + eventemitter3: 4.0.7 | ||
6551 | + dev: false | ||
6552 | + | ||
6553 | + /xgplayer-transmuxer@3.0.14(core-js@3.36.1): | ||
6554 | + resolution: {integrity: sha512-lMS2EwuA6tToCC4NuyJ5Ax0UDaaWU/YuaSkI/Bsj+vHkEzO42vgi2EerSPr91Moz05KhG/+4Vt8qMKUVFjhGTw==} | ||
6555 | + peerDependencies: | ||
6556 | + core-js: '>=3.12.1' | ||
6557 | + dependencies: | ||
6558 | + '@babel/runtime': 7.20.6 | ||
6559 | + concat-typed-array: 1.0.2 | ||
6560 | + core-js: 3.36.1 | ||
6561 | + crypto-es: 1.2.7 | ||
6562 | + dev: false | ||
6563 | + | ||
6564 | + /xgplayer@3.0.14(core-js@3.36.1): | ||
6565 | + resolution: {integrity: sha512-TPS77hUIcM1zVx6FSpGG+OzfMwjwxxWihd+YxVx82DQ22QK60v8TXWSZlWISbmS1+fAlFneesvXDjwy60tC37w==} | ||
6566 | + peerDependencies: | ||
6567 | + core-js: '>=3.12.1' | ||
6568 | + dependencies: | ||
6569 | + core-js: 3.36.1 | ||
6570 | + danmu.js: 1.1.13 | ||
6571 | + delegate: 3.2.0 | ||
6572 | + downloadjs: 1.4.7 | ||
6573 | + eventemitter3: 4.0.7 | ||
6574 | + xgplayer-subtitles: 3.0.14(core-js@3.36.1) | ||
6575 | + dev: false | ||
6576 | + | ||
6311 | /y18n@5.0.8: | 6577 | /y18n@5.0.8: |
6312 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} | 6578 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} |
6313 | engines: {node: '>=10'} | 6579 | engines: {node: '>=10'} |
1 | import { defHttp } from '@/utils/external/http/axios' | 1 | import { defHttp } from '@/utils/external/http/axios' |
2 | -import { ConfigurationItemType, DictItem, OrganizationListItem, UploadResponse } from './model' | 2 | +import {CameraRecord, ConfigurationItemType, DictItem, OrganizationListItem, UploadResponse} from './model' |
3 | import { PaginationResult } from '/#/external/axios' | 3 | import { PaginationResult } from '/#/external/axios' |
4 | import { isShareMode } from '@/views/share/hook' | 4 | import { isShareMode } from '@/views/share/hook' |
5 | 5 | ||
@@ -88,7 +88,7 @@ export const getOrganizationList = (params?: OrganizationListItem) => | @@ -88,7 +88,7 @@ export const getOrganizationList = (params?: OrganizationListItem) => | ||
88 | 88 | ||
89 | //获取视频列表 | 89 | //获取视频列表 |
90 | export const getVideoList = (params?: object) => | 90 | export const getVideoList = (params?: object) => |
91 | - defHttp.get({ | 91 | + defHttp.get<{data: CameraRecord[]}>({ |
92 | url: Api.VIDEO, | 92 | url: Api.VIDEO, |
93 | params | 93 | params |
94 | }) | 94 | }) |
@@ -54,3 +54,39 @@ export interface ProductAndDevice { | @@ -54,3 +54,39 @@ export interface ProductAndDevice { | ||
54 | deviceType: string | 54 | deviceType: string |
55 | transportType: string | 55 | transportType: string |
56 | } | 56 | } |
57 | + | ||
58 | + | ||
59 | +export interface CameraRecord { | ||
60 | + id: string; | ||
61 | + creator: string; | ||
62 | + createTime: string; | ||
63 | + updater: string; | ||
64 | + updateTime: string; | ||
65 | + name: string; | ||
66 | + enabled: boolean; | ||
67 | + tenantId: string; | ||
68 | + videoUrl: string; | ||
69 | + brand: string; | ||
70 | + sn: string; | ||
71 | + organizationId: string; | ||
72 | + organizationName: string; | ||
73 | + status: boolean; | ||
74 | + accessMode: number; | ||
75 | + playProtocol: number; | ||
76 | + deviceId?: string; | ||
77 | + channelId?: string; | ||
78 | + params?: { | ||
79 | + channelNo: string; | ||
80 | + deviceId: string; | ||
81 | + }; | ||
82 | + videoPlatformDTO?: VideoPlatformDTO; | ||
83 | +} | ||
84 | + | ||
85 | +interface VideoPlatformDTO { | ||
86 | + enabled: boolean; | ||
87 | + type: number; | ||
88 | + host: string; | ||
89 | + appKey: string; | ||
90 | + appSecret: string; | ||
91 | + ssl: number; | ||
92 | +} |
src/components/Video/index.ts
0 → 100644
1 | +export {default as XGPlayer} from './src/index.vue' |
src/components/Video/src/index.vue
0 → 100644
1 | +<script setup lang="ts"> | ||
2 | +import Player, {Events, IError} from 'xgplayer'; | ||
3 | +import {FlvPlugin} from 'xgplayer-flv'; | ||
4 | +import Mp4Plugin from 'xgplayer-mp4'; | ||
5 | +import {HlsPlugin} from 'xgplayer-hls'; | ||
6 | +import {onMounted, shallowRef, computed, unref, toRaw, onUnmounted, ref, watch} from 'vue'; | ||
7 | +import PresetPlayer from 'xgplayer'; | ||
8 | +import {IPlayerOptions} from 'xgplayer/es/player'; | ||
9 | +import 'xgplayer/dist/index.min.css'; | ||
10 | +import {StreamType, XGPlayerProps} from './types'; | ||
11 | +import {isShareMode} from "@/views/share/hook"; | ||
12 | +import {getJwtToken, getShareJwtToken} from "@/utils/external/auth"; | ||
13 | + | ||
14 | +const props = withDefaults(defineProps<{ | ||
15 | + streamType?: StreamType; | ||
16 | + autoPlay?: boolean; | ||
17 | + url?: string; | ||
18 | + withToken?: boolean; | ||
19 | + config?: Omit<IPlayerOptions, 'url'>; | ||
20 | +}>(), { | ||
21 | + streamType: 'auto', | ||
22 | + autoPlay: true, | ||
23 | + config: () => ({}), | ||
24 | +}); | ||
25 | + | ||
26 | +const emits = defineEmits<{ | ||
27 | + (eventName: 'ready', player: PresetPlayer): void; | ||
28 | + (eventName: 'onUnmounted', player: PresetPlayer): void; | ||
29 | +}>(); | ||
30 | + | ||
31 | +function getStreamTypeByUrl(url = ''): StreamType | undefined { | ||
32 | + if (url.endsWith('.m3u8')) return 'hls'; | ||
33 | + else if (url.endsWith('.mp4')) return 'mp4'; | ||
34 | + else if (url.endsWith('.flv')) { | ||
35 | + return 'flv'; | ||
36 | + } else return; | ||
37 | +} | ||
38 | + | ||
39 | +const getPluginByStreamType = (): IPlayerOptions => { | ||
40 | + let {url, withToken} = props; | ||
41 | + let {streamType} = props; | ||
42 | + streamType = streamType === 'auto' ? getStreamTypeByUrl(url)! : streamType; | ||
43 | + | ||
44 | + const liveConfig = { | ||
45 | + targetLatency: 10, | ||
46 | + maxLatency: 20, | ||
47 | + disconnectTime: 0, | ||
48 | + fetchOptions: withToken | ||
49 | + ? { | ||
50 | + headers: { | ||
51 | + 'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}`, | ||
52 | + }, | ||
53 | + } | ||
54 | + : {}, | ||
55 | + }; | ||
56 | + const config: IPlayerOptions = { | ||
57 | + flv: liveConfig, | ||
58 | + hls: liveConfig, | ||
59 | + }; | ||
60 | + switch (streamType) { | ||
61 | + case 'hls': | ||
62 | + config.plugins = [HlsPlugin]; | ||
63 | + break; | ||
64 | + case 'mp4': | ||
65 | + config.plugins = [Mp4Plugin]; | ||
66 | + break; | ||
67 | + case 'flv': | ||
68 | + config.plugins = [FlvPlugin]; | ||
69 | + break; | ||
70 | + } | ||
71 | + return config; | ||
72 | +}; | ||
73 | + | ||
74 | +const videoElRef = shallowRef<Nullable<HTMLDivElement>>(); | ||
75 | + | ||
76 | +const playerRef = shallowRef<Nullable<PresetPlayer>>(); | ||
77 | + | ||
78 | +const propsRef = ref<XGPlayerProps>({}); | ||
79 | + | ||
80 | +const getPlayerConfig = computed<IPlayerOptions>(() => { | ||
81 | + const {url, autoPlay, config} = props; | ||
82 | + | ||
83 | + const basicConfig: IPlayerOptions = { | ||
84 | + ...config, | ||
85 | + ...propsRef, | ||
86 | + url, | ||
87 | + lang: 'zh', | ||
88 | + isLive: true, | ||
89 | + autoplay: autoPlay, | ||
90 | + autoplayMuted: autoPlay, | ||
91 | + ...getPluginByStreamType(), | ||
92 | + }; | ||
93 | + return basicConfig; | ||
94 | +}); | ||
95 | + | ||
96 | +function onDecodeError() { | ||
97 | + console.warn('player happend decode error'); | ||
98 | + playerRef.value?.switchURL(props.url!); | ||
99 | +} | ||
100 | + | ||
101 | +function initializePlayer() { | ||
102 | + if (unref(playerRef)) { | ||
103 | + playerRef.value?.destroy?.(); | ||
104 | + playerRef.value = null; | ||
105 | + } | ||
106 | + | ||
107 | + const config = toRaw(unref(getPlayerConfig)); | ||
108 | + | ||
109 | + if (!unref(videoElRef)) return; | ||
110 | + | ||
111 | + const player = (playerRef.value = new Player(Object.assign(config, {el: unref(videoElRef)}))); | ||
112 | + | ||
113 | + player.on(Events.READY, () => { | ||
114 | + emits('ready', player); | ||
115 | + }); | ||
116 | + | ||
117 | + player.setEventsMiddleware({ | ||
118 | + error: (event, callback) => { | ||
119 | + const code = ( | ||
120 | + event as unknown as { | ||
121 | + error: MediaError; | ||
122 | + } | ||
123 | + ).error.code; | ||
124 | + if (code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) { | ||
125 | + if (!props.url) { | ||
126 | + return; | ||
127 | + } | ||
128 | + callback(); | ||
129 | + return; | ||
130 | + } | ||
131 | + | ||
132 | + if (code === MediaError.MEDIA_ERR_DECODE) { | ||
133 | + // 视频流可以播放 中途解码失败重载 | ||
134 | + if (playerRef.value?.isPlaying) { | ||
135 | + onDecodeError(); | ||
136 | + } | ||
137 | + return; | ||
138 | + } | ||
139 | + | ||
140 | + callback(); | ||
141 | + }, | ||
142 | + }); | ||
143 | +} | ||
144 | + | ||
145 | +onMounted(() => { | ||
146 | + initializePlayer(); | ||
147 | +}); | ||
148 | + | ||
149 | +onUnmounted(() => { | ||
150 | + emits('onUnmounted', unref(playerRef)!); | ||
151 | + playerRef.value?.destroy?.(); | ||
152 | +}); | ||
153 | + | ||
154 | +watch( | ||
155 | + () => props.url, | ||
156 | + () => { | ||
157 | + initializePlayer(); | ||
158 | + } | ||
159 | +); | ||
160 | + | ||
161 | +defineExpose({ | ||
162 | + getPlayerInstance: () => unref(playerRef), | ||
163 | +}); | ||
164 | +</script> | ||
165 | + | ||
166 | +<template> | ||
167 | + <div ref="videoElRef"></div> | ||
168 | +</template> |
src/components/Video/src/types.ts
0 → 100644
src/packages/components/external/Informations/Mores/Camera/components/VideoPlay.vue
deleted
100644 → 0
1 | -<template> | ||
2 | - <n-spin size="medium" :show="showLoading" | ||
3 | - :style="{background: '#000',width: baseSize?.w + 'px', height: baseSize?.h + 'px' }"> | ||
4 | - <template #description> 视频正在努力加载中...... </template> | ||
5 | - <div> | ||
6 | - <div ref="playerContainerElRef" class="go-content-box" | ||
7 | - :style="{ width: baseSize?.w + 'px', height: baseSize?.h + 'px', background: '#000' }"> | ||
8 | - | ||
9 | - </div> | ||
10 | - </div> | ||
11 | - </n-spin> | ||
12 | -</template> | ||
13 | -<script setup lang="ts" name="VideoPlay"> | ||
14 | -import { onMounted, ref, onUnmounted, watch, unref, PropType, shallowRef } from 'vue' | ||
15 | -import videojs from 'video.js' | ||
16 | -import 'videojs-flvjs-es6' | ||
17 | -import type { VideoJsPlayerOptions } from 'video.js' | ||
18 | -import 'video.js/dist/video-js.min.css' | ||
19 | -import { getJwtToken, getShareJwtToken } from '@/utils/external/auth' | ||
20 | -import { isShareMode } from '@/views/share/hook' | ||
21 | -import { getOpenFlvPlayUrl, closeFlvPlay, getVideoControlStart } from '@/api/external/flvPlay' | ||
22 | -import { useFingerprint } from '@/utils/external/useFingerprint' | ||
23 | -import { GetResult } from '@fingerprintjs/fingerprintjs' | ||
24 | -import { AccessModeEnum, VideoPlayerType } from '../config' | ||
25 | -import { getVideoUrl } from '@/api/external/common' | ||
26 | - | ||
27 | -const props = defineProps({ | ||
28 | - sourceSrc: { | ||
29 | - type: String | ||
30 | - }, | ||
31 | - option: { | ||
32 | - type: Object | ||
33 | - }, | ||
34 | - | ||
35 | - baseSize: { | ||
36 | - type: Object as PropType<{ w: number; h: number }> | ||
37 | - }, | ||
38 | - autoPlay: { | ||
39 | - type: Boolean | ||
40 | - }, | ||
41 | - name: { | ||
42 | - type: String | ||
43 | - }, | ||
44 | - avatar: { | ||
45 | - type: String | ||
46 | - }, | ||
47 | - w: { | ||
48 | - type: Number, | ||
49 | - default: 300 | ||
50 | - }, | ||
51 | - h: { | ||
52 | - type: Number, | ||
53 | - default: 300 | ||
54 | - }, | ||
55 | - index: { | ||
56 | - type: Number | ||
57 | - } | ||
58 | -}) | ||
59 | - | ||
60 | - | ||
61 | -const { getResult } = useFingerprint() | ||
62 | - | ||
63 | -const showLoading = ref<boolean>(false) | ||
64 | - | ||
65 | -const sourceSrc = ref<string | null>(props.sourceSrc || '') | ||
66 | - | ||
67 | - | ||
68 | -// video实例对象 | ||
69 | -const videoPlayer = shallowRef<videojs.Player | null>(null) | ||
70 | -const playerContainerElRef = shallowRef<HTMLElement | null>(null) | ||
71 | - | ||
72 | -const fingerprintResult = ref<Nullable<GetResult>>(null) | ||
73 | - | ||
74 | -const isRtspProtocol = (url: string) => { | ||
75 | - const reg = /^rtsp:\/\//g | ||
76 | - return reg.test(url) | ||
77 | -} | ||
78 | - | ||
79 | -const getVideoTypeByUrl = (url = '') => { | ||
80 | - if (!url) return; | ||
81 | - try { | ||
82 | - const { protocol, pathname } = new URL(url) | ||
83 | - if (protocol.startsWith('rtsp:')) return VideoPlayerType.flv | ||
84 | - const reg = /[^.]\w*$/ | ||
85 | - const mathValue = pathname.match(reg) || [] | ||
86 | - const ext = (mathValue[0] as keyof typeof VideoPlayerType) || 'webm' | ||
87 | - const type = VideoPlayerType[ext] | ||
88 | - return type ? type : VideoPlayerType.webm | ||
89 | - } catch (error) { | ||
90 | - console.error(error) | ||
91 | - return VideoPlayerType.webm | ||
92 | - } | ||
93 | -} | ||
94 | - | ||
95 | - | ||
96 | -//options配置 | ||
97 | -const options: VideoJsPlayerOptions & Recordable = { | ||
98 | - language: 'zh-CN', // 设置语言 | ||
99 | - controls: true, // 是否显示控制条 | ||
100 | - preload: 'auto', // 预加载 | ||
101 | - autoplay: props.autoPlay ? true : false, // 是否自动播放 | ||
102 | - fluid: false, // 自适应宽高 | ||
103 | - poster: props?.avatar || '', | ||
104 | - sources: [], | ||
105 | - muted: props.autoPlay ? true : false, | ||
106 | - userActions: { | ||
107 | - hotkeys: true | ||
108 | - }, | ||
109 | - techOrder: ['html5', 'flvjs'], | ||
110 | - flvjs: { | ||
111 | - mediaDataSource: { | ||
112 | - isLive: true, | ||
113 | - cors: true, | ||
114 | - withCredentials: false, | ||
115 | - hasAudio: false | ||
116 | - }, | ||
117 | - config: { | ||
118 | - autoCleanupSourceBuffer: true | ||
119 | - } | ||
120 | - } | ||
121 | -} | ||
122 | - | ||
123 | - | ||
124 | -async function getSource() { | ||
125 | - fingerprintResult.value = await getResult() | ||
126 | - let src = unref(sourceSrc) || '' | ||
127 | - if (isRtspProtocol(unref(sourceSrc)!)) { | ||
128 | - src = getOpenFlvPlayUrl(src, unref(fingerprintResult)?.visitorId || '') | ||
129 | - } | ||
130 | - return [ | ||
131 | - { | ||
132 | - type: getVideoTypeByUrl(src), | ||
133 | - src | ||
134 | - } | ||
135 | - ] | ||
136 | -} | ||
137 | - | ||
138 | -//针对萤石云或者海康威视,根据视频id获取播放流地址 | ||
139 | -const getVideoUrlById = async (id: string) => { | ||
140 | - const res = await getVideoUrl(id) | ||
141 | - if (!res) return | ||
142 | - const { url } = res.data | ||
143 | - return url | ||
144 | -} | ||
145 | - | ||
146 | -//针对gbt28181,根据设备id和通道号获取播放流地址 | ||
147 | -const getVideoControlList = async (deviceId: string, channelId: string) => { | ||
148 | - const { | ||
149 | - data: { flv } | ||
150 | - } = await getVideoControlStart({ | ||
151 | - deviceId, | ||
152 | - channelId | ||
153 | - }) | ||
154 | - return flv | ||
155 | -} | ||
156 | - | ||
157 | -//针对自定义地址,直接获取地址 | ||
158 | -const getCustomUrl = (url: string) => { | ||
159 | - return url | ||
160 | -} | ||
161 | - | ||
162 | - | ||
163 | -function createVideoElement() { | ||
164 | - if (!unref(playerContainerElRef)) return | ||
165 | - unref(playerContainerElRef)!.innerHTML = '' | ||
166 | - const video = document.createElement('video') | ||
167 | - video.setAttribute('crossOrigin', 'anonymous') | ||
168 | - video.style.setProperty('width', '100%') | ||
169 | - video.style.setProperty('height', '100%') | ||
170 | - video.classList.add('video-js', 'my-video', 'vjs-theme-city', 'vjs-big-play-centered') | ||
171 | - unref(playerContainerElRef)?.appendChild(video) | ||
172 | - return video | ||
173 | -} | ||
174 | - | ||
175 | - | ||
176 | -// 初始化videojs | ||
177 | -const createVideoPlayer = async () => { | ||
178 | - if (unref(videoPlayer)) dispose() | ||
179 | - | ||
180 | - options.sources = await getSource() | ||
181 | - | ||
182 | - if (isRtspProtocol(unref(sourceSrc) || '')) { | ||
183 | - options.flvjs = { | ||
184 | - ...(options.flvjs || {}), | ||
185 | - config: { | ||
186 | - headers: { | ||
187 | - 'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}` | ||
188 | - } | ||
189 | - } | ||
190 | - } | ||
191 | - } | ||
192 | - const video = createVideoElement() | ||
193 | - if (!video) return | ||
194 | - | ||
195 | - videoPlayer.value = videojs(video!, options) //fix 修复videojs解决直播延时的问题 | ||
196 | - | ||
197 | - videoPlayer.value?.on('timeupdate', function () { | ||
198 | - // 计算表最新推流的时间和现在播放器播放推流的时间 | ||
199 | - let differTime = | ||
200 | - (unref(videoPlayer))!.buffered()?.end(0) - | ||
201 | - (unref(videoPlayer))!.currentTime() // 差值小于1.5s时根据1倍速进行播放 | ||
202 | - if (differTime < 1.5) { | ||
203 | - videoPlayer.value?.playbackRate(1) | ||
204 | - } // 差值大于1.5s小于10s根据1.2倍速进行播放 | ||
205 | - if (differTime < 10 && differTime > 1.5) { | ||
206 | - videoPlayer.value?.playbackRate(1.2) | ||
207 | - } // 差值大于10s时进行重新加载直播流 | ||
208 | - if (differTime > 10) { | ||
209 | - createVideoPlayer() | ||
210 | - } | ||
211 | - }) | ||
212 | -} | ||
213 | - | ||
214 | -const getVideosUrl = async () => { | ||
215 | - try { | ||
216 | - showLoading.value = true | ||
217 | - videoPlayer.value?.src(''); | ||
218 | - const { option } = props || {} | ||
219 | - const { accessMode, id, channelId, deviceId, customUrl } = option || {} | ||
220 | - if (accessMode === AccessModeEnum.Streaming) { | ||
221 | - return await getVideoUrlById(id) | ||
222 | - } else if (accessMode === AccessModeEnum.GBT28181) { | ||
223 | - return await getVideoControlList(deviceId, channelId) | ||
224 | - } else { | ||
225 | - return await getCustomUrl(customUrl) | ||
226 | - } | ||
227 | - } finally { | ||
228 | - showLoading.value = false | ||
229 | - } | ||
230 | -} | ||
231 | - | ||
232 | - | ||
233 | -watch(() => props.option, async () => { | ||
234 | - console.log(props, 'prop') | ||
235 | - dispose() | ||
236 | - sourceSrc.value = await getVideosUrl() | ||
237 | - createVideoPlayer() | ||
238 | -}) | ||
239 | - | ||
240 | - | ||
241 | - | ||
242 | -// 销毁 | ||
243 | -function dispose() { | ||
244 | - unref(videoPlayer)?.dispose() | ||
245 | - videoPlayer.value = null | ||
246 | -} | ||
247 | - | ||
248 | -watch( | ||
249 | - () => props.autoPlay, | ||
250 | - async (newData: boolean) => { | ||
251 | - if (newData) { | ||
252 | - handleVideoPlay() | ||
253 | - } else { | ||
254 | - videoPlayer.value?.pause() | ||
255 | - } | ||
256 | - } | ||
257 | -) | ||
258 | - | ||
259 | -onMounted(async () => { | ||
260 | - dispose() | ||
261 | - sourceSrc.value = await getVideosUrl() | ||
262 | - createVideoPlayer() | ||
263 | -}) | ||
264 | - | ||
265 | -onUnmounted(() => { | ||
266 | - if (props.sourceSrc) { | ||
267 | - closeFlvPlay(props.sourceSrc, unref(fingerprintResult)!.visitorId!) | ||
268 | - } | ||
269 | - handleVideoDispose() | ||
270 | -}) | ||
271 | - | ||
272 | -//播放 | ||
273 | -const handleVideoPlay = () => videoPlayer.value?.play() | ||
274 | - | ||
275 | -//暂停和销毁 | ||
276 | -const handleVideoDispose = () => videoPlayer.value?.dispose() && videoPlayer.value?.pause() | ||
277 | - | ||
278 | -</script> | ||
279 | - | ||
280 | -<style lang="scss" scoped> | ||
281 | - | ||
282 | -.go-content-box { | ||
283 | - display: flex; | ||
284 | - align-items: center; | ||
285 | - justify-content: center; | ||
286 | - | ||
287 | - .my-video { | ||
288 | - width: 100% !important; | ||
289 | - height: 100% !important; | ||
290 | - position: relative; | ||
291 | - } | ||
292 | -} | ||
293 | -</style> | ||
294 | -<style> | ||
295 | -.vjs-poster { | ||
296 | - background-size: 100% !important; | ||
297 | -} | ||
298 | -</style> |
1 | +<script lang="ts" setup> | ||
2 | +import {XGPlayer} from '@/components/Video' | ||
3 | +import {watch, ref} from "vue"; | ||
4 | +import {StreamType} from "@/components/Video/src/types"; | ||
5 | +import {getPlayUrl} from "@/packages/components/external/Informations/Mores/SingleCamera/config"; | ||
6 | +import {CameraRecord} from "@/api/external/common/model"; | ||
7 | + | ||
8 | +; | ||
9 | + | ||
10 | +const props = defineProps<{ | ||
11 | + dataset?: any | ||
12 | + width: number | ||
13 | + height: number | ||
14 | +}>() | ||
15 | + | ||
16 | +const loading = ref(false) | ||
17 | +const playUrl = ref<string>() | ||
18 | +const playType = ref<StreamType>() | ||
19 | + | ||
20 | +interface Dataset { | ||
21 | + accessMode: number | ||
22 | + autoPlay: boolean | ||
23 | + channelId?: string | ||
24 | + customUrl?: string | ||
25 | + deviceId?: string | ||
26 | + id?: string | ||
27 | + playProtocol?: number | ||
28 | +} | ||
29 | + | ||
30 | +const handleGetPlayUrl = async (dataset: Dataset) => { | ||
31 | + try { | ||
32 | + loading.value = true | ||
33 | + const {id, channelId, deviceId, accessMode, customUrl, playProtocol} = dataset | ||
34 | + if (!accessMode) return | ||
35 | + const {type, url} = await getPlayUrl({ | ||
36 | + id: id, | ||
37 | + accessMode: accessMode, | ||
38 | + playProtocol: playProtocol, | ||
39 | + videoUrl: customUrl, | ||
40 | + params: { | ||
41 | + deviceId: deviceId, | ||
42 | + channelNo: channelId, | ||
43 | + }, | ||
44 | + } as unknown as CameraRecord) | ||
45 | + playUrl.value = url | ||
46 | + playType.value = type | ||
47 | + } finally { | ||
48 | + loading.value = false | ||
49 | + } | ||
50 | +} | ||
51 | + | ||
52 | +watch( | ||
53 | + () => props.dataset, | ||
54 | + (newData: Dataset) => { | ||
55 | + handleGetPlayUrl(newData) | ||
56 | + }, | ||
57 | + { | ||
58 | + immediate: true | ||
59 | + } | ||
60 | +) | ||
61 | +</script> | ||
62 | + | ||
63 | +<template> | ||
64 | + <NSpin :show="loading" class="player-spin"> | ||
65 | + <XGPlayer | ||
66 | + :url="playUrl" | ||
67 | + :stream-type="playType" | ||
68 | + :auto-play="dataset.autoPlay" | ||
69 | + :config="{width: width, height: height, poster: dataset.avatar}" | ||
70 | + /> | ||
71 | + </NSpin> | ||
72 | +</template> | ||
73 | + | ||
74 | +<style lang="scss" scoped> | ||
75 | +.player-spin { | ||
76 | + width: 100%; | ||
77 | + height: 100%; | ||
78 | + @include deep() { | ||
79 | + .n-spin-content { | ||
80 | + width: 100%; | ||
81 | + height: 100%; | ||
82 | + } | ||
83 | + } | ||
84 | +} | ||
85 | + | ||
86 | +</style> |
@@ -53,6 +53,7 @@ export interface videoList { | @@ -53,6 +53,7 @@ export interface videoList { | ||
53 | deviceId: string | 53 | deviceId: string |
54 | customUrl: string | 54 | customUrl: string |
55 | params: GBT28181Params | 55 | params: GBT28181Params |
56 | + playProtocol?: number | ||
56 | } | 57 | } |
57 | 58 | ||
58 | export const option = { | 59 | export const option = { |
@@ -120,15 +120,16 @@ const handleUpdateTreeValue = (e: string) => { | @@ -120,15 +120,16 @@ const handleUpdateTreeValue = (e: string) => { | ||
120 | const getVideoLists = async (organizationId: string) => { | 120 | const getVideoLists = async (organizationId: string) => { |
121 | const res = await getVideoList({ organizationId }) | 121 | const res = await getVideoList({ organizationId }) |
122 | if (!res) return | 122 | if (!res) return |
123 | - videoOptions.value = res?.data?.map((item: videoList) => ({ | 123 | + videoOptions.value = res?.data?.map((item) => ({ |
124 | label: item.name, | 124 | label: item.name, |
125 | value: item.id, | 125 | value: item.id, |
126 | id: item.id, | 126 | id: item.id, |
127 | accessMode: item.accessMode, | 127 | accessMode: item.accessMode, |
128 | customUrl: item.accessMode === AccessModeEnum.ManuallyEnter ? item.videoUrl: '', //参数只给自定义视频流使用 | 128 | customUrl: item.accessMode === AccessModeEnum.ManuallyEnter ? item.videoUrl: '', //参数只给自定义视频流使用 |
129 | channelId: item.accessMode === AccessModeEnum.GBT28181 ? item?.params?.channelNo : '', //参数只给gbt28181使用 | 129 | channelId: item.accessMode === AccessModeEnum.GBT28181 ? item?.params?.channelNo : '', //参数只给gbt28181使用 |
130 | - deviceId: item.accessMode === AccessModeEnum.GBT28181 ? item?.params?.deviceId : '' //参数只给gbt28181使用 | ||
131 | - })) | 130 | + deviceId: item.accessMode === AccessModeEnum.GBT28181 ? item?.params?.deviceId : '', //参数只给gbt28181使用 |
131 | + playProtocol: item?.playProtocol | ||
132 | + } as any)) | ||
132 | } | 133 | } |
133 | 134 | ||
134 | //针对萤石云或者海康威视,根据视频id获取播放流地址 | 135 | //针对萤石云或者海康威视,根据视频id获取播放流地址 |
@@ -2,17 +2,7 @@ | @@ -2,17 +2,7 @@ | ||
2 | <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="banner-box" ref="root"> | 2 | <div @mouseenter="handleMouseenter" @mouseleave="handleMouseleave" class="banner-box" ref="root"> |
3 | <div class="wrapper"> | 3 | <div class="wrapper"> |
4 | <div v-for="(item, index) in option.dataset" :key="index" :class="item.className" :style="item.sty"> | 4 | <div v-for="(item, index) in option.dataset" :key="index" :class="item.className" :style="item.sty"> |
5 | - <VideoPlay | ||
6 | - :autoPlay="item.autoPlay" | ||
7 | - :option="item" | ||
8 | - :name="item.name" | ||
9 | - :avatar="item.avatar" | ||
10 | - :key="item + index" | ||
11 | - :sourceSrc="item.url" | ||
12 | - :baseSize="{w,h}" | ||
13 | - :index="index" | ||
14 | - /> | ||
15 | - <span class="video-title">{{ item.name }}</span> | 5 | + <VideoPlayer :key="item + index" :dataset="item" :width="w" :height="h"/> |
16 | </div> | 6 | </div> |
17 | </div> | 7 | </div> |
18 | <a v-show="isShowSvg" href="javascript:;" class="left" @click="changeSlide('left')"></a> | 8 | <a v-show="isShowSvg" href="javascript:;" class="left" @click="changeSlide('left')"></a> |
@@ -20,11 +10,10 @@ | @@ -20,11 +10,10 @@ | ||
20 | </div> | 10 | </div> |
21 | </template> | 11 | </template> |
22 | <script setup lang="ts" name="index"> | 12 | <script setup lang="ts" name="index"> |
23 | -import { PropType, watch, toRefs, shallowReactive, onMounted, ref } from 'vue' | ||
24 | -import { CreateComponentType } from '@/packages/index.d' | ||
25 | -import 'video.js/dist/video-js.min.css' | ||
26 | -import { option as typeOption } from './config' | ||
27 | -import VideoPlay from './components' | 13 | +import {PropType, watch, toRefs, shallowReactive, onMounted, ref} from 'vue' |
14 | +import {CreateComponentType} from '@/packages/index.d' | ||
15 | +import {option as typeOption} from './config' | ||
16 | +import VideoPlayer from "@/packages/components/external/Informations/Mores/Camera/components/VideoPlayer.vue"; | ||
28 | 17 | ||
29 | const props = defineProps({ | 18 | const props = defineProps({ |
30 | chartConfig: { | 19 | chartConfig: { |
@@ -35,9 +24,9 @@ const props = defineProps({ | @@ -35,9 +24,9 @@ const props = defineProps({ | ||
35 | 24 | ||
36 | const isShowSvg = ref(false) | 25 | const isShowSvg = ref(false) |
37 | 26 | ||
38 | -const { w, h } = toRefs(props.chartConfig.attr) | 27 | +const {w, h} = toRefs(props.chartConfig.attr) |
39 | 28 | ||
40 | -const { autoSwitch, interval } = toRefs(props.chartConfig.option) | 29 | +const {autoSwitch, interval} = toRefs(props.chartConfig.option) |
41 | 30 | ||
42 | //暂定 any类型 | 31 | //暂定 any类型 |
43 | const option = shallowReactive<{ ['dataset']: any }>({ | 32 | const option = shallowReactive<{ ['dataset']: any }>({ |
@@ -50,15 +39,15 @@ const computedFunc = (initial: number, source: Recordable[]) => { | @@ -50,15 +39,15 @@ const computedFunc = (initial: number, source: Recordable[]) => { | ||
50 | if (initial < 0) initial = 0 | 39 | if (initial < 0) initial = 0 |
51 | if (Array.isArray(source)) { | 40 | if (Array.isArray(source)) { |
52 | let len = source.length, | 41 | let len = source.length, |
53 | - temp1 = initial - 2 < 0 ? initial - 2 + len : initial - 2, | ||
54 | - temp2 = initial - 1 < 0 ? initial - 1 + len : initial - 1, | ||
55 | - temp3 = initial, | ||
56 | - temp4 = initial + 1 >= len ? initial + 1 - len : initial + 1, | ||
57 | - temp5 = initial + 2 >= len ? initial + 2 - len : initial + 2 | 42 | + temp1 = initial - 2 < 0 ? initial - 2 + len : initial - 2, |
43 | + temp2 = initial - 1 < 0 ? initial - 1 + len : initial - 1, | ||
44 | + temp3 = initial, | ||
45 | + temp4 = initial + 1 >= len ? initial + 1 - len : initial + 1, | ||
46 | + temp5 = initial + 2 >= len ? initial + 2 - len : initial + 2 | ||
58 | return source?.map((item: Recordable, index: number) => { | 47 | return source?.map((item: Recordable, index: number) => { |
59 | let transform = `translateX(-50%) scale(0.7)`, | 48 | let transform = `translateX(-50%) scale(0.7)`, |
60 | - zIndex = 0, | ||
61 | - className = 'slide' | 49 | + zIndex = 0, |
50 | + className = 'slide' | ||
62 | switch (index) { | 51 | switch (index) { |
63 | case temp3: | 52 | case temp3: |
64 | transform = `translateX(-50%) scale(1)` | 53 | transform = `translateX(-50%) scale(1)` |
@@ -93,23 +82,23 @@ const computedFunc = (initial: number, source: Recordable[]) => { | @@ -93,23 +82,23 @@ const computedFunc = (initial: number, source: Recordable[]) => { | ||
93 | } | 82 | } |
94 | 83 | ||
95 | watch( | 84 | watch( |
96 | - () => props.chartConfig.option.dataset, | ||
97 | - newData => { | ||
98 | - option.dataset = newData | ||
99 | - }, | ||
100 | - { | ||
101 | - immediate: true, | ||
102 | - deep: true | ||
103 | - } | 85 | + () => props.chartConfig.option.dataset, |
86 | + newData => { | ||
87 | + option.dataset = newData | ||
88 | + }, | ||
89 | + { | ||
90 | + immediate: true, | ||
91 | + deep: true | ||
92 | + } | ||
104 | ) | 93 | ) |
105 | 94 | ||
106 | option.dataset = computedFunc(initial.value, option.dataset) | 95 | option.dataset = computedFunc(initial.value, option.dataset) |
107 | 96 | ||
108 | watch( | 97 | watch( |
109 | - () => initial.value, | ||
110 | - newV => { | ||
111 | - option.dataset = computedFunc(newV, option.dataset) | ||
112 | - } | 98 | + () => initial.value, |
99 | + newV => { | ||
100 | + option.dataset = computedFunc(newV, option.dataset) | ||
101 | + } | ||
113 | ) | 102 | ) |
114 | 103 | ||
115 | // 处理自动轮播 | 104 | // 处理自动轮播 |
@@ -155,17 +144,17 @@ function changeSlide(dir: string) { | @@ -155,17 +144,17 @@ function changeSlide(dir: string) { | ||
155 | } | 144 | } |
156 | 145 | ||
157 | watch( | 146 | watch( |
158 | - () => autoSwitch.value, | ||
159 | - (newV: boolean) => { | ||
160 | - if (newV) { | ||
161 | - autoPlay() | ||
162 | - } else { | ||
163 | - clearInterval(timer) | 147 | + () => autoSwitch.value, |
148 | + (newV: boolean) => { | ||
149 | + if (newV) { | ||
150 | + autoPlay() | ||
151 | + } else { | ||
152 | + clearInterval(timer) | ||
153 | + } | ||
154 | + }, | ||
155 | + { | ||
156 | + immediate: true | ||
164 | } | 157 | } |
165 | - }, | ||
166 | - { | ||
167 | - immediate: true | ||
168 | - } | ||
169 | ) | 158 | ) |
170 | 159 | ||
171 | const handleMouseenter = () => { | 160 | const handleMouseenter = () => { |
@@ -181,6 +170,7 @@ const handleMouseleave = () => (isShowSvg.value = false) | @@ -181,6 +170,7 @@ const handleMouseleave = () => (isShowSvg.value = false) | ||
181 | height: 100%; | 170 | height: 100%; |
182 | display: flex; | 171 | display: flex; |
183 | overflow: hidden; | 172 | overflow: hidden; |
173 | + | ||
184 | .slide { | 174 | .slide { |
185 | width: 20%; | 175 | width: 20%; |
186 | height: 100%; | 176 | height: 100%; |
@@ -200,6 +190,7 @@ const handleMouseleave = () => (isShowSvg.value = false) | @@ -200,6 +190,7 @@ const handleMouseleave = () => (isShowSvg.value = false) | ||
200 | } | 190 | } |
201 | } | 191 | } |
202 | } | 192 | } |
193 | + | ||
203 | .arrow { | 194 | .arrow { |
204 | position: absolute; | 195 | position: absolute; |
205 | top: 50%; | 196 | top: 50%; |
@@ -211,11 +202,13 @@ const handleMouseleave = () => (isShowSvg.value = false) | @@ -211,11 +202,13 @@ const handleMouseleave = () => (isShowSvg.value = false) | ||
211 | background-color: white; | 202 | background-color: white; |
212 | opacity: 0.5; | 203 | opacity: 0.5; |
213 | } | 204 | } |
205 | + | ||
214 | a.left { | 206 | a.left { |
215 | @extend .arrow; | 207 | @extend .arrow; |
216 | background-image: url('./static/left.svg'); | 208 | background-image: url('./static/left.svg'); |
217 | left: 0px; | 209 | left: 0px; |
218 | } | 210 | } |
211 | + | ||
219 | a.right { | 212 | a.right { |
220 | @extend .arrow; | 213 | @extend .arrow; |
221 | background-image: url('./static/right.svg'); | 214 | background-image: url('./static/right.svg'); |
src/packages/components/external/Informations/Mores/SingleCamera/components/VideoPlay.vue
deleted
100644 → 0
1 | -<template> | ||
2 | - <div ref="playerContainerElRef" class="go-content-box" | ||
3 | - :style="{ width: baseSize?.w + 'px', height: baseSize?.h + 'px', background: '#000' }"> | ||
4 | - | ||
5 | - </div> | ||
6 | -</template> | ||
7 | -<script setup lang="ts"> | ||
8 | -import { ref, onUnmounted, watch, unref, PropType, shallowRef } from 'vue' | ||
9 | -import videojs from 'video.js' | ||
10 | -import 'videojs-flvjs-es6' | ||
11 | -import type { VideoJsPlayerOptions } from 'video.js' | ||
12 | -import 'video.js/dist/video-js.min.css' | ||
13 | -import { getJwtToken, getShareJwtToken } from '@/utils/external/auth' | ||
14 | -import { isShareMode } from '@/views/share/hook' | ||
15 | -import { getOpenFlvPlayUrl, closeFlvPlay } from '@/api/external/flvPlay' | ||
16 | -import { useFingerprint } from '@/utils/external/useFingerprint' | ||
17 | -import { GetResult } from '@fingerprintjs/fingerprintjs' | ||
18 | -import { VideoPlayerTypeEnum } from '../config' | ||
19 | - | ||
20 | -const props = defineProps({ | ||
21 | - sourceSrc: { | ||
22 | - type: String | ||
23 | - }, | ||
24 | - autoPlay: { | ||
25 | - type: Boolean | ||
26 | - }, | ||
27 | - name: { | ||
28 | - type: String | ||
29 | - }, | ||
30 | - avatar: { | ||
31 | - type: String | ||
32 | - }, | ||
33 | - baseSize: { | ||
34 | - type: Object as PropType<{ w: number; h: number }> | ||
35 | - } | ||
36 | -}) | ||
37 | - | ||
38 | -const isRtspProtocol = (url: string) => { | ||
39 | - const reg = /^rtsp:\/\//g | ||
40 | - return reg.test(url) | ||
41 | -} | ||
42 | - | ||
43 | -const getVideoTypeByUrl = (url = '') => { | ||
44 | - if (!url) return; | ||
45 | - try { | ||
46 | - const { protocol, pathname } = new URL(url) | ||
47 | - if (protocol.startsWith('rtsp:')) return VideoPlayerTypeEnum.flv | ||
48 | - const reg = /[^.]\w*$/ | ||
49 | - const mathValue = pathname.match(reg) || [] | ||
50 | - const ext = (mathValue[0] as keyof typeof VideoPlayerTypeEnum) || 'webm' | ||
51 | - const type = VideoPlayerTypeEnum[ext] | ||
52 | - return type ? type : VideoPlayerTypeEnum.webm | ||
53 | - } catch (error) { | ||
54 | - console.error(error) | ||
55 | - return VideoPlayerTypeEnum.webm | ||
56 | - } | ||
57 | -} | ||
58 | - | ||
59 | -// video实例对象 | ||
60 | -const videoPlayer = shallowRef<videojs.Player | null>(null) | ||
61 | -const playerContainerElRef = shallowRef<HTMLElement | null>(null) | ||
62 | - | ||
63 | -const fingerprintResult = ref<Nullable<GetResult>>(null) | ||
64 | - | ||
65 | -//options配置 | ||
66 | -const options: VideoJsPlayerOptions & Recordable = { | ||
67 | - language: 'zh-CN', // 设置语言 | ||
68 | - controls: true, // 是否显示控制条 | ||
69 | - autoplay: !!props.autoPlay, // 是否自动播放 | ||
70 | - fluid: false, // 自适应宽高 | ||
71 | - poster: props?.avatar || '', | ||
72 | - sources: [], | ||
73 | - muted: !!props.autoPlay, | ||
74 | - userActions: { | ||
75 | - hotkeys: true | ||
76 | - }, | ||
77 | - techOrder: ['html5', 'flvjs'], | ||
78 | - flvjs: { | ||
79 | - mediaDataSource: { | ||
80 | - isLive: true, | ||
81 | - cors: true, | ||
82 | - withCredentials: false, | ||
83 | - hasAudio: false | ||
84 | - }, | ||
85 | - config: { | ||
86 | - autoCleanupSourceBuffer: true | ||
87 | - } | ||
88 | - } | ||
89 | -} | ||
90 | - | ||
91 | -const { getResult } = useFingerprint() | ||
92 | - | ||
93 | -async function getSource() { | ||
94 | - fingerprintResult.value = await getResult() | ||
95 | - let src = props.sourceSrc || '' | ||
96 | - if (isRtspProtocol(props.sourceSrc!)) { | ||
97 | - src = getOpenFlvPlayUrl(src, unref(fingerprintResult)?.visitorId || '') | ||
98 | - } | ||
99 | - return [ | ||
100 | - { | ||
101 | - type: getVideoTypeByUrl(props.sourceSrc), | ||
102 | - src | ||
103 | - } | ||
104 | - ] | ||
105 | -} | ||
106 | - | ||
107 | -function createVideoElement() { | ||
108 | - if (!unref(playerContainerElRef)) return | ||
109 | - unref(playerContainerElRef)!.innerHTML = '' | ||
110 | - const video = document.createElement('video') | ||
111 | - video.setAttribute('crossOrigin', 'anonymous') | ||
112 | - video.style.setProperty('width', '100%') | ||
113 | - video.style.setProperty('height', '100%') | ||
114 | - video.classList.add('video-js', 'my-video', 'vjs-theme-city', 'vjs-big-play-centered') | ||
115 | - unref(playerContainerElRef)?.appendChild(video) | ||
116 | - return video | ||
117 | -} | ||
118 | - | ||
119 | - | ||
120 | -// 初始化videojs | ||
121 | -const createVideoPlayer = async () => { | ||
122 | - if (unref(videoPlayer)) dispose() | ||
123 | - | ||
124 | - options.sources = await getSource() | ||
125 | - | ||
126 | - if (isRtspProtocol(props.sourceSrc || '')) { | ||
127 | - options.flvjs = { | ||
128 | - ...(options.flvjs || {}), | ||
129 | - config: { | ||
130 | - headers: { | ||
131 | - 'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}` | ||
132 | - } | ||
133 | - } | ||
134 | - } | ||
135 | - } | ||
136 | - const video = createVideoElement() | ||
137 | - if (!video) return | ||
138 | - | ||
139 | - videoPlayer.value = videojs(video!, options) //fix 修复videojs解决直播延时的问题 | ||
140 | - | ||
141 | - videoPlayer.value?.on('timeupdate', function () { | ||
142 | - // 计算表最新推流的时间和现在播放器播放推流的时间 | ||
143 | - let differTime = | ||
144 | - (unref(videoPlayer))!.buffered()?.end(0) - | ||
145 | - (unref(videoPlayer))!.currentTime() // 差值小于1.5s时根据1倍速进行播放 | ||
146 | - if (differTime < 1.5) { | ||
147 | - videoPlayer.value?.playbackRate(1) | ||
148 | - } // 差值大于1.5s小于10s根据1.2倍速进行播放 | ||
149 | - if (differTime < 10 && differTime > 1.5) { | ||
150 | - videoPlayer.value?.playbackRate(1.2) | ||
151 | - } // 差值大于10s时进行重新加载直播流 | ||
152 | - if (differTime > 10) { | ||
153 | - createVideoPlayer() | ||
154 | - } | ||
155 | - }) | ||
156 | -} | ||
157 | - | ||
158 | -// watch( | ||
159 | -// () => props.sourceSrc, | ||
160 | -// async () => { | ||
161 | -// (props as any ).sourceSrc = '' | ||
162 | -// if(!props.sourceSrc) return; | ||
163 | -// await nextTick(); | ||
164 | -// if(unref(fingerprintResult)!.visitorId!) { | ||
165 | -// closeFlvPlay(props.sourceSrc!, unref(fingerprintResult)!.visitorId!) | ||
166 | -// } | ||
167 | -// videoPlayer.value?.src(''); | ||
168 | -// createVideoPlayer() | ||
169 | - | ||
170 | -// if (props.sourceSrc) { | ||
171 | -// reloadSource({ src: props.sourceSrc, type: getVideoTypeByUrl(props.sourceSrc) }) | ||
172 | -// } | ||
173 | -// } | ||
174 | -// ) | ||
175 | - | ||
176 | -watch( | ||
177 | - () => props.autoPlay, | ||
178 | - async (newData: boolean) => { | ||
179 | - if (newData) { | ||
180 | - handleVideoPlay() | ||
181 | - } else { | ||
182 | - videoPlayer.value?.pause() | ||
183 | - } | ||
184 | - }, | ||
185 | -) | ||
186 | - | ||
187 | -// onMounted(() => { | ||
188 | -// createVideoPlayer() | ||
189 | -// }) | ||
190 | - | ||
191 | -onUnmounted(() => { | ||
192 | - if (props.sourceSrc) { | ||
193 | - closeFlvPlay(props.sourceSrc, unref(fingerprintResult)!.visitorId!) | ||
194 | - } | ||
195 | - handleVideoDispose() | ||
196 | -}) | ||
197 | - | ||
198 | - | ||
199 | -function anewInit() { | ||
200 | - createVideoPlayer() | ||
201 | -} | ||
202 | - | ||
203 | -function reloadSource(sources: string | videojs.Tech.SourceObject | videojs.Tech.SourceObject[]) { | ||
204 | - if (!unref(videoPlayer)) return | ||
205 | - unref(videoPlayer)?.pause() | ||
206 | - unref(videoPlayer)?.src(sources) | ||
207 | - unref(videoPlayer)?.load() | ||
208 | - unref(videoPlayer)?.play() | ||
209 | -} | ||
210 | - | ||
211 | -function dispose() { | ||
212 | - unref(videoPlayer)?.dispose() | ||
213 | - videoPlayer.value = null | ||
214 | -} | ||
215 | - | ||
216 | -//播放 | ||
217 | -const handleVideoPlay = () => videoPlayer.value?.play() | ||
218 | - | ||
219 | -//暂停和销毁 | ||
220 | -const handleVideoDispose = () => videoPlayer.value?.dispose() | ||
221 | - | ||
222 | -defineExpose({ | ||
223 | - dispose, | ||
224 | - reloadSource, | ||
225 | - anewInit, | ||
226 | -}) | ||
227 | - | ||
228 | -</script> | ||
229 | - | ||
230 | -<style lang="scss" scoped> | ||
231 | -.go-content-box { | ||
232 | - display: flex; | ||
233 | - align-items: center; | ||
234 | - justify-content: center; | ||
235 | - | ||
236 | - .my-video { | ||
237 | - width: 100% !important; | ||
238 | - height: 100% !important; | ||
239 | - position: relative; | ||
240 | - } | ||
241 | -} | ||
242 | -</style> | ||
243 | -<style> | ||
244 | -.vjs-poster { | ||
245 | - background-size: 100% !important; | ||
246 | -} | ||
247 | -</style> |
@@ -2,6 +2,11 @@ import { PublicConfigClass } from '@/packages/public' | @@ -2,6 +2,11 @@ import { PublicConfigClass } from '@/packages/public' | ||
2 | import { CreateComponentType } from '@/packages/index.d' | 2 | import { CreateComponentType } from '@/packages/index.d' |
3 | import { SingleCameraConfig } from './index' | 3 | import { SingleCameraConfig } from './index' |
4 | import cloneDeep from 'lodash/cloneDeep' | 4 | import cloneDeep from 'lodash/cloneDeep' |
5 | +import {StreamType} from "@/components/Video/src/types"; | ||
6 | +import {useFingerprint} from "@/utils/external/useFingerprint"; | ||
7 | +import {getOpenFlvPlayUrl, getVideoControlStart} from "@/api/external/flvPlay"; | ||
8 | +import {getVideoUrl} from "@/api/external/common"; | ||
9 | +import {CameraRecord} from "@/api/external/common/model"; | ||
5 | 10 | ||
6 | export enum sourceTypeEnum { | 11 | export enum sourceTypeEnum { |
7 | CUSTOM = 'custom', | 12 | CUSTOM = 'custom', |
@@ -13,6 +18,11 @@ export enum sourceTypeNameEnum { | @@ -13,6 +18,11 @@ export enum sourceTypeNameEnum { | ||
13 | PLATFORM = '平台获取' | 18 | PLATFORM = '平台获取' |
14 | } | 19 | } |
15 | 20 | ||
21 | +export enum FluoriteMideaProtocolEnum { | ||
22 | + HLS = 2, | ||
23 | + FLV = 4, | ||
24 | +} | ||
25 | + | ||
16 | export enum VideoPlayerTypeEnum { | 26 | export enum VideoPlayerTypeEnum { |
17 | m3u8 = 'application/x-mpegURL', | 27 | m3u8 = 'application/x-mpegURL', |
18 | mp4 = 'video/mp4', | 28 | mp4 = 'video/mp4', |
@@ -32,6 +42,7 @@ export interface videoListInterface { | @@ -32,6 +42,7 @@ export interface videoListInterface { | ||
32 | deviceId: string | 42 | deviceId: string |
33 | customUrl: string | 43 | customUrl: string |
34 | params: GBT28181Params | 44 | params: GBT28181Params |
45 | + playProtocol?: number | ||
35 | } | 46 | } |
36 | 47 | ||
37 | export interface GBT28181Params { | 48 | export interface GBT28181Params { |
@@ -53,6 +64,7 @@ export interface Dataset { | @@ -53,6 +64,7 @@ export interface Dataset { | ||
53 | deviceId?: string | 64 | deviceId?: string |
54 | id?: string | 65 | id?: string |
55 | value?: string | 66 | value?: string |
67 | + playProtocol?: number | ||
56 | } | 68 | } |
57 | 69 | ||
58 | export const option = { | 70 | export const option = { |
@@ -70,3 +82,42 @@ export default class Config extends PublicConfigClass implements CreateComponent | @@ -70,3 +82,42 @@ export default class Config extends PublicConfigClass implements CreateComponent | ||
70 | public chartConfig = cloneDeep(SingleCameraConfig) | 82 | public chartConfig = cloneDeep(SingleCameraConfig) |
71 | public option = cloneDeep(option) | 83 | public option = cloneDeep(option) |
72 | } | 84 | } |
85 | + | ||
86 | +export const isRtspProtocol = (url: string) => { | ||
87 | + const reg = /^rtsp:\/\//g; | ||
88 | + return reg.test(url); | ||
89 | +}; | ||
90 | + | ||
91 | +export async function getPlayUrl( | ||
92 | + params: CameraRecord | ||
93 | +): Promise<{ url: string; type: StreamType }> { | ||
94 | + const { accessMode } = params; | ||
95 | + if (accessMode === AccessMode.ManuallyEnter) { | ||
96 | + const { videoUrl } = params; | ||
97 | + if (params.videoUrl) { | ||
98 | + const isRTSPPlay = isRtspProtocol(videoUrl); | ||
99 | + | ||
100 | + if (isRTSPPlay) { | ||
101 | + const { getResult } = useFingerprint(); | ||
102 | + const fingerprint = await getResult(); | ||
103 | + return { url: getOpenFlvPlayUrl(videoUrl, fingerprint.visitorId), type: 'flv' }; | ||
104 | + } else { | ||
105 | + return { url: videoUrl, type: 'auto' }; | ||
106 | + } | ||
107 | + } | ||
108 | + } else if (accessMode === AccessMode.GBT28181) { | ||
109 | + const { deviceId, channelNo } = params?.params || {}; | ||
110 | + const result = await getVideoControlStart({ channelId: channelNo!, deviceId: deviceId! }); | ||
111 | + return { url: result.data.flv, type: 'flv' }; | ||
112 | + } else { | ||
113 | + const { id, playProtocol } = params; | ||
114 | + const result = await getVideoUrl(id); | ||
115 | + const type: StreamType = | ||
116 | + playProtocol === FluoriteMideaProtocolEnum.FLV | ||
117 | + ? 'flv' | ||
118 | + : playProtocol === FluoriteMideaProtocolEnum.HLS | ||
119 | + ? 'hls' | ||
120 | + : 'auto'; | ||
121 | + return { url: result.data.url, type }; | ||
122 | + } | ||
123 | +} |
@@ -97,7 +97,7 @@ const handleUpdateTreeValue = (value: string) => { | @@ -97,7 +97,7 @@ const handleUpdateTreeValue = (value: string) => { | ||
97 | const getVideoLists = async (organizationId: string) => { | 97 | const getVideoLists = async (organizationId: string) => { |
98 | const res = await getVideoList({ organizationId }) | 98 | const res = await getVideoList({ organizationId }) |
99 | if (!res) return | 99 | if (!res) return |
100 | - videoOptions.value = res?.data?.map((item: videoListInterface) => { | 100 | + videoOptions.value = res?.data?.map((item) => { |
101 | return { | 101 | return { |
102 | label: item.name, | 102 | label: item.name, |
103 | value: item.id, | 103 | value: item.id, |
@@ -105,8 +105,9 @@ const getVideoLists = async (organizationId: string) => { | @@ -105,8 +105,9 @@ const getVideoLists = async (organizationId: string) => { | ||
105 | id: item.id, | 105 | id: item.id, |
106 | accessMode: item.accessMode, | 106 | accessMode: item.accessMode, |
107 | channelId: item.accessMode === AccessMode.GBT28181 ? item?.params?.channelNo : '', //参数只给gbt28181使用 | 107 | channelId: item.accessMode === AccessMode.GBT28181 ? item?.params?.channelNo : '', //参数只给gbt28181使用 |
108 | - deviceId: item.accessMode === AccessMode.GBT28181 ? item?.params?.deviceId : '' //参数只给gbt28181使用 | ||
109 | - } | 108 | + deviceId: item.accessMode === AccessMode.GBT28181 ? item?.params?.deviceId : '', //参数只给gbt28181使用 |
109 | + playProtocol: item?.playProtocol | ||
110 | + } as any | ||
110 | }) | 111 | }) |
111 | } | 112 | } |
112 | 113 |
1 | <template> | 1 | <template> |
2 | <div> | 2 | <div> |
3 | - <n-spin size="medium" :show="showLoading" :content-style="{ background: 'red' }"> | ||
4 | - <template #description> 视频正在努力加载中...... </template> | ||
5 | - <div> | ||
6 | - <VideoPlay ref="videoPlayerRef" :baseSize="{ w, h }" :sourceSrc="sourceUrl" :autoPlay="option.autoplay" | ||
7 | - :avatar="option.poster" /> | ||
8 | - </div> | 3 | + <n-spin size="medium" :show="showLoading" class="player-spin"> |
4 | + <template #description> 视频正在努力加载中......</template> | ||
5 | + <XGPlayer :url="sourceUrl" :stream-type="playType" | ||
6 | + :config="{width: '100%', height: '100%', poster: option.poster}" | ||
7 | + :auto-play="option.autoplay"/> | ||
9 | </n-spin> | 8 | </n-spin> |
10 | </div> | 9 | </div> |
11 | </template> | 10 | </template> |
12 | <script setup lang="ts"> | 11 | <script setup lang="ts"> |
13 | -import { PropType, toRefs, shallowReactive, watch, ref } from 'vue' | ||
14 | -import { CreateComponentType } from '@/packages/index.d' | ||
15 | -import { AccessMode, Dataset, option as configOption, sourceTypeEnum } from './config' | ||
16 | -import { VideoPlay } from './components' | ||
17 | -import { getVideoControlStart } from '@/api/external/flvPlay' | ||
18 | -import { getVideoUrl } from '@/api/external/common' | 12 | +import {PropType, toRefs, shallowReactive, watch, ref} from 'vue' |
13 | +import {CreateComponentType} from '@/packages/index.d' | ||
14 | +import {Dataset, getPlayUrl, option as configOption} from './config' | ||
15 | +import {XGPlayer} from '@/components/Video' | ||
16 | +import {StreamType} from "@/components/Video/src/types"; | ||
17 | +import {CameraRecord} from "@/api/external/common/model"; | ||
19 | 18 | ||
20 | const props = defineProps({ | 19 | const props = defineProps({ |
21 | chartConfig: { | 20 | chartConfig: { |
@@ -26,9 +25,9 @@ const props = defineProps({ | @@ -26,9 +25,9 @@ const props = defineProps({ | ||
26 | 25 | ||
27 | const showLoading = ref(false) | 26 | const showLoading = ref(false) |
28 | 27 | ||
29 | -const { w, h } = toRefs(props.chartConfig.attr) | 28 | +const {w, h} = toRefs(props.chartConfig.attr) |
30 | 29 | ||
31 | -const { autoplay, dataset, poster, customVideoUrl } = toRefs(props.chartConfig.option as typeof configOption) | 30 | +const {autoplay, dataset, poster, customVideoUrl} = toRefs(props.chartConfig.option as typeof configOption) |
32 | 31 | ||
33 | const option = shallowReactive({ | 32 | const option = shallowReactive({ |
34 | dataset: configOption.dataset, | 33 | dataset: configOption.dataset, |
@@ -37,87 +36,52 @@ const option = shallowReactive({ | @@ -37,87 +36,52 @@ const option = shallowReactive({ | ||
37 | }) | 36 | }) |
38 | 37 | ||
39 | const sourceUrl = ref('') | 38 | const sourceUrl = ref('') |
40 | -const videoPlayerRef = ref<InstanceType<typeof VideoPlay> | null>() | ||
41 | - | ||
42 | -// 针对萤石云或者海康威视,根据视频id获取播放流地址 | ||
43 | -const getVideoUrlById = async (id: string) => { | ||
44 | - const res = await getVideoUrl(id) | ||
45 | - if (!res) return | ||
46 | - const { url } = res.data | ||
47 | - return url | ||
48 | -} | ||
49 | - | ||
50 | -// 针对gbt28181,根据设备id和通道号获取播放流地址 | ||
51 | -const getVideoControlList = async (deviceId: string, channelId: string) => { | ||
52 | - const { | ||
53 | - data: { flv } | ||
54 | - } = await getVideoControlStart({ | ||
55 | - deviceId, | ||
56 | - channelId | ||
57 | - }) | ||
58 | - return flv | ||
59 | -} | ||
60 | - | ||
61 | -// 针对自定义地址,直接获取地址 | ||
62 | -const getCustomUrl = (url: string) => { | ||
63 | - return url | ||
64 | -} | 39 | +const playType = ref<StreamType>() |
65 | 40 | ||
66 | 41 | ||
67 | async function getPlaySource(params: Dataset) { | 42 | async function getPlaySource(params: Dataset) { |
68 | try { | 43 | try { |
69 | showLoading.value = true | 44 | showLoading.value = true |
70 | - | ||
71 | - const { accessMode, id, deviceId, channelId, customUrl } = params | ||
72 | - if (accessMode === AccessMode.Streaming && id) { | ||
73 | - return await getVideoUrlById(id!) | ||
74 | - } else if (accessMode === AccessMode.GBT28181 && deviceId && channelId) { | ||
75 | - return await getVideoControlList(deviceId!, channelId!) | ||
76 | - } else { | ||
77 | - return getCustomUrl(customUrl!) | ||
78 | - } | 45 | + const {id, channelId, deviceId, accessMode, customUrl, playProtocol} = params |
46 | + if (!accessMode) return | ||
47 | + const {type, url} = await getPlayUrl({ | ||
48 | + id: id, | ||
49 | + accessMode: accessMode, | ||
50 | + playProtocol: playProtocol, | ||
51 | + videoUrl: customUrl, | ||
52 | + params: { | ||
53 | + deviceId: deviceId, | ||
54 | + channelNo: channelId, | ||
55 | + }, | ||
56 | + } as unknown as CameraRecord) | ||
57 | + sourceUrl.value = url | ||
58 | + playType.value = type | ||
79 | } finally { | 59 | } finally { |
80 | showLoading.value = false | 60 | showLoading.value = false |
81 | } | 61 | } |
82 | } | 62 | } |
83 | 63 | ||
84 | watch( | 64 | watch( |
85 | - () => dataset?.value, | ||
86 | - async (newData) => { | ||
87 | - videoPlayerRef.value?.dispose() | ||
88 | - sourceUrl.value = await getPlaySource(newData) | ||
89 | - videoPlayerRef.value?.anewInit() | ||
90 | - }, | ||
91 | - { | ||
92 | - immediate: true | ||
93 | - } | ||
94 | -) | ||
95 | - | ||
96 | -watch( | ||
97 | - () => customVideoUrl.value, | ||
98 | - (newData) => { | ||
99 | - if(newData){ | ||
100 | - videoPlayerRef.value?.dispose() | ||
101 | - sourceUrl.value = newData; | ||
102 | - videoPlayerRef.value?.anewInit() | 65 | + () => dataset?.value, |
66 | + async (newData) => { | ||
67 | + getPlaySource(newData) | ||
68 | + }, | ||
69 | + { | ||
70 | + immediate: true | ||
103 | } | 71 | } |
104 | - }, | ||
105 | - { | ||
106 | - immediate: true | ||
107 | - } | ||
108 | ) | 72 | ) |
109 | 73 | ||
110 | -watch( | ||
111 | - () => [poster.value, autoplay.value], | ||
112 | - newData => { | ||
113 | - option.poster = newData.at(-2) as string | ||
114 | - option.autoplay = newData.at(-1) as boolean | ||
115 | - }, | ||
116 | - { | ||
117 | - immediate: true | ||
118 | - } | ||
119 | -) | ||
120 | </script> | 74 | </script> |
121 | 75 | ||
122 | <style lang="scss" scoped> | 76 | <style lang="scss" scoped> |
77 | +.player-spin { | ||
78 | + width: 100%; | ||
79 | + height: 100%; | ||
80 | + @include deep() { | ||
81 | + .n-spin-content { | ||
82 | + width: 100%; | ||
83 | + height: 100%; | ||
84 | + } | ||
85 | + } | ||
86 | +} | ||
123 | </style> | 87 | </style> |