Spaces:
				
			
			
	
			
			
		Runtime error
		
	
	
	
			
			
	
	
	
	
		
		
		Runtime error
		
	| (function () { | |
| const BENCHMARK_THROTTLE = 250; | |
| const INTERVAL = 33; | |
| const video = document.createElement('video'); | |
| navigator.getUserMedia({ | |
| audio: false, | |
| video: { | |
| width: {min: 480, ideal: 640}, | |
| height: {min: 360, ideal: 480} | |
| } | |
| }, stream => { | |
| video.autoplay = true; | |
| video.src = window.URL.createObjectURL(stream); | |
| // Get the track to hint to the browser the stream needs to be running | |
| // even though we don't add the video tag to the DOM. | |
| stream.getTracks(); | |
| video.addEventListener('play', () => { | |
| video.width = video.videoWidth; | |
| video.height = video.videoHeight; | |
| }); | |
| }, err => { | |
| // eslint-disable-next-line no-console | |
| console.log(err); | |
| }); | |
| const VideoMotion = window.Scratch3VideoSensingDebug.VideoMotion; | |
| const VideoMotionView = window.Scratch3VideoSensingDebug.VideoMotionView; | |
| // Create motion detector | |
| const motion = new VideoMotion(); | |
| // Create debug views that will render different slices of how the detector | |
| // uses a frame of input. | |
| const OUTPUT = VideoMotionView.OUTPUT; | |
| const outputKeys = Object.keys(OUTPUT); | |
| const outputValues = Object.values(OUTPUT); | |
| const views = outputValues | |
| .map(output => new VideoMotionView(motion, output)); | |
| const view = views[0]; | |
| const defaultViews = [OUTPUT.INPUT, OUTPUT.XY_CELL, OUTPUT.T_CELL, OUTPUT.UV_CELL]; | |
| // Add activation toggles for each debug view. | |
| const activators = document.createElement('div'); | |
| activators.style.userSelect = 'none'; | |
| outputValues.forEach((output, index) => { | |
| const checkboxLabel = document.createElement('label'); | |
| const checkbox = document.createElement('input'); | |
| checkbox.type = 'checkbox'; | |
| checkbox.checked = defaultViews.indexOf(output) !== -1; | |
| const checkboxSpan = document.createElement('span'); | |
| checkboxSpan.innerText = outputKeys[index]; | |
| checkboxLabel.appendChild(checkbox); | |
| checkboxLabel.appendChild(checkboxSpan); | |
| const _view = views[index]; | |
| _view.canvas.style.display = checkbox.checked ? '' : 'none'; | |
| _view.active = checkbox.checked; | |
| checkbox.onchange = event => { | |
| _view.canvas.style.display = checkbox.checked ? '' : 'none'; | |
| _view.active = checkbox.checked; | |
| event.preventDefault(); | |
| return false; | |
| }; | |
| activators.appendChild(checkboxLabel); | |
| }); | |
| document.body.appendChild(activators); | |
| // Add a text line to display milliseconds per frame, motion value, and | |
| // motion direction | |
| const textContainer = document.createElement('div'); | |
| const textHeader = document.createElement('div'); | |
| textHeader.innerText = 'duration (us) :: motion amount :: motion direction'; | |
| textContainer.appendChild(textHeader); | |
| const textEl = document.createElement('div'); | |
| textEl.innerText = `0 :: 0 :: 0`; | |
| textContainer.appendChild(textEl); | |
| document.body.appendChild(textContainer); | |
| let textTimer = Date.now(); | |
| // Add the motion debug views to the dom after the text line, so the text | |
| // appears first. | |
| views.forEach(_view => document.body.appendChild(_view.canvas)); | |
| // Create a temporary canvas the video will be drawn to so the video's | |
| // bitmap data can be transformed into a TypeArray. | |
| const tempCanvas = document.createElement('canvas'); | |
| tempCanvas.width = view.canvas.width; | |
| tempCanvas.height = view.canvas.height; | |
| const ctx = tempCanvas.getContext('2d'); | |
| const loop = function () { | |
| const timeoutId = setTimeout(loop, INTERVAL); | |
| try { | |
| // Get the bitmap data for the video frame | |
| ctx.scale(-1, 1); | |
| ctx.drawImage( | |
| video, | |
| 0, 0, video.width || video.clientWidth, video.height || video.clientHeight, | |
| -tempCanvas.width, 0, tempCanvas.width, tempCanvas.height | |
| ); | |
| ctx.resetTransform(); | |
| const data = ctx.getImageData(0, 0, tempCanvas.width, tempCanvas.height); | |
| // Analyze the latest frame. | |
| const b = performance.now(); | |
| motion.addFrame(data.data); | |
| motion.analyzeFrame(); | |
| // Every so often update the visible debug numbers with duration in | |
| // microseconds, the amount of motion and the direction of the | |
| // motion. | |
| if (Date.now() - textTimer > BENCHMARK_THROTTLE) { | |
| const e = performance.now(); | |
| const analyzeDuration = ((e - b) * 1000).toFixed(0); | |
| const motionAmount = motion.motionAmount.toFixed(1); | |
| const motionDirection = motion.motionDirection.toFixed(1); | |
| textEl.innerText = `${analyzeDuration} :: ${motionAmount} :: ${motionDirection}`; | |
| textTimer = Date.now(); | |
| } | |
| views.forEach(_view => _view.active && _view.draw()); | |
| } catch (error) { | |
| // eslint-disable-next-line no-console | |
| console.error(error.stack || error); | |
| clearTimeout(timeoutId); | |
| } | |
| }; | |
| loop(); | |
| }()); | |
