-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
Is your feature request related to a problem? Please describe.
I need to observe the screen of a remote device. The screen ist recorded with an USB camera and ffplay
from another headless device and shared with ThightVNC and noVNC. The interval of relevant changes on the screen is very slow.
As mentioned in 6.4.3 FramebufferUpdateRequest (rfbproto-3.8.pdf) I need to regulate the rate at which it sends
incremental FramebufferUpdateRequests to avoid hogging the network to reduce network traffic over a metered connection.
Describe the solution you'd like
A new property delayIncrementalUpdateRequests
on RFB instances delays incremental FramebufferUpdateRequest
(client to server) messages after FramebufferUpdate
(server to client) messages.
If you like the idea I would integrate my current implementation (see below) into rfb.js
and vnc.html
and create a PR.
Describe alternatives you've considered
None.
Additional context
Below is a redacted screenshot from a page with two <iframe>
s to the same (no)VNC server.
- https://example.org/properties={"compressionLevel":9,"qualityLevel":4}
- https://example.org/properties={"compressionLevel":9,"qualityLevel":4,"delayIncrementalUpdateRequests":500}
Over about 11 minutes I could reduce the transferred bytes to 16% from 93.56 MiB to 14.72 MiB and the number of messages (TCP frames/IP packets) to 14% from 90523 to 12052 with a delay of 500 ms.

Here is my current implementation to fix this in this use case:
const $$screen = document.getElementById('screen');
const rfbUrl = location.origin.replace(/^http/, 'ws') + location.pathname.replace(/[^/]*$/, 'websockify');
// FIXME: DO NOT DO THIS IS REAL LIFE!!!
const rfbOptions = JSON.parse(decodeURIComponent(location.search.match(/[?&]options=([^&]*)/)[1]));
const rfbProperties = JSON.parse(decodeURIComponent(location.search.match(/[?&]properties=([^&]*)/)[1]));
const rfb = Object.assign(new RFB($$screen, rfbUrl, rfbOptions), rfbProperties);
// 6.4.3 FramebufferUpdateRequest (rfbproto-3.8.pdf)
//
// In the case of a fast client, the client may want to regulate the rate at which it sends
// incremental FramebufferUpdateRequests to avoid hogging the network.
//
if (rfb.delayIncrementalUpdateRequests) {
RFB.messages.fbUpdateRequest = ((fbUpdateRequest)=>{
let timer = null;
let delay = +rfb.delayIncrementalUpdateRequests;
return (sock, incremental, x, y, w, h) => {
if (!incremental) {
fbUpdateRequest(sock, incremental, x, y, w, h);
return;
}
if (timer !== null) {
return;
}
timer = setTimeout(() => {
timer = null;
fbUpdateRequest(sock, incremental, x, y, w, h);
}, delay);
};
})(RFB.messages.fbUpdateRequest);
}
BTW: The measurements are carried out with my WebSocketGuardian.
<script src="./core/WebSocketGuardian.js"></script>
<script type="module">
const encoder = new TextEncoder();
const startTime = Date.now();
let bytes = 0;
let bytesSent = 0;
let bytesRcvd = 0;
let messgages = 0;
let messgagesSent = 0;
let messgagesRcvd = 0;
WebSocket.onSendMessage = (event) => {
const data = event.data;
let length = typeof data === 'string' ? encoder.encode( data ).length : data.length;
length += length <= 125 ? 6 : length <= 0x7fff ? 8 : 14;
bytesSent += length;
bytes += length;
++messgagesSent;
++messgages;
updateStatus();
}
WebSocket.onRecvMessage = (event) => {
const data = event.data;
let length = typeof data === 'string' ? encoder.encode( data ).length : data.byteLength;
length += length <= 125 ? 6 : length <= 0x7fff ? 8 : 14;
bytesRcvd += length;
bytes += length;
++messgagesRcvd;
++messgages;
updateStatus();
}
</script>