diff --git a/README.md b/README.md index 9f7a01e..803f556 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,29 @@ You may also pass in an optional `dimensions` object: getScreenshot({width: 1920, height: 1080}); ``` +`getScreenshotBlob` - Returns a Promise that resolves to a Blob of the current webcam image. This is more efficient than base64 encoding when uploading to a server or processing large images. Example: + +```jsx +const capture = async () => { + try { + const blob = await webcamRef.current.getScreenshotBlob({width: 1920, height: 1080}); + if (blob) { + // Upload to a server + const formData = new FormData(); + formData.append('image', blob); + await fetch('/upload', { method: 'POST', body: formData }); + + // Or create an object URL for display + const url = URL.createObjectURL(blob); + image.src = url; + URL.revokeObjectURL(url); // Clean up when done + } + } catch (error) { + console.error('Failed to capture screenshot:', error); + } +}; +``` + ### The Constraints We can build a constraints object by passing it to the videoConstraints prop. This gets passed into getUserMedia method. Please take a look at the MDN docs to get an understanding how this works. @@ -95,14 +118,23 @@ const WebcamCapture = () => ( width={1280} videoConstraints={videoConstraints} > - {({ getScreenshot }) => ( - + {({ getScreenshot, getScreenshotBlob }) => ( +
+ + +
)} ); @@ -121,7 +153,7 @@ const WebcamCapture = () => { const webcamRef = React.useRef(null); const capture = React.useCallback( () => { - const imageSrc = webcamRef.current.getScreenshot(); + const imageSrc = webcamRef.current.getScreenshot(); // or getScreenshotBlob() }, [webcamRef] ); diff --git a/src/react-webcam.tsx b/src/react-webcam.tsx index 5b054ca..e940174 100644 --- a/src/react-webcam.tsx +++ b/src/react-webcam.tsx @@ -50,6 +50,7 @@ interface ScreenshotDimensions { interface ChildrenProps { getScreenshot: (screenshotDimensions?: ScreenshotDimensions) => string | null; + getScreenshotBlob: (screenshotDimensions?: ScreenshotDimensions) => Promise; } export type WebcamProps = Omit, "ref"> & { @@ -204,6 +205,37 @@ export default class Webcam extends React.Component { ); } + async getScreenshotBlob(screenshotDimensions?: ScreenshotDimensions): Promise { + const { state, props } = this; + + if (!state.hasUserMedia) return null; + + const canvas = this.getCanvas(screenshotDimensions); + if (!canvas) return null; + + if (typeof canvas.toBlob !== 'function') { + throw new Error('Canvas toBlob is not supported'); + } + + try { + const blob = await new Promise((resolve) => { + canvas.toBlob( + (blob) => resolve(blob), + props.screenshotFormat, + props.screenshotQuality + ); + }); + + if (!blob) { + throw new Error('Failed to convert canvas to blob'); + } + + return blob; + } catch (error) { + throw error instanceof Error ? error : new Error('Failed to capture screenshot'); + } + } + getCanvas(screenshotDimensions?: ScreenshotDimensions) { const { state, props } = this; @@ -404,6 +436,7 @@ export default class Webcam extends React.Component { const childrenProps: ChildrenProps = { getScreenshot: this.getScreenshot.bind(this), + getScreenshotBlob: this.getScreenshotBlob.bind(this), }; return (