import { MediaSet, MediaSetServiceClientImpl } from './generated/media_set'; import { newRPC } from './App'; import { useEffect, useRef } from 'react'; interface Props { mediaSet: MediaSet; position: number; duration: number; height: number; video: HTMLVideoElement; } export const VideoPreview: React.FC = ({ mediaSet, position, duration, height, video, }: Props) => { const videoCanvasRef = useRef(null); // effects // load thumbnail, to display when the component is loaded for the first // time. This is needed because of browser autoplay limitations. useEffect(() => { (async function () { if (mediaSet == null) { return; } const canvas = videoCanvasRef.current; if (canvas == null) { console.error('no canvas ref available'); return; } const ctx = canvas.getContext('2d'); if (ctx == null) { console.error('no 2d context available'); return; } // Set aspect ratio. canvas.width = canvas.height * (canvas.clientWidth / canvas.clientHeight); console.log('getting video thumbnail...'); const rpc = newRPC(); const service = new MediaSetServiceClientImpl(rpc); const thumbnail = await service.GetVideoThumbnail({ id: mediaSet.id }); console.log('got thumbnail', thumbnail); const url = URL.createObjectURL( new Blob([thumbnail.image], { type: 'image/jpeg' }) ); const img = new Image(thumbnail.width, thumbnail.height); img.src = url; console.log('img', img); img.onerror = console.error; img.onload = () => { ctx.drawImage(img, 0, 0, 177, 100); }; console.log('set src to', url); })(); }, [mediaSet]); // render canvas useEffect(() => { // TODO: not sure if requestAnimationFrame is recommended here. requestAnimationFrame(() => { const canvas = videoCanvasRef.current; if (canvas == null) { console.error('no canvas ref available'); return; } const ctx = canvas.getContext('2d'); if (ctx == null) { console.error('no 2d context available'); return; } // Set aspect ratio. canvas.width = canvas.height * (canvas.clientWidth / canvas.clientHeight); const durSecs = duration / 1000; const ratio = position / durSecs; const x = (canvas.width - 177) * ratio; ctx.clearRect(0, 0, x, canvas.height); ctx.clearRect(x + 177, 0, canvas.width - 177 - x, canvas.height); ctx.drawImage(video, x, 0, 177, 100); }); }, [position]); // render component const containerStyles = { height: height + 'px', position: 'relative', flexGrow: 0, } as React.CSSProperties; const canvasStyles = { position: 'absolute', width: '100%', height: '100%', display: 'block', zIndex: 1, } as React.CSSProperties; return ( <>
); };