Commit d81f3f3a7d840952aca9fca11655e9435b09588b

Authored by guzijian
1 parent d34371a9

feat: 新增水印

src/main/resources/Aserver.keystore 0 → 100644
No preview for this file type
src/main/resources/application-dev.yml
@@ -13,13 +13,13 @@ spring: @@ -13,13 +13,13 @@ spring:
13 # REDIS数据库配置 13 # REDIS数据库配置
14 redis: 14 redis:
15 # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1 15 # [必须修改] Redis服务器IP, REDIS安装在本机的,使用127.0.0.1
16 - host: 127.0.0.1 16 + host: 192.168.168.124
17 # [必须修改] 端口号 17 # [必须修改] 端口号
18 port: 6379 18 port: 6379
19 # [可选] 数据库 DB 19 # [可选] 数据库 DB
20 database: 7 20 database: 7
21 # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接 21 # [可选] 访问密码,若你的redis服务器没有设置密码,就不需要用密码去连接
22 - password: luna 22 +# password: luna
23 # [可选] 超时时间 23 # [可选] 超时时间
24 timeout: 10000 24 timeout: 10000
25 # mysql数据源 25 # mysql数据源
@@ -30,9 +30,9 @@ spring: @@ -30,9 +30,9 @@ spring:
30 master: 30 master:
31 type: com.zaxxer.hikari.HikariDataSource 31 type: com.zaxxer.hikari.HikariDataSource
32 driver-class-name: com.mysql.cj.jdbc.Driver 32 driver-class-name: com.mysql.cj.jdbc.Driver
33 - url: jdbc:mysql://127.0.0.1:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true 33 + url: jdbc:mysql://192.168.168.124:3306/wvp2?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false&allowMultiQueries=true
34 username: root 34 username: root
35 - password: root123 35 + password: guzijian
36 hikari: 36 hikari:
37 connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数 37 connection-timeout: 20000 # 是客户端等待连接池连接的最大毫秒数
38 initialSize: 50 # 连接池初始化连接数 38 initialSize: 50 # 连接池初始化连接数
@@ -60,36 +60,36 @@ sip: @@ -60,36 +60,36 @@ sip:
60 # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4 60 # 如果要监听多张网卡,可以使用逗号分隔多个IP, 例如: 192.168.1.4,10.0.0.4
61 # 如果不明白,就使用0.0.0.0,大部分情况都是可以的 61 # 如果不明白,就使用0.0.0.0,大部分情况都是可以的
62 # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。 62 # 请不要使用127.0.0.1,任何包括localhost在内的域名都是不可以的。
63 - ip: 172.19.128.50 63 + ip: 192.168.168.124
64 # [可选] 28181服务监听的端口 64 # [可选] 28181服务监听的端口
65 - port: 8116 65 + port: 5060
66 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) 66 # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007)
67 # 后两位为行业编码,定义参照附录D.3 67 # 后两位为行业编码,定义参照附录D.3
68 # 3701020049标识山东济南历下区 信息行业接入 68 # 3701020049标识山东济南历下区 信息行业接入
69 # [可选] 69 # [可选]
70 - domain: 4101050000 70 + domain: 3402000000
71 # [可选] 71 # [可选]
72 - id: 41010500002000000001 72 + id: 34020000002000000001
73 # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验 73 # [可选] 默认设备认证密码,后续扩展使用设备单独密码, 移除密码将不进行校验
74 - password: bajiuwulian1006 74 + password: 12345678
75 # 是否存储alarm信息 75 # 是否存储alarm信息
76 alarm: true 76 alarm: true
77 77
78 #zlm 默认服务器配置 78 #zlm 默认服务器配置
79 media: 79 media:
80 - id: zlmediakit-local 80 + id: your_server_id
81 # [必须修改] zlm服务器的内网IP 81 # [必须修改] zlm服务器的内网IP
82 - ip: 172.19.128.50 82 + ip: 192.168.168.124
83 # [必须修改] zlm服务器的http.port 83 # [必须修改] zlm服务器的http.port
84 - http-port: 9092 84 + http-port: 9090
85 # [可选] 返回流地址时的ip,置空使用 media.ip 85 # [可选] 返回流地址时的ip,置空使用 media.ip
86 - stream-ip: 172.19.128.50 86 + stream-ip: 61.169.120.202
87 # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip 87 # [可选] wvp在国标信令中使用的ip,此ip为摄像机可以访问到的ip, 置空使用 media.ip
88 - sdp-ip: 172.19.128.50 88 + sdp-ip: 192.168.168.124
89 # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip 89 # [可选] zlm服务器的hook所使用的IP, 默认使用sip.ip
90 - hook-ip: 172.19.128.50 90 + hook-ip: 192.168.168.124
91 # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置 91 # [可选] zlm服务器的http.sslport, 置空使用zlm配置文件配置
92 - http-ssl-port: 1443 92 + http-ssl-port: 7443
93 # [可选] zlm服务器的hook.admin_params=secret 93 # [可选] zlm服务器的hook.admin_params=secret
94 secret: 10000 94 secret: 10000
95 # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 95 # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
@@ -97,9 +97,9 @@ media: @@ -97,9 +97,9 @@ media:
97 # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 97 # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
98 enable: true 98 enable: true
99 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 99 # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功
100 - port-range: 50000,50300 # 端口范围 100 + port-range: 30000,30500 # 端口范围
101 # [可选] 国标级联在此范围内选择端口发送媒体流, 101 # [可选] 国标级联在此范围内选择端口发送媒体流,
102 - send-port-range: 50000,50300 # 端口范围 102 + send-port-range: 30000,30500 # 端口范围
103 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 103 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用
104 record-assist-port: 18081 104 record-assist-port: 18081
105 # [根据业务需求配置] 105 # [根据业务需求配置]
web_src/build/utils.js
@@ -95,7 +95,7 @@ exports.createNotifierCallback = () => { @@ -95,7 +95,7 @@ exports.createNotifierCallback = () => {
95 title: packageConfig.name, 95 title: packageConfig.name,
96 message: severity + ': ' + error.name, 96 message: severity + ': ' + error.name,
97 subtitle: filename || '', 97 subtitle: filename || '',
98 - icon: path.join(__dirname, 'logo.png') 98 + icon: path.join(__dirname, 'favicon_tuohua.ico')
99 }) 99 })
100 } 100 }
101 } 101 }
web_src/config/index.js
@@ -12,14 +12,14 @@ module.exports = { @@ -12,14 +12,14 @@ module.exports = {
12 assetsPublicPath: '/', 12 assetsPublicPath: '/',
13 proxyTable: { 13 proxyTable: {
14 '/debug': { 14 '/debug': {
15 - target: 'http://127.0.0.1:18082', 15 + target: 'https://192.169.1.31:18080',
16 changeOrigin: true, 16 changeOrigin: true,
17 pathRewrite: { 17 pathRewrite: {
18 '^/debug': '/' 18 '^/debug': '/'
19 } 19 }
20 }, 20 },
21 '/static/snap': { 21 '/static/snap': {
22 - target: 'http://127.0.0.1:18082', 22 + target: 'https://192.169.1.31:18080',
23 changeOrigin: true, 23 changeOrigin: true,
24 // pathRewrite: { 24 // pathRewrite: {
25 // '^/static/snap': '/static/snap' 25 // '^/static/snap': '/static/snap'
web_src/src/components/Login.vue
1 <template> 1 <template>
2 -<div class="login" id="login">  
3 - <div class="limiter">  
4 - <div class="container-login100">  
5 - <div class="wrap-login100">  
6 - <span class="login100-form-title p-b-26">WVP视频平台</span>  
7 - <span class="login100-form-title p-b-48">  
8 - <i class="fa fa-video-camera"></i>  
9 - </span> 2 + <div class="login-container">
  3 + <div class="login" id="login">
  4 + <div class="limiter">
  5 + <div class="container-login100">
  6 + <div class="wrap-login100">
  7 + <span class="login100-form-title p-b-26">综合视频平台</span>
  8 + <span class="login100-form-title p-b-48">
  9 + <i class="fa fa-video-camera"></i>
  10 + </span>
10 11
11 - <div class="wrap-input100 validate-input" data-validate = "Valid email is: a@b.c">  
12 - <input :class="'input100 ' + (username==''?'':'has-val')" type="text" v-model="username" name="username">  
13 - <span class="focus-input100" data-placeholder="用户名"></span>  
14 - </div> 12 + <div class="wrap-input100 validate-input" data-validate="Valid email is: a@b.c">
  13 + <input :class="'input100 ' + (username == '' ? '' : 'has-val')" type="text" v-model="username"
  14 + name="username">
  15 + <span class="focus-input100" data-placeholder="用户名"></span>
  16 + </div>
15 17
16 - <div class="wrap-input100 validate-input" data-validate="Enter password">  
17 - <span class="btn-show-pass">  
18 - <i :class="'fa ' + (!showPassword?'fa-eye':'fa-eye-slash')" @click="showPassword = !showPassword"></i>  
19 - </span>  
20 - <input :class="'input100 ' + (password==''?'':'has-val')" :type="(!showPassword?'password':'text')" v-model="password" name="password">  
21 - <span class="focus-input100" data-placeholder="密码"></span>  
22 - </div> 18 + <div class="wrap-input100 validate-input" data-validate="Enter password">
  19 + <span class="btn-show-pass">
  20 + <i :class="'fa ' + (!showPassword ? 'fa-eye' : 'fa-eye-slash')"
  21 + @click="showPassword = !showPassword"></i>
  22 + </span>
  23 + <input :class="'input100 ' + (password == '' ? '' : 'has-val')"
  24 + :type="(!showPassword ? 'password' : 'text')" v-model="password" name="password">
  25 + <span class="focus-input100" data-placeholder="密码"></span>
  26 + </div>
23 27
24 - <div class="container-login100-form-btn">  
25 - <div class="wrap-login100-form-btn" :class="{'login-loading': isLoging}" v-loading="isLoging" element-loading-background="rgb(0 0 0 / 0%);" element-loading-custom-class="login-loading-class">  
26 - <div class="login100-form-bgbtn"></div>  
27 - <button class="login100-form-btn" @click="login">登录</button> 28 + <div class="container-login100-form-btn">
  29 + <div class="wrap-login100-form-btn" :class="{ 'login-loading': isLoging }" v-loading="isLoging"
  30 + element-loading-background="rgb(0 0 0 / 0%);" element-loading-custom-class="login-loading-class">
  31 + <div class="login100-form-bgbtn"></div>
  32 + <button class="login100-form-btn" @click="login">登录</button>
  33 + </div>
28 </div> 34 </div>
29 </div> 35 </div>
  36 + </div>
  37 + <div class="company-author">
  38 + <span>@2024 上海巴士拓华科技发展有限公司 版权所有</span>
  39 + </div>
30 </div> 40 </div>
31 </div> 41 </div>
32 </div> 42 </div>
33 -</div> 43 +
34 </template> 44 </template>
35 45
36 <script> 46 <script>
37 -import crypto from 'crypto' 47 +import crypto from 'crypto';
38 import userService from "./service/UserService"; 48 import userService from "./service/UserService";
39 export default { 49 export default {
40 name: 'Login', 50 name: 'Login',
41 - data(){  
42 - return { 51 + data() {
  52 + return {
43 isLoging: false, 53 isLoging: false,
44 showPassword: false, 54 showPassword: false,
45 loginLoading: false, 55 loginLoading: false,
46 - username: '',  
47 - password: ''  
48 - } 56 + username: '',
  57 + password: ''
  58 + }
49 }, 59 },
50 - created(){ 60 + created() {
51 var that = this; 61 var that = this;
52 - document.onkeydown = function(e) { 62 + document.onkeydown = function (e) {
53 var key = window.event.keyCode; 63 var key = window.event.keyCode;
54 if (key == 13) { 64 if (key == 13) {
55 that.login(); 65 that.login();
56 } 66 }
57 } 67 }
58 }, 68 },
59 - methods:{ 69 + methods: {
60 70
61 - //登录逻辑  
62 - login(){  
63 - if(this.username!='' && this.password!=''){  
64 - this.toLogin();  
65 - }  
66 - }, 71 + //登录逻辑
  72 + login() {
  73 + if (this.username != '' && this.password != '') {
  74 + this.toLogin();
  75 + }
  76 + },
67 77
68 - //登录请求  
69 - toLogin(){  
70 - //需要想后端发送的登录参数  
71 - let loginParam = {  
72 - username: this.username,  
73 - password: crypto.createHash('md5').update(this.password, "utf8").digest('hex')  
74 - } 78 + //登录请求
  79 + toLogin() {
  80 + //需要想后端发送的登录参数
  81 + let loginParam = {
  82 + username: this.username,
  83 + password: crypto.createHash('md5').update(this.password, "utf8").digest('hex')
  84 + }
75 var that = this; 85 var that = this;
76 //设置在登录状态 86 //设置在登录状态
77 this.isLoging = true; 87 this.isLoging = true;
78 - let timeoutTask = setTimeout(()=>{ 88 + let timeoutTask = setTimeout(() => {
79 that.$message.error("登录超时"); 89 that.$message.error("登录超时");
80 that.isLoging = false; 90 that.isLoging = false;
81 }, 1000) 91 }, 1000)
82 92
83 this.$axios({ 93 this.$axios({
84 - method: 'get',  
85 - url:"/api/user/login", 94 + method: 'get',
  95 + url: "/api/user/login",
86 params: loginParam 96 params: loginParam
87 }).then(function (res) { 97 }).then(function (res) {
88 window.clearTimeout(timeoutTask) 98 window.clearTimeout(timeoutTask)
89 console.log(res); 99 console.log(res);
90 console.log("登录成功"); 100 console.log("登录成功");
91 - if (res.data.code === 0 ) {  
92 - userService.setUser(res.data.data)  
93 - //登录成功后  
94 - that.cancelEnterkeyDefaultAction();  
95 - that.$router.push('/');  
96 - }else{  
97 - that.isLoging = false;  
98 - that.$message({  
99 - showClose: true,  
100 - message: '登录失败,用户名或密码错误',  
101 - type: 'error'  
102 - });  
103 - } 101 + if (res.data.code === 0) {
  102 + userService.setUser(res.data.data)
  103 + //登录成功后
  104 + that.cancelEnterkeyDefaultAction();
  105 + that.$router.push('/');
  106 + } else {
  107 + that.isLoging = false;
  108 + that.$message({
  109 + showClose: true,
  110 + message: '登录失败,用户名或密码错误',
  111 + type: 'error'
  112 + });
  113 + }
104 }).catch(function (error) { 114 }).catch(function (error) {
105 console.log(error) 115 console.log(error)
106 window.clearTimeout(timeoutTask) 116 window.clearTimeout(timeoutTask)
@@ -108,8 +118,8 @@ export default { @@ -108,8 +118,8 @@ export default {
108 that.isLoging = false; 118 that.isLoging = false;
109 }); 119 });
110 }, 120 },
111 - cancelEnterkeyDefaultAction: function() {  
112 - document.onkeydown = function(e) { 121 + cancelEnterkeyDefaultAction: function () {
  122 + document.onkeydown = function (e) {
113 var key = window.event.keyCode; 123 var key = window.event.keyCode;
114 if (key == 13) { 124 if (key == 13) {
115 return false; 125 return false;
@@ -119,4 +129,11 @@ export default { @@ -119,4 +129,11 @@ export default {
119 } 129 }
120 } 130 }
121 </script> 131 </script>
122 - 132 +<style scoped>
  133 +.container-login100 {
  134 + background: url("../assets/login-bg.jpg") no-repeat;
  135 + background-size: 100% 100%;
  136 + width: 100vw;
  137 + height: 100vh;
  138 +}
  139 +</style>
web_src/src/components/common/easyPlayer.vue
1 <template> 1 <template>
2 - <div id="easyplayer" ></div> 2 + <div id="easyplayer"></div>
3 </template> 3 </template>
4 4
5 <script> 5 <script>
  6 +import userService from '../service/UserService';
6 export default { 7 export default {
7 - name: 'player',  
8 - data() {  
9 - return {  
10 - easyPlayer: null  
11 - }; 8 + name: 'player',
  9 + data() {
  10 + return {
  11 + timer: null,
  12 + easyPlayer: null,
  13 + config: {
  14 + userName: userService.getUser().username,
  15 + nowTime: "2024-03-01 12:00:00"
  16 + } // 水印
  17 + };
  18 + },
  19 + props: ['videoUrl', 'error', 'hasaudio', 'height'],
  20 + mounted() {
  21 + let paramUrl = decodeURIComponent(this.$route.params.url)
  22 + this.$nextTick(() => {
  23 + if (typeof (this.videoUrl) == "undefined") {
  24 + this.videoUrl = paramUrl;
  25 + }
  26 + console.log("初始化时的地址为: " + this.videoUrl)
  27 + this.play(this.videoUrl)
  28 + })
  29 + },
  30 + watch: {
  31 + videoUrl(newData, oldData) {
  32 + this.play(newData)
12 }, 33 },
13 - props: ['videoUrl', 'error', 'hasaudio', 'height'],  
14 - mounted () {  
15 - let paramUrl = decodeURIComponent(this.$route.params.url)  
16 - this.$nextTick(() =>{  
17 - if (typeof (this.videoUrl) == "undefined") {  
18 - this.videoUrl = paramUrl;  
19 - }  
20 - console.log("初始化时的地址为: " + this.videoUrl)  
21 - this.play(this.videoUrl)  
22 - }) 34 + immediate: true
  35 + },
  36 + methods: {
  37 + play: function (url) {
  38 + console.log(this.height)
  39 + if (this.easyPlayer != null) {
  40 + this.easyPlayer.destroy();
  41 + }
  42 + if (typeof (this.height) == "undefined") {
  43 + this.height = false
  44 + }
  45 + this.easyPlayer = new WasmPlayer(null, 'easyplayer', this.eventcallbacK, { Height: this.height })
  46 + this.easyPlayer.play(url, 1)
23 }, 47 },
24 - watch:{  
25 - videoUrl(newData, oldData){  
26 - this.play(newData)  
27 - },  
28 - immediate:true  
29 - },  
30 - methods: {  
31 - play: function (url) {  
32 - console.log(this.height)  
33 - if (this.easyPlayer != null) {  
34 - this.easyPlayer.destroy();  
35 - }  
36 - if (typeof (this.height) == "undefined") {  
37 - this.height = false  
38 - }  
39 - this.easyPlayer = new WasmPlayer(null, 'easyplayer', this.eventcallbacK, {Height: this.height})  
40 - this.easyPlayer.play(url, 1)  
41 - },  
42 - pause: function () {  
43 - this.easyPlayer.destroy();  
44 - this.easyPlayer = null  
45 - },  
46 - eventcallbacK: function(type, message) {  
47 - // console.log("player 事件回调")  
48 - // console.log(type)  
49 - // console.log(message)  
50 - }  
51 - },  
52 - destroyed() { 48 + pause: function () {
53 this.easyPlayer.destroy(); 49 this.easyPlayer.destroy();
  50 + this.easyPlayer = null
54 }, 51 },
  52 + eventcallbacK: function (type, message) {
  53 + // console.log("player 事件回调")
  54 + // console.log(type)
  55 + // console.log(message)
  56 + }
  57 + },
  58 + destroyed() {
  59 + this.easyPlayer.destroy();
  60 + },
55 } 61 }
56 </script> 62 </script>
57 63
58 <style> 64 <style>
59 - .LodingTitle {  
60 - min-width: 70px;  
61 - }  
62 - /* 隐藏logo */  
63 - .iconqingxiLOGO {  
64 - display: none !important;  
65 - } 65 +.LodingTitle {
  66 + min-width: 70px;
  67 +}
66 68
  69 +/* 隐藏logo */
  70 +.iconqingxiLOGO {
  71 + display: none !important;
  72 +}
67 </style> 73 </style>
web_src/src/components/common/jessibuca.vue
1 <template> 1 <template>
2 <div ref="container" @dblclick="fullscreenSwich" 2 <div ref="container" @dblclick="fullscreenSwich"
3 - style="width:100%; height: 100%; background-color: #000000;margin:0 auto;position: relative;"> 3 + style="width:100%; height: 100%; background-color: #000000;margin:0 auto;position: relative;">
4 <div class="buttons-box" id="buttonsBox"> 4 <div class="buttons-box" id="buttonsBox">
5 <div class="buttons-box-left"> 5 <div class="buttons-box-left">
6 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i> 6 <i v-if="!playing" class="iconfont icon-play jessibuca-btn" @click="playBtnClick"></i>
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>--> 14 <!-- <i class="iconfont icon-file-record1 jessibuca-btn"></i>-->
15 <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>--> 15 <!-- <i class="iconfont icon-xiangqing2 jessibuca-btn" ></i>-->
16 <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot" 16 <i class="iconfont icon-camera1196054easyiconnet jessibuca-btn" @click="screenshot"
17 - style="font-size: 1rem !important"></i> 17 + style="font-size: 1rem !important"></i>
18 <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i> 18 <i class="iconfont icon-shuaxin11 jessibuca-btn" @click="playBtnClick"></i>
19 <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i> 19 <i v-if="!fullscreen" class="iconfont icon-weibiaoti10 jessibuca-btn" @click="fullscreenSwich"></i>
20 <i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i> 20 <i v-if="fullscreen" class="iconfont icon-weibiaoti11 jessibuca-btn" @click="fullscreenSwich"></i>
@@ -24,6 +24,9 @@ @@ -24,6 +24,9 @@
24 </template> 24 </template>
25 25
26 <script> 26 <script>
  27 +import watermark from '../../../utils/waterMark.js';
  28 +import userService from '../service/UserService';
  29 +
27 let jessibucaPlayer = {}; 30 let jessibucaPlayer = {};
28 export default { 31 export default {
29 name: 'jessibuca', 32 name: 'jessibuca',
@@ -43,6 +46,11 @@ export default { @@ -43,6 +46,11 @@ export default {
43 rotate: 0, 46 rotate: 0,
44 vod: true, // 点播 47 vod: true, // 点播
45 forceNoOffscreen: false, 48 forceNoOffscreen: false,
  49 + watermarkTimer: null,
  50 + config: {
  51 + userName: userService.getUser().username,
  52 + nowTime: "2024-03-01 12:00:00"
  53 + } // 水印
46 }; 54 };
47 }, 55 },
48 props: ['videoUrl', 'error', 'hasAudio', 'height'], 56 props: ['videoUrl', 'error', 'hasAudio', 'height'],
@@ -56,6 +64,7 @@ export default { @@ -56,6 +64,7 @@ export default {
56 this.videoUrl = paramUrl; 64 this.videoUrl = paramUrl;
57 } 65 }
58 this.btnDom = document.getElementById("buttonsBox"); 66 this.btnDom = document.getElementById("buttonsBox");
  67 + this.watermarkTimer = watermark(this.$refs.container, this.config);
59 }) 68 })
60 }, 69 },
61 // mounted() { 70 // mounted() {
@@ -140,7 +149,7 @@ export default { @@ -140,7 +149,7 @@ export default {
140 wcsUseVideoRender: true 149 wcsUseVideoRender: true
141 }; 150 };
142 console.log("Jessibuca -> options: ", options); 151 console.log("Jessibuca -> options: ", options);
143 - jessibucaPlayer[this._uid] = new window.Jessibuca({...options}); 152 + jessibucaPlayer[this._uid] = new window.Jessibuca({ ...options });
144 153
145 let jessibuca = jessibucaPlayer[this._uid]; 154 let jessibuca = jessibucaPlayer[this._uid];
146 let _this = this; 155 let _this = this;
@@ -267,6 +276,7 @@ export default { @@ -267,6 +276,7 @@ export default {
267 this.playing = false; 276 this.playing = false;
268 this.loaded = false; 277 this.loaded = false;
269 this.performance = ""; 278 this.performance = "";
  279 + clearInterval(this.watermarkTimer);
270 }, 280 },
271 } 281 }
272 </script> 282 </script>
web_src/src/components/dialog/rtcPlayer.vue
@@ -2,36 +2,49 @@ @@ -2,36 +2,49 @@
2 <div id="rtcPlayer"> 2 <div id="rtcPlayer">
3 <video id='webRtcPlayerBox' controls autoplay style="text-align:left;"> 3 <video id='webRtcPlayerBox' controls autoplay style="text-align:left;">
4 Your browser is too old which doesn't support HTML5 video. 4 Your browser is too old which doesn't support HTML5 video.
5 - </video> 5 + </video>
6 </div> 6 </div>
7 </template> 7 </template>
8 8
9 <script> 9 <script>
  10 +import watermark from '../../../utils/waterMark.js';
  11 +import userService from '../service/UserService';
10 let webrtcPlayer = null; 12 let webrtcPlayer = null;
11 export default { 13 export default {
12 name: 'rtcPlayer', 14 name: 'rtcPlayer',
13 data() { 15 data() {
14 return { 16 return {
15 - timer: null 17 + timer: null,
  18 + watermarkTimer: null,
  19 + config: {
  20 + userName: userService.getUser().username,
  21 + nowTime: "2024-03-01 12:00:00"
  22 + }
16 }; 23 };
17 }, 24 },
18 props: ['videoUrl', 'error', 'hasaudio'], 25 props: ['videoUrl', 'error', 'hasaudio'],
19 - mounted () {  
20 - let paramUrl = decodeURIComponent(this.$route.params.url)  
21 - this.$nextTick(() =>{  
22 - if (typeof (this.videoUrl) == "undefined") {  
23 - this.videoUrl = paramUrl;  
24 - }  
25 - console.log("初始化时的地址为: " + this.videoUrl)  
26 - this.play(this.videoUrl) 26 + mounted() {
  27 + let paramUrl = decodeURIComponent(this.$route.params.url)
  28 + this.$nextTick(() => {
  29 + if (typeof (this.videoUrl) == "undefined") {
  30 + this.videoUrl = paramUrl;
  31 + }
  32 + console.log("初始化时的地址为: " + this.videoUrl)
  33 + this.play(this.videoUrl)
27 }) 34 })
28 }, 35 },
29 - watch:{  
30 - videoUrl(newData, oldData){ 36 + watch: {
  37 + videoUrl(newData, oldData) {
31 this.pause(); 38 this.pause();
32 this.play(newData); 39 this.play(newData);
33 }, 40 },
34 - immediate:true 41 + immediate: true
  42 + },
  43 + created() {
  44 + this.$nextTick(() => {
  45 + this.rtcPlayer = document.getElementById("rtcPlayer");
  46 + this.watermarkTimer = watermark(this.rtcPlayer, this.config);
  47 + })
35 }, 48 },
36 methods: { 49 methods: {
37 play: function (url) { 50 play: function (url) {
@@ -45,22 +58,22 @@ export default { @@ -45,22 +58,22 @@ export default {
45 videoEnable: true, 58 videoEnable: true,
46 recvOnly: true, 59 recvOnly: true,
47 }) 60 })
48 - webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR,(e)=>{// ICE 协商出错 61 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ICE_CANDIDATE_ERROR, (e) => {// ICE 协商出错
49 console.error('ICE 协商出错') 62 console.error('ICE 协商出错')
50 this.eventcallbacK("ICE ERROR", "ICE 协商出错") 63 this.eventcallbacK("ICE ERROR", "ICE 协商出错")
51 }); 64 });
52 65
53 - webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS,(e)=>{//获取到了远端流,可以播放  
54 - console.log('播放成功',e.streams) 66 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_REMOTE_STREAMS, (e) => {//获取到了远端流,可以播放
  67 + console.log('播放成功', e.streams)
55 this.eventcallbacK("playing", "播放成功") 68 this.eventcallbacK("playing", "播放成功")
56 }); 69 });
57 70
58 - webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED,(e)=>{// offer anwser 交换失败  
59 - console.error('offer anwser 交换失败',e) 71 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_OFFER_ANWSER_EXCHANGE_FAILED, (e) => {// offer anwser 交换失败
  72 + console.error('offer anwser 交换失败', e)
60 this.eventcallbacK("OFFER ANSWER ERROR ", "offer anwser 交换失败") 73 this.eventcallbacK("OFFER ANSWER ERROR ", "offer anwser 交换失败")
61 - if (e.code ==-400 && e.msg=="流不存在"){ 74 + if (e.code == -400 && e.msg == "流不存在") {
62 console.log("流不存在") 75 console.log("流不存在")
63 - this.timer = setTimeout(()=>{ 76 + this.timer = setTimeout(() => {
64 this.webrtcPlayer.close(); 77 this.webrtcPlayer.close();
65 this.play(url) 78 this.play(url)
66 }, 100) 79 }, 100)
@@ -68,7 +81,7 @@ export default { @@ -68,7 +81,7 @@ export default {
68 } 81 }
69 }); 82 });
70 83
71 - webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM,(s)=>{// 获取到了本地流 84 + webrtcPlayer.on(ZLMRTCClient.Events.WEBRTC_ON_LOCAL_STREAM, (s) => {// 获取到了本地流
72 85
73 // document.getElementById('selfVideo').srcObject=s; 86 // document.getElementById('selfVideo').srcObject=s;
74 this.eventcallbacK("LOCAL STREAM", "获取到了本地流") 87 this.eventcallbacK("LOCAL STREAM", "获取到了本地流")
@@ -82,7 +95,7 @@ export default { @@ -82,7 +95,7 @@ export default {
82 } 95 }
83 96
84 }, 97 },
85 - eventcallbacK: function(type, message) { 98 + eventcallbacK: function (type, message) {
86 console.log("player 事件回调") 99 console.log("player 事件回调")
87 console.log(type) 100 console.log(type)
88 console.log(message) 101 console.log(message)
@@ -90,25 +103,28 @@ export default { @@ -90,25 +103,28 @@ export default {
90 }, 103 },
91 destroyed() { 104 destroyed() {
92 clearTimeout(this.timer); 105 clearTimeout(this.timer);
  106 + clearInterval(this.watermarkTimer);
93 }, 107 },
94 } 108 }
95 </script> 109 </script>
96 110
97 <style> 111 <style>
98 - .LodingTitle {  
99 - min-width: 70px;  
100 - }  
101 - #rtcPlayer{  
102 - width: 100%;  
103 - }  
104 - #webRtcPlayerBox{  
105 - width: 100%;  
106 - max-height: 56vh;  
107 - background-color: #000;  
108 - }  
109 - /* 隐藏logo */  
110 - /* .iconqingxiLOGO { 112 +.LodingTitle {
  113 + min-width: 70px;
  114 +}
  115 +
  116 +#rtcPlayer {
  117 + width: 100%;
  118 +}
  119 +
  120 +#webRtcPlayerBox {
  121 + width: 100%;
  122 + max-height: 56vh;
  123 + background-color: #000;
  124 +}
  125 +
  126 +/* 隐藏logo */
  127 +/* .iconqingxiLOGO {
111 display: none !important; 128 display: none !important;
112 } */ 129 } */
113 -  
114 </style> 130 </style>
web_src/static/js/config.js
1 1
2 -window.baseUrl = "" 2 +window.baseUrl = "https://192.169.1.31:18080"
3 3
4 // map组件全局参数, 注释此内容可以关闭地图功能 4 // map组件全局参数, 注释此内容可以关闭地图功能
5 window.mapParam = { 5 window.mapParam = {