diff --git a/README.md b/README.md index 91d3d39..7b9c51c 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,10 @@ Demo: https://eyaler.github.io/LordTubeMaster/#dQw4w9WgXcQ -Note as of May 2024 this is only supported on *Chromium desktop* +Note as of June 2024 this is only supported on *Chromium desktop*. -Enable graphics/hardware acceleration browser setting to reduce lag +Enable graphics/hardware acceleration browser setting to reduce lag. +Specifically for the WebGPU example - make sure you are using a discrete GPU. For fullscreen zoom of output (by right-click) in *Google Chrome*, enable: `chrome://flags/#element-capture` diff --git a/index.html b/index.html index ce47fce..7bf7ebe 100644 --- a/index.html +++ b/index.html @@ -15,7 +15,7 @@ - + diff --git a/script.js b/script.js index bc4cafc..2905ca5 100644 --- a/script.js +++ b/script.js @@ -8,11 +8,24 @@ import { import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@4.20.0/dist/tf.min.js' import 'https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgpu@4.20.0/dist/tf-backend-webgpu.min.js' -if (typeof CropTarget === 'undefined' || - typeof navigator.mediaDevices.getDisplayMedia === 'undefined' || - typeof MediaStreamTrackProcessor === 'undefined' || - typeof MediaStreamTrackGenerator === 'undefined' || - typeof VideoFrame === 'undefined') +function getGPUInfo() { + const gl = document.createElement('canvas').getContext('webgl') + const ext = gl.getExtension('WEBGL_debug_renderer_info') + return ext ? { + vendor: gl.getParameter(ext.UNMASKED_VENDOR_WEBGL), + renderer: gl.getParameter(ext.UNMASKED_RENDERER_WEBGL), + } : { + vendor: 'unknown', + renderer: 'unknown', + } +} +console.log(getGPUInfo()) + +if (typeof CropTarget == 'undefined' || + typeof navigator.mediaDevices.getDisplayMedia == 'undefined' || + typeof MediaStreamTrackProcessor == 'undefined' || + typeof MediaStreamTrackGenerator == 'undefined' || + typeof VideoFrame == 'undefined') out_video.outerHTML = '

Not supported by your browser :(

Try in Chromium desktop!

' video_url.addEventListener('change', e => get_video(e.currentTarget)) @@ -89,7 +102,8 @@ const effect_funcs = { lastVideoTime = videoFrame.timestamp poseLandmarker.detectForVideo(videoFrame, startTimeMs, result => { canvasCtx.save() - canvasCtx.clearRect(0, 0, canvasCtx.canvas.width, canvasCtx.canvas.height) + canvas.width = 1920 + canvas.height = 1080 result.landmarks.forEach((landmarks, i) => { drawingUtils.drawConnectors(landmarks, PoseLandmarker.POSE_CONNECTIONS, { color: colors[i % colors.length], lineWidth: 5 }) const color = colors[(i+1) % colors.length] @@ -170,7 +184,7 @@ const effect_funcs = { } }, - 'cartoonization': (W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame, canvas) => { + 'cartoonization_webgpu': (W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) => { let rgb = new Float32Array(W * H * 3) for (let y = 0; y < H; y++) { const yUV = (y >> 1) * stride @@ -290,7 +304,7 @@ async function capture() { } const [track] = stream.getVideoTracks() track.addEventListener('ended', () => capture_started = false) - if (typeof RestrictionTarget !== 'undefined') { + if (typeof RestrictionTarget != 'undefined') { // In Google Chrome, enable chrome://flags/#element-capture - this will enable fullscreen zoom of output // See: https://developer.chrome.com/docs/web-platform/element-capture // Note that pinch zoom pauses the stream: https://issues.chromium.org/issues/337337168 @@ -338,14 +352,13 @@ async function capture() { console.warn(e) await tf.setBackend('webgl') } + const queue = tf.backend().queue // https://github.com/SystemErrorWang/White-box-Cartoonization // https://github.com/vladmandic/anime const cartoon = await tf.loadGraphModel('cartoon/whitebox.json') const models = {'pose': poseLandmarker, 'segment': imageSegmenter, 'cartoon': cartoon} - canvas.width = 1920 - canvas.height = 1080 const canvasCtx = canvas.getContext('2d') const drawingUtils = new DrawingUtils(canvasCtx) @@ -368,7 +381,9 @@ async function capture() { const copyResult = await videoFrame.copyTo(yuv) const { stride, offset: Voffset } = copyResult[1] const { offset: Uoffset } = copyResult[2] - effect_funcs[effect.value](W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame, canvas) + effect_funcs[effect.value](W, H, stride, Voffset, Uoffset, yuv, rgba, models, videoFrame) + if (effect.value.includes('webgpu')) + await queue.onSubmittedWorkDone() } const init = { codedHeight: H,