Skip to content

Instantly share code, notes, and snippets.

@pyplacca
Last active July 21, 2021 02:36
Show Gist options
  • Save pyplacca/bf4ead5414912dea4337e450f450a4ae to your computer and use it in GitHub Desktop.
Save pyplacca/bf4ead5414912dea4337e450f450a4ae to your computer and use it in GitHub Desktop.
React component for generating video thumbnails
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