Skip to content

Instantly share code, notes, and snippets.

@t57ser
Last active May 19, 2023 09:06
Show Gist options
  • Save t57ser/919ff9c9fe623b51fde41772bf4c9207 to your computer and use it in GitHub Desktop.
Save t57ser/919ff9c9fe623b51fde41772bf4c9207 to your computer and use it in GitHub Desktop.
electron getCaptureHandle
body {
text-align: center;
}
h2 {
font-size: 10vmin;
}
pre {
font-size: 4vmin;
white-space: pre-line;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
http-equiv="origin-trial"
content="AjsgeCuaC4qHMu0mU/pBJMzCfCpGQdmeZuUI++8+W7PN4zMxWHuFpT10JQImqukj8f/HDg4kBSRQ3n6V+Gk+5gYAAABfeyJvcmlnaW4iOiJodHRwczovL2NhcHR1cmUtaGFuZGxlLmdsaXRjaC5tZTo0NDMiLCJmZWF0dXJlIjoiQ2FwdHVyZUhhbmRsZSIsImV4cGlyeSI6MTY1ODg3OTk5OX0="
/>
<title>CAPTURE ME</title>
<link rel="stylesheet" href="./captured.css" />
<script src="./captured.js" defer></script>
</head>
<body>
<h2>Slide #<span id="slideNum">1</span></h2>
<pre id="logs"></pre>
<script>
window.onerror = (message) => {
logs.textContent += `${message}\r\n`;
};
</script>
</body>
</html>
// Exposes a random handle and the origin to any capturing web app.
const config = {
handle: crypto.randomUUID(), // A randomly generated UUID.
exposeOrigin: true, // Expose own origin.
permittedOrigins: ["*"], // Observable by any capturing web app.
};
navigator.mediaDevices.setCaptureHandleConfig(config);
const broadcastChannel = new BroadcastChannel("capture-handle");
broadcastChannel.onmessage = async (message) => {
if (message.data.handle != config.handle) return;
// Play a sliding animation
await document.body.animate([{ transform: "translate(-100%)" }], {
duration: 500,
}).finished;
// Then update slide number
if (message.data.direction == "prev") {
slideNum.textContent = Math.max(0, parseInt(slideNum.textContent) - 1);
} else if (message.data.direction == "next") {
slideNum.textContent = parseInt(slideNum.textContent) + 1;
}
};
logs.textContent = `navigator.mediaDevices.setCaptureHandleConfig(\r\n${JSON.stringify(
config
)});`;
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
}
h1 {
margin-block-end: 0;
}
a {
display: block;
margin-block-end: 1.4em;
}
video {
width: calc(100% - 8px);
border: 4px solid;
border-radius: 16px;
}
@media screen and (min-width: 640px) {
body {
margin: 2em auto;
max-width: calc(640px - 2em);
}
}
#logs {
margin-top: 1em;
white-space: pre-wrap;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta
http-equiv="origin-trial"
content="AjsgeCuaC4qHMu0mU/pBJMzCfCpGQdmeZuUI++8+W7PN4zMxWHuFpT10JQImqukj8f/HDg4kBSRQ3n6V+Gk+5gYAAABfeyJvcmlnaW4iOiJodHRwczovL2NhcHR1cmUtaGFuZGxlLmdsaXRjaC5tZTo0NDMiLCJmZWF0dXJlIjoiQ2FwdHVyZUhhbmRsZSIsImV4cGlyeSI6MTY1ODg3OTk5OX0="
/>
<title>capture-handle.glitch.me</title>
<link rel="stylesheet" href="./index.css" />
<script src="./index.js" defer></script>
</head>
<body>
<h1>Tab Capture Handle</h1>
<a href="https://w3c.github.io/mediacapture-handle/identity/"
>https://w3c.github.io/mediacapture-handle/identity/</a
>
<button id="openButton">Open Presentation</button>
<button id="captureButton">Capture</button>
<button id="previousButton">Previous</button>
<button id="nextButton">Next</button>
<br />
<pre id="captureHandle"></pre>
<br />
<video id="video" autoplay playsinline></video>
<pre id="logs"></pre>
<script>
window.onunhandledrejection = (event) => {
logs.textContent += `${event.reason}\r\n`;
};
</script>
</body>
</html>
let captureHandle;
captureButton.onclick = async () => {
const stream = await navigator.mediaDevices.getDisplayMedia();
document.getElementById("video").srcObject = stream;
const [videoTrack] = stream.getVideoTracks();
captureHandle = videoTrack.getCaptureHandle();
console.log(videoTrack, captureHandle);
updateCaptureHandleText();
videoTrack.oncapturehandlechange = (event) => {
captureHandle = event.target.getCaptureHandle();
updateCaptureHandleText();
};
};
openButton.onclick = () => window.open("captured.html");
previousButton.onclick = () => sendInstruction("prev");
nextButton.onclick = () => sendInstruction("next");
const broadcastChannel = new BroadcastChannel("capture-handle");
function sendInstruction(direction) {
if (!captureHandle) return;
broadcastChannel.postMessage({
handle: captureHandle.handle,
direction,
});
}
function updateCaptureHandleText() {
document.getElementById("captureHandle").textContent = captureHandle
? `Sharing ${captureHandle.origin} content with handle ${captureHandle.handle}`
: "Try sharing a tab that exposes information to capturing applications instead.";
}
const electron = require("electron");
electron.app.whenReady().then(()=>{
let main = new electron.BrowserWindow({
"height" : 700,
"width" : 800,
show: true
});
main.webContents.loadFile("index.html").then(() => {
console.log("File loaded");
});
main.webContents.setWindowOpenHandler((details) => {
console.log(`[setWindowOpenHandler]`, details.url);
return {
action: "allow",
};
});
let child = null;
main.webContents.on("did-create-window", (browserWindow, details) => {
child = browserWindow;
});
electron.session.defaultSession.setDisplayMediaRequestHandler((request, callback) => {
callback({ video: child.webContents.mainFrame });
});
})
{
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "25.0.0-beta.7"
},
"dependencies": {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment