diff --git a/pkg/messages/messages.go b/pkg/messages/messages.go
index ed1cd2a..1477dbf 100644
--- a/pkg/messages/messages.go
+++ b/pkg/messages/messages.go
@@ -140,6 +140,7 @@ const (
VideoFlagMutualOpen // viewer wants to auto-open viewers' cameras
VideoFlagOnlyVIP // can only shows as active to VIP members
VideoFlagInvited // user invites another to watch their camera
+ VideoFlagNoWatermark // user opts out of QR code watermark protection
)
// Presence message templates.
diff --git a/src/App.vue b/src/App.vue
index 4cdba81..4893770 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -739,6 +739,9 @@ export default {
if (settings.autoMuteWebcams === true) {
this.webcam.autoMuteWebcams = true;
}
+ if (settings.videoNoWatermark === true) {
+ this.webcam.noWatermark = true;
+ }
// Misc preferences
if (settings.usePolling != undefined) {
@@ -2726,13 +2729,6 @@ export default {
Camera Settings
-
- The settings on this tab will be relevant only when you are already
- broadcasting your camera. They allow you to modify your broadcast settings
- while you are already live (for example, to change your mutual camera
- preference or select another audio/video device to broadcast from).
-
-
+
@@ -268,6 +268,9 @@ video {
}
/* Watermark image */
+.is-no-watermark {
+ display: none;
+}
.watermark {
position: absolute;
top: 0;
diff --git a/src/lib/LocalStorage.js b/src/lib/LocalStorage.js
index 70d4caa..5644740 100644
--- a/src/lib/LocalStorage.js
+++ b/src/lib/LocalStorage.js
@@ -19,6 +19,7 @@ const keys = {
'rememberExpresslyClosed': Boolean,
'autoMuteWebcams': Boolean, // automatically mute other peoples' webcam audio feeds
'videoAutoShare': Boolean, // automatically share your webcam on page load
+ 'videoNoWatermark': Boolean, // user does not want watermark protection
// Booleans
'usePolling': Boolean, // use the polling API instead of WebSocket
diff --git a/src/lib/VideoFlag.js b/src/lib/VideoFlag.js
index d00499f..5866e66 100644
--- a/src/lib/VideoFlag.js
+++ b/src/lib/VideoFlag.js
@@ -8,6 +8,7 @@ const VideoFlag = {
MutualOpen: 1 << 5,
VipOnly: 1 << 6,
Invited: 1 << 7,
+ NoWatermark: 1 << 8,
};
export default VideoFlag;
diff --git a/src/lib/WebRTC.js b/src/lib/WebRTC.js
index 1c047df..ea25b39 100644
--- a/src/lib/WebRTC.js
+++ b/src/lib/WebRTC.js
@@ -75,6 +75,7 @@ class WebRTCController {
mutualOpen: false, // user wants to open video mutually
nonExplicit: false, // user prefers not to see explicit cameras
vipOnly: false, // only show camera to fellow VIP users
+ noWatermark: false, // user opts out of their own QR code watermark
rememberExpresslyClosed: true, // remember cams we expressly closed
autoMuteWebcams: false, // auto-mute other cameras' audio channels
@@ -247,6 +248,12 @@ class WebRTCController {
}
}
},
+ "webcam.noWatermark": function () {
+ LocalStorage.set('videoNoWatermark', this.webcam.noWatermark);
+ if (this.webcam.active) {
+ this.sendMe();
+ }
+ },
"webcam.rememberExpresslyClosed": function () {
LocalStorage.set('rememberExpresslyClosed', this.webcam.rememberExpresslyClosed);
},
@@ -273,6 +280,7 @@ class WebRTCController {
if (this.webcam.mutualOpen) status |= this.VideoFlag.MutualOpen;
if (this.webcam.nonExplicit) status |= this.VideoFlag.NonExplicit;
if (this.webcam.vipOnly && this.isVIP) status |= this.VideoFlag.VipOnly;
+ if (this.webcam.noWatermark) status |= this.VideoFlag.NoWatermark;
return status;
},
anyVideosOpen() {
@@ -669,9 +677,13 @@ class WebRTCController {
`My camera is: ${this.webcam.active ? 'active': 'not active'}`,
);
+ // If the user leaves our watching list, play the sound.
+ if (this.webcam.watching[msg.username] != undefined) {
+ this.playSound("Unwatch");
+ }
+
// The user has closed our video feed.
delete (this.webcam.watching[msg.username]);
- this.playSound("Unwatch");
this.cleanupPeerConnections();
},
sendWatch(username, watching) {
@@ -702,6 +714,14 @@ class WebRTCController {
return false;
},
+ isUsernameCamNoWatermark(username) {
+ // returns true if the user is broadcasting and has the NoWatermark flag set.
+ if (this.whoMap[username] != undefined && this.whoMap[username].video & this.VideoFlag.NoWatermark) {
+ return true;
+ }
+ return false;
+ },
+
/**********************************
* Front-end methods and handlers *
**********************************/
diff --git a/web/templates/about.html b/web/templates/about.html
index 19fb8dc..61fe2e5 100644
--- a/web/templates/about.html
+++ b/web/templates/about.html
@@ -470,6 +470,37 @@
full screen view.
+
+ What are the QR codes on top of webcams?
+
+
+
+
+ Most webcams will display a QR code in the corner by default, as well as a translucent copy of the
+ QR code over the center/middle of the video.
+
+
+
+ These QR codes (or 'watermarks') are a safety feature to deter people from screen recording each
+ other's webcams on here. There is no technical measure that a web page could take to prevent
+ screen recording from being possible (or to even detect that it is happening), so the QR code
+ watermarks instead will "tag" the recorded video with the current viewer's username and the
+ current date.
+
+
+
+ The idea is that if a webcam recording ends up leaked online, the QR code will be captured in
+ the video and it can be used to trace back who exactly recorded that webcam
+ and when, so that the user may be banned from the chat room and/or be reported to a relevant law
+ enforcement agency as necessary for spreading non-consensual 'revenge porn' online.
+
+
+
+ If you do not care about the risk that anyone could record your webcam, then you
+ may "opt out" of the QR code watermark being applied to your own video. The setting for
+ this can be found in the Chat Settings "Camera" tab.
+
+