|
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 |
|
} |
|
} |