import { useState } from "react"; import { Button } from "../ui/button"; import { ScreenRecorderState } from "../../types"; import { blobToBase64DataUrl } from "./utils"; import fixWebmDuration from "webm-duration-fix"; import toast from "react-hot-toast"; interface Props { screenRecorderState: ScreenRecorderState; setScreenRecorderState: (state: ScreenRecorderState) => void; generateCode: ( referenceImages: string[], inputMode: "image" | "video" ) => void; } function ScreenRecorder({ screenRecorderState, setScreenRecorderState, generateCode, }: Props) { const [mediaStream, setMediaStream] = useState(null); const [mediaRecorder, setMediaRecorder] = useState( null ); const [screenRecordingDataUrl, setScreenRecordingDataUrl] = useState< string | null >(null); const startScreenRecording = async () => { try { // Get the screen recording stream const stream = await navigator.mediaDevices.getDisplayMedia({ video: true, audio: { echoCancellation: true }, }); setMediaStream(stream); // TODO: Test across different browsers // Create the media recorder const options = { mimeType: "video/webm" }; const mediaRecorder = new MediaRecorder(stream, options); setMediaRecorder(mediaRecorder); const chunks: BlobPart[] = []; // Accumalate chunks as data is available mediaRecorder.ondataavailable = (e: BlobEvent) => chunks.push(e.data); // When media recorder is stopped, create a data URL mediaRecorder.onstop = async () => { // TODO: Do I need to fix duration if it's not a webm? const completeBlob = await fixWebmDuration( new Blob(chunks, { type: options.mimeType, }) ); const dataUrl = await blobToBase64DataUrl(completeBlob); // downloadBlob(completeBlob); setScreenRecordingDataUrl(dataUrl); setScreenRecorderState(ScreenRecorderState.FINISHED); }; // Start recording mediaRecorder.start(); setScreenRecorderState(ScreenRecorderState.RECORDING); } catch (error) { toast.error("Could not start screen recording"); throw error; } }; const stopScreenRecording = () => { // Stop the recorder if (mediaRecorder) { mediaRecorder.stop(); setMediaRecorder(null); } // Stop the screen sharing stream if (mediaStream) { mediaStream.getTracks().forEach((track) => { track.stop(); }); } }; const kickoffGeneration = () => { if (screenRecordingDataUrl) { generateCode([screenRecordingDataUrl], "video"); } else { toast.error("Screen recording does not exist. Please try again."); throw new Error("No screen recording data url"); } }; return (
{screenRecorderState === ScreenRecorderState.INITIAL && ( )} {screenRecorderState === ScreenRecorderState.RECORDING && (
Recording...
)} {screenRecorderState === ScreenRecorderState.FINISHED && (
Screen Recording Captured.
)}
); } export default ScreenRecorder;