radames's picture
controlnet
ff9325e
raw
history blame
5.64 kB
export function LCMLive(webcamVideo, liveImage) {
let websocket: WebSocket;
async function start() {
return new Promise((resolve, reject) => {
const websocketURL = `${window.location.protocol === "https:" ? "wss" : "ws"
}:${window.location.host}/ws`;
const socket = new WebSocket(websocketURL);
socket.onopen = () => {
console.log("Connected to websocket");
};
socket.onclose = () => {
console.log("Disconnected from websocket");
stop();
resolve({ "status": "disconnected" });
};
socket.onerror = (err) => {
console.error(err);
reject(err);
};
socket.onmessage = (event) => {
const data = JSON.parse(event.data);
switch (data.status) {
case "success":
break;
case "start":
const userId = data.userId;
initVideoStream(userId);
break;
case "timeout":
stop();
resolve({ "status": "timeout" });
case "error":
stop();
reject(data.message);
}
};
websocket = socket;
})
}
function switchCamera() {
const constraints = {
audio: false,
video: { width: 1024, height: 1024, deviceId: mediaDevices[webcamsEl.value].deviceId }
};
navigator.mediaDevices
.getUserMedia(constraints)
.then((mediaStream) => {
webcamVideo.removeEventListener("timeupdate", videoTimeUpdateHandler);
webcamVideo.srcObject = mediaStream;
webcamVideo.onloadedmetadata = () => {
webcamVideo.play();
webcamVideo.addEventListener("timeupdate", videoTimeUpdateHandler);
};
})
.catch((err) => {
console.error(`${err.name}: ${err.message}`);
});
}
async function videoTimeUpdateHandler() {
const dimension = getValue("input[name=dimension]:checked");
const [WIDTH, HEIGHT] = JSON.parse(dimension);
const canvas = new OffscreenCanvas(WIDTH, HEIGHT);
const videoW = webcamVideo.videoWidth;
const videoH = webcamVideo.videoHeight;
const aspectRatio = WIDTH / HEIGHT;
const ctx = canvas.getContext("2d");
ctx.drawImage(webcamVideo, videoW / 2 - videoH * aspectRatio / 2, 0, videoH * aspectRatio, videoH, 0, 0, WIDTH, HEIGHT)
const blob = await canvas.convertToBlob({ type: "image/jpeg", quality: 1 });
websocket.send(blob);
websocket.send(JSON.stringify({
"seed": getValue("#seed"),
"prompt": getValue("#prompt"),
"guidance_scale": getValue("#guidance-scale"),
"strength": getValue("#strength"),
"steps": getValue("#steps"),
"lcm_steps": getValue("#lcm_steps"),
"width": WIDTH,
"height": HEIGHT,
"controlnet_scale": getValue("#controlnet_scale"),
"controlnet_start": getValue("#controlnet_start"),
"controlnet_end": getValue("#controlnet_end"),
"canny_low_threshold": getValue("#canny_low_threshold"),
"canny_high_threshold": getValue("#canny_high_threshold"),
"debug_canny": getValue("#debug_canny")
}));
}
let mediaDevices = [];
async function initVideoStream(userId) {
liveImage.src = `/stream/${userId}`;
await navigator.mediaDevices.enumerateDevices()
.then(devices => {
const cameras = devices.filter(device => device.kind === 'videoinput');
mediaDevices = cameras;
webcamsEl.innerHTML = "";
cameras.forEach((camera, index) => {
const option = document.createElement("option");
option.value = index;
option.innerText = camera.label;
webcamsEl.appendChild(option);
option.selected = index === 0;
});
webcamsEl.addEventListener("change", switchCamera);
})
.catch(err => {
console.error(err);
});
const constraints = {
audio: false,
video: { width: 1024, height: 1024, deviceId: mediaDevices[0].deviceId }
};
navigator.mediaDevices
.getUserMedia(constraints)
.then((mediaStream) => {
webcamVideo.srcObject = mediaStream;
webcamVideo.onloadedmetadata = () => {
webcamVideo.play();
webcamVideo.addEventListener("timeupdate", videoTimeUpdateHandler);
};
})
.catch((err) => {
console.error(`${err.name}: ${err.message}`);
});
}
async function stop() {
websocket.close();
navigator.mediaDevices.getUserMedia({ video: true }).then((mediaStream) => {
mediaStream.getTracks().forEach((track) => track.stop());
});
webcamVideo.removeEventListener("timeupdate", videoTimeUpdateHandler);
webcamsEl.removeEventListener("change", switchCamera);
webcamVideo.srcObject = null;
}
return {
start,
stop
}
}