Added WebM conversion feature to recordings player.

This commit is contained in:
Ylian Saint-Hilaire 2021-07-04 15:53:51 -07:00
parent 2ae6dced9e
commit b8f7fb16ec
4 changed files with 1170 additions and 2 deletions

View File

@ -138,6 +138,7 @@ var CreateAgentRemoteDesktop = function (canvasid, scrolldiv) {
for (var i = 0; i < obj.PendingOperations.length; i++) { // && KillDraw < tilesDrawn for (var i = 0; i < obj.PendingOperations.length; i++) { // && KillDraw < tilesDrawn
var Msg = obj.PendingOperations[i]; var Msg = obj.PendingOperations[i];
if (Msg[0] == (obj.TilesDrawn + 1)) { if (Msg[0] == (obj.TilesDrawn + 1)) {
if (obj.onPreDrawImage != null) obj.onPreDrawImage(); // Notify that we are about to draw on the canvas.
if (Msg[1] == 1) { obj.ProcessCopyRectMsg(Msg[2]); } if (Msg[1] == 1) { obj.ProcessCopyRectMsg(Msg[2]); }
else if (Msg[1] == 2) { obj.Canvas.drawImage(Msg[2], obj.rotX(Msg[3], Msg[4]), obj.rotY(Msg[3], Msg[4])); delete Msg[2]; } else if (Msg[1] == 2) { obj.Canvas.drawImage(Msg[2], obj.rotX(Msg[3], Msg[4]), obj.rotY(Msg[3], Msg[4])); delete Msg[2]; }
obj.PendingOperations.splice(i, 1); obj.PendingOperations.splice(i, 1);

View File

@ -33,6 +33,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
obj.sparecache = {}; obj.sparecache = {};
obj.ZRLEfirst = 1; obj.ZRLEfirst = 1;
obj.onScreenSizeChange = null; obj.onScreenSizeChange = null;
//obj.onPreDrawImage = null;
obj.frameRateDelay = 0; obj.frameRateDelay = 0;
// ###BEGIN###{DesktopRotation} // ###BEGIN###{DesktopRotation}
obj.noMouseRotate = false; obj.noMouseRotate = false;
@ -179,6 +180,7 @@ var CreateAmtRemoteDesktop = function (divid, scrolldiv) {
if (obj.acc.byteLength < 4) return; if (obj.acc.byteLength < 4) return;
obj.state = 100 + accview.getUint16(2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state. obj.state = 100 + accview.getUint16(2); // Read the number of tiles that are going to be sent, add 100 and use that as our protocol state.
cmdsize = 4; cmdsize = 4;
if (obj.onPreDrawImage != null) obj.onPreDrawImage(); // Notify that we are about to draw on the canvas.
break; break;
case 2: // This is the bell, do nothing. case 2: // This is the bell, do nothing.
cmdsize = 1; cmdsize = 1;

File diff suppressed because it is too large Load Diff

View File

@ -17,13 +17,16 @@
<script type="text/javascript" src="scripts/zlib-inflate{{min}}.js"></script> <script type="text/javascript" src="scripts/zlib-inflate{{min}}.js"></script>
<script type="text/javascript" src="scripts/zlib-adler32{{min}}.js"></script> <script type="text/javascript" src="scripts/zlib-adler32{{min}}.js"></script>
<script type="text/javascript" src="scripts/zlib-crc32{{min}}.js"></script> <script type="text/javascript" src="scripts/zlib-crc32{{min}}.js"></script>
<script keeplink=1 type="text/javascript" src="scripts/webm-writer.js"></script>
<script keeplink=1 type="text/javascript" src="scripts/filesaver.min.js"></script>
</head> </head>
<body style="overflow:hidden;background-color:black"> <body style="overflow:hidden;background-color:black">
<div id=p11 class="noselect" style="overflow:hidden"> <div id=p11 class="noselect" style="overflow:hidden">
<div id=deskarea0> <div id=deskarea0>
<div id=deskarea1 class="areaHead"> <div id=deskarea1 class="areaHead">
<div class="toright2"> <div class="toright2">
<div class='deskareaicon' title="Toggle View Mode" onclick="toggleAspectRatio(1)">&#8690;</div> <div class='deskareaicon' title="Toggle View Mode" onclick="toggleAspectRatio(1)">&#8690;</div>&nbsp;
<input id="ConvertAsWebM" style="display:none" type=button value="Convert to WebM" onclick="saveAsWebMfile()">&nbsp;
</div> </div>
<div> <div>
<input id="OpenFileButton" type=button value="Open File..." onclick="openfile()"> <input id="OpenFileButton" type=button value="Open File..." onclick="openfile()">
@ -105,8 +108,26 @@
var waitTimerArgs = null; var waitTimerArgs = null;
var deskAspectRatio = 0; var deskAspectRatio = 0;
var currentDeltaTimeTotalSec = 0; var currentDeltaTimeTotalSec = 0;
var videoWriter = null;
var videoWriterLastFrame = null;
var videoWriterCurrentFrame = null;
var browser = null;
function start() { function start() {
// Detect what browser is in use
browser = (function (agent) {
switch (true) {
case agent.indexOf("edge") > -1: return "MS Edge (EdgeHtml)";
case agent.indexOf("edg") > -1: return "MS Edge Chromium";
case agent.indexOf("opr") > -1 && !!window.opr: return "opera";
case agent.indexOf("chrome") > -1 && !!window.chrome: return "chrome";
case agent.indexOf("trident") > -1: return "Internet Explorer";
case agent.indexOf("firefox") > -1: return "firefox";
case agent.indexOf("safari") > -1: return "safari";
default: return "other";
}
})(window.navigator.userAgent.toLowerCase());
window.onresize = deskAdjust; window.onresize = deskAdjust;
document.ondrop = ondrop; document.ondrop = ondrop;
document.ondragover = ondragover; document.ondragover = ondragover;
@ -237,6 +258,7 @@
} }
QV('DeskParent', true); QV('DeskParent', true);
QV('TermParent', false); QV('TermParent', false);
QV('ConvertAsWebM', false);
if (recFileMetadata.protocol == 1) { if (recFileMetadata.protocol == 1) {
// MeshCentral remote terminal // MeshCentral remote terminal
recFileProtocol = 1; recFileProtocol = 1;
@ -256,8 +278,10 @@
recFileStartTime = recFileLastTime = time; recFileStartTime = recFileLastTime = time;
agentDesktop = CreateAgentRemoteDesktop('Desk'); agentDesktop = CreateAgentRemoteDesktop('Desk');
agentDesktop.onScreenSizeChange = deskAdjust; agentDesktop.onScreenSizeChange = deskAdjust;
agentDesktop.onPreDrawImage = preCanvasDraw;
agentDesktop.State = 3; agentDesktop.State = 3;
deskAdjust(); deskAdjust();
QV('ConvertAsWebM', browser == 'chrome'); // Only show the "Convert to WebM button when in Chrome
} }
else if (recFileMetadata.protocol == 101) { else if (recFileMetadata.protocol == 101) {
// Intel AMT Redirection // Intel AMT Redirection
@ -269,6 +293,7 @@
recFileStartTime = recFileLastTime = time; recFileStartTime = recFileLastTime = time;
amtDesktop = CreateAmtRemoteDesktop('Desk'); amtDesktop = CreateAmtRemoteDesktop('Desk');
amtDesktop.onScreenSizeChange = deskAdjust; amtDesktop.onScreenSizeChange = deskAdjust;
amtDesktop.onPreDrawImage = preCanvasDraw;
if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; } if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
amtDesktop.State = 3; amtDesktop.State = 3;
amtDesktop.Start(); amtDesktop.Start();
@ -284,11 +309,13 @@
recFileStartTime = recFileLastTime = time; recFileStartTime = recFileLastTime = time;
amtDesktop = CreateAmtRemoteDesktop('Desk'); amtDesktop = CreateAmtRemoteDesktop('Desk');
amtDesktop.onScreenSizeChange = deskAdjust; amtDesktop.onScreenSizeChange = deskAdjust;
amtDesktop.onPreDrawImage = preCanvasDraw;
amtDesktop.State = 3; amtDesktop.State = 3;
amtDesktop.Start(); amtDesktop.Start();
if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; } if (recFileMetadata.bpp) { amtDesktop.bpp = recFileMetadata.bpp; }
amtDesktop.state = 3; amtDesktop.state = 3;
deskAdjust(); deskAdjust();
QV('ConvertAsWebM', browser == 'chrome'); // Only show the "Convert to WebM button when in Chrome
} }
QV('metadatadiv', true); QV('metadatadiv', true);
QH('metadatadiv', x); QH('metadatadiv', x);
@ -299,7 +326,7 @@
function processBlock(type, flags, time, data) { function processBlock(type, flags, time, data) {
if (type < 0) { pause(); return; } if (type < 0) { pause(); return; }
var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('PlaySpeed').value)); var waitTime = Math.round((time - recFileLastTime) * parseFloat(Q('PlaySpeed').value));
if (waitTime < 5) { if ((waitTime < 5) || (videoWriter != null)) {
processBlockEx(type, flags, time, data); processBlockEx(type, flags, time, data);
} else { } else {
waitTimerArgs = [type, flags, time, data] waitTimerArgs = [type, flags, time, data]
@ -311,6 +338,20 @@
if ((playing == false) && (forced !== true)) return; if ((playing == false) && (forced !== true)) return;
var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0; var flagBinary = (flags & 1) != 0, flagUser = (flags & 2) != 0;
// End of the stream, close the WebM converter
if ((type == 3) && (videoWriter != null)) {
preCanvasDraw();
videoWriter.complete().then(function (webMBlob) {
saveAs(webMBlob, recFile.name.replace('.mcrec', '.webm'));
videoWriter = null;
QE('PlaySpeed', true);
QE('SeekBackwardButton', true);
QE('SeekForwardButton', true);
QE('ConvertAsWebM', true);
QE('OpenFileButton', true);
});
}
if (type == 2) { if (type == 2) {
// Update the clock // Update the clock
recFileLastTime = time; recFileLastTime = time;
@ -323,6 +364,10 @@
var secs = Math.floor(deltaTimeTotalSec % 60); var secs = Math.floor(deltaTimeTotalSec % 60);
QH('timespan', pad2(hrs) + ':' + pad2(mins) + ':' + pad2(secs)) QH('timespan', pad2(hrs) + ':' + pad2(mins) + ':' + pad2(secs))
} }
// Set the initial time on the WebM movie writer if needed
if (videoWriterLastFrame == null) { videoWriterLastFrame = time; }
videoWriterCurrentFrame = time;
} }
if ((type == 2) && flagBinary && !flagUser) { if ((type == 2) && flagBinary && !flagUser) {
@ -463,6 +508,29 @@
if (e.key == '0') { pause(); restart(); haltEvent(e); } if (e.key == '0') { pause(); restart(); haltEvent(e); }
} }
// Convert the remote desktop or KVM file into a WebM movie file.
function saveAsWebMfile() {
videoWriterLastFrame = null;
videoWriter = new WebMWriter({ quality: 0.60, frameDuration: 10, transparent: false });
restart();
play();
QE('PlayButton', false);
QE('PauseButton', false);
QE('RestartButton', false);
QE('PlaySpeed', false);
QE('SeekBackwardButton', false);
QE('SeekForwardButton', false);
QE('ConvertAsWebM', false);
QE('OpenFileButton', false);
}
function preCanvasDraw() {
if (videoWriter) {
var delta = videoWriterCurrentFrame - videoWriterLastFrame;
if (delta >= 100) { videoWriter.addFrame(Q('Desk'), delta); videoWriterLastFrame = videoWriterCurrentFrame; }
}
}
function openfile() { function openfile() {
var x = '<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />'; var x = '<input type=file name=files id=p2fileinput style=width:100% accept=".mcrec" onchange="openfileChanged()" />';
setDialogMode(2, "Open File...", 3, openfileEx, x); setDialogMode(2, "Open File...", 3, openfileEx, x);