Last active
July 21, 2021 02:36
-
-
Save pyplacca/bf4ead5414912dea4337e450f450a4ae to your computer and use it in GitHub Desktop.
React component for generating video thumbnails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { | |
useState, | |
useRef, | |
forwardRef, | |
useImperativeHandle | |
} from 'react' | |
function ThumbnailGenerator({ src, width, height }, ref) { | |
/* | |
The only required prop is the "src". | |
The value of this prop can be any valid (not an embed) video url | |
A valid video url in this case is any video url that can be loaded by the HTML <video/> element | |
If you choose to omit the "width" and "height" props, | |
they both will automatically generated from the video src (recommended approach) | |
*/ | |
const canvasRef = useRef() | |
const videoRef = useRef() | |
const [canvasWidth, setCanvasWidth] = useState(width) | |
const [canvasHeight, setCanvasHeight] = useState(height) | |
useImperativeHandle(ref, () => ({ | |
// call this method in your parent component when you're ready to generate a thumbnail | |
// by default, the generated thumbnail is based on the first frame of the video | |
generateThumbnail() { | |
const canvas = canvasRef.current | |
const context = canvas.getContext('2d') | |
context.drawImage(videoRef.current, 0, 0, canvasWidth, canvasHeight) | |
const blob = canvas.toDataURL() | |
const { ext: mimeType } = blob.split(',')[0].match(/\/(?<ext>\w+);/).groups | |
return { | |
blob, | |
mimeType, | |
filename: `image.${mimeType}`, | |
width: canvasWidth, | |
height: canvasHeight | |
} | |
} | |
})) | |
const onVideoLoad = ({target}) => { | |
if (!(width && height)) { | |
setCanvasWidth(target.videoWidth) | |
setCanvasHeight(target.videoHeight) | |
} | |
} | |
return ( | |
<div | |
style={{ | |
position: 'fixed', | |
zIndex: '-1', | |
visibility: 'hidden' | |
}} | |
> | |
<canvas | |
ref={canvasRef} | |
width={canvasWidth} | |
height={canvasHeight} | |
/> | |
<video | |
crossOrigin="Anonymous" | |
ref={videoRef} | |
src={src} | |
onLoadedData={onVideoLoad} | |
/> | |
</div> | |
) | |
} | |
export default forwardRef(ThumbnailGenerator) | |
/* | |
Use it in your parent component like so; | |
function ParentComponent() { | |
... | |
const thumbGenRef = useRef() | |
const videoSource = "https://i.imgur.com/8yEqycg.mp4" // an example video url used for testing | |
// bind this method to a click event on the component you would like to handle the action | |
const generateThumb = () => { | |
const data = thumbGenRef.current.generateThumbnail() | |
} | |
return ( | |
... | |
<ThumbmnailGenerator ref={thumbGenRef} src={videoSource} /> | |
) | |
} | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment