timecut icon indicating copy to clipboard operation
timecut copied to clipboard

[BUG] unhandledRejection: Error: ENOENT: no such file or directory, scandir '...\photobooth\timecut-temp-1715854229528'

Open joshuasir opened this issue 1 year ago • 5 comments

i'm getting eror unhandledRejection: Error: ENOENT: no such file or directory, scandir '...\photobooth\timecut-temp-1715854229528' any idea on why is this happening

action.tsx const timecut = require('timecut');

export const snapRecord = async () =>{ timecut({ url: 'file://' + path.join(__dirname, '../../components/CanvasVideo.tsx'), viewport: { width: 800, // sets the viewport (window size) to 800x600 height: 600 }, selector: '#container', // crops each frame to the bounding box of '#container' left: 0, top: 0, // further crops the left by 20px, and the top by 40px right: 60, bottom: 300, // and the right by 6px, and the bottom by 30px fps: 30, // saves 30 frames for each virtual second duration: 20, // for 20 virtual seconds output: 'video.mp4' // to video.mp4 of the current working directory }).then(function () { console.log('Done!'); }); }

called on main file useEffect(() => { snapRecord()

}, []);

joshuasir avatar May 16 '24 10:05 joshuasir

@joshuasir Hey! Were you able to somehow work around the issue?

OlekVano avatar Mar 28 '25 13:03 OlekVano

@joshuasir Hey! Were you able to somehow work around the issue?

Hi, unfortunately no, but I manage to use ref to capture my canvas draw changes as stream bytes and export it as video instead

joshuasir avatar Mar 29 '25 04:03 joshuasir

@joshuasir I see, I'd love to use your workaround. Could you be more specific with how I might replicate it?

OlekVano avatar Mar 29 '25 22:03 OlekVano

Sure! I'll share it here once I'm with my laptop

joshuasir avatar Mar 30 '25 01:03 joshuasir

@OlekVano Hi, sorry for the late response here is my code implementation example

  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  function record(canvas: HTMLCanvasElement, time: number = 5000) {

 // init media recorder
  const recordedChunks: Blob[] = [];
  const stream = canvas.captureStream(30);
  const mimeType = MediaRecorder.isTypeSupported("video/mp4") ? "video/mp4" : "video/webm";
  mediaRecorderRef.current = new MediaRecorder(stream, { mimeType });

  return new Promise((resolve, reject) => {
    if (!mediaRecorderRef.current) {
      reject(new Error("MediaRecorder not initialized"));
      return;
    }

    //ondataavailable will fire in interval of `time`
    mediaRecorderRef.current.ondataavailable = (event: BlobEvent) => {
      // save the available chunk data
      recordedChunks.push(event.data);

      // since my use case is only for a few second i stop the recording after the first interval
      if (mediaRecorderRef.current!.state === "recording") {

        // after stop `dataavailable` event run one more time to send any remaining recorded data
        mediaRecorderRef.current!.stop();
      }
    };

    // onstop save the recorded chunks data as blob mp4
    mediaRecorderRef.current.onstop = () => {
      const videoBlob = new Blob(recordedChunks, { type: mimeType });
      setVideoBlob(videoBlob);
      resolve(videoBlob);
    };

    mediaRecorderRef.current.onerror = (event) => {
      reject(new Error("Recording failed: " + (event as any).error?.message));
    };
    
    // start the recording interval
    mediaRecorderRef.current.start(time);
  });
}

// ...

useEffect(() => {
  if (!canvasRef.current) return;
  record(canvasRef.current, 4000).catch((err) => console.error(err));

 // stop recording on unmount 
 return () => {
    if (mediaRecorderRef.current?.state === "recording") {
      mediaRecorderRef.current.stop();
    }
  };

  }, [canvasRef]);

// ...

<canvas
        ref={canvasRef}
        ....
></canvas>

Let me know if you have further question 😊

joshuasir avatar Mar 31 '25 06:03 joshuasir