Refactor frontend thumbnail handling
This commit is contained in:
parent
7eef0b6e25
commit
8a69a07cc7
|
@ -21,82 +21,58 @@ export const VideoPreview: React.FC<Props> = ({
|
|||
|
||||
// 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;
|
||||
}
|
||||
(async function () {
|
||||
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;
|
||||
}
|
||||
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);
|
||||
// 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;
|
||||
// If the required position is 0, display the thumbnail instead of
|
||||
// trying to render the video. The most important use case is before a
|
||||
// click event has happened, when autoplay restrictions will prevent
|
||||
// the video being rendered to canvas.
|
||||
if (position == 0) {
|
||||
const service = new MediaSetServiceClientImpl(newRPC());
|
||||
const thumbnail = await service.GetVideoThumbnail({
|
||||
id: mediaSet.id,
|
||||
});
|
||||
|
||||
ctx.clearRect(0, 0, x, canvas.height);
|
||||
ctx.clearRect(x + 177, 0, canvas.width - 177 - x, canvas.height);
|
||||
// TODO: avoid fetching the image every re-render:
|
||||
const url = URL.createObjectURL(
|
||||
new Blob([thumbnail.image], { type: 'image/jpeg' })
|
||||
);
|
||||
const img = new Image(thumbnail.width, thumbnail.height);
|
||||
|
||||
ctx.drawImage(video, x, 0, 177, 100);
|
||||
img.src = url;
|
||||
img.onload = () => ctx.drawImage(img, 0, 0, 177, 100);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, render the video, which (should) work now.
|
||||
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]);
|
||||
}, [mediaSet, position]);
|
||||
|
||||
// render component
|
||||
|
||||
|
|
Loading…
Reference in New Issue