Skip to content

Instantly share code, notes, and snippets.

@r3Fuze
Last active December 31, 2023 19:02
Show Gist options
  • Save r3Fuze/5551079c01b1d6e882734bc69561e904 to your computer and use it in GitHub Desktop.
Save r3Fuze/5551079c01b1d6e882734bc69561e904 to your computer and use it in GitHub Desktop.
Prusa Connect Live Camera
// ==UserScript==
// @name Prusa Connect - Custom Live Camera Feed
// @namespace https://r3fuze.github.io
// @match https://connect.prusa3d.com/*
// @run-at document-idle
// @grant none
// @version 0.5.0
// @author fz
// @description Replace the slow camera snapshots in Prusa Connect with a custom live camera feed by using a Raspberry Pi running μStreamer.
// ==/UserScript==
const PRINTER_GUID = "<printer guid>"
const CAMERA_STREAM = "<stream url>"
const root = document.getElementById("root")
const cameraContainer = document.createElement("div")
cameraContainer.classList.add("image-contents", "custom-camera")
const cameraFeed = document.createElement("img")
cameraFeed.src = CAMERA_STREAM
cameraFeed.addEventListener("error", () => {
console.error("Failed to load camera stream")
})
const reloadButton = document.createElement("button")
reloadButton.type = "button"
reloadButton.title = "Reload Camera"
// Icon from Heroicons (https://heroicons.com/)
reloadButton.innerHTML = `
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
</svg>
`
const reloadButtonStyle = {
position: "absolute",
top: "0.5rem",
right: "0.5rem",
width: "1.5rem",
height: "1.5rem",
display: "flex",
background: "transparent",
border: "1px solid white",
borderRadius: "0.25rem",
padding: "0",
}
Object.assign(reloadButton.style, reloadButtonStyle)
reloadButton.addEventListener("click", (e) => {
e.stopPropagation()
cameraFeed.src = CAMERA_STREAM + "&t=" + Date.now()
})
cameraContainer.appendChild(cameraFeed)
cameraContainer.appendChild(reloadButton)
const observer = new MutationObserver((mutations) => {
if (!location.pathname.includes(PRINTER_GUID)) {
return
}
mutations.forEach((mutation) => {
if (mutation.type === "childList") {
if (mutation.addedNodes.length > 0) {
mutation.addedNodes.forEach((node) => {
if (node.classList?.contains("image-contents") || node.querySelector(".image-contents")) {
const originalCameraContainer = document.querySelector?.(".image-contents:not(.custom-camera)")
if (originalCameraContainer) {
originalCameraContainer.parentElement.appendChild(cameraContainer)
originalCameraContainer.remove()
}
return
}
})
}
}
})
})
observer.observe(root, {
childList: true,
subtree: true,
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment