import { useState, useCallback, useRef, useEffect } from 'react'; export const usePictureInPicture = () => { const [isPipActive, setIsPipActive] = useState(false); const videoRef = useRef(null); useEffect(() => { if (typeof window === 'undefined') return; const video = document.createElement('video'); video.muted = true; video.playsInline = true; videoRef.current = video; const handleLeavePip = () => { setIsPipActive(false); }; video.addEventListener('leavepictureinpicture', handleLeavePip); return () => { video.removeEventListener('leavepictureinpicture', handleLeavePip); if (document.pictureInPictureElement === video) { document.exitPictureInPicture().catch(() => {}); } }; }, []); const togglePip = useCallback(async (canvas: HTMLCanvasElement | null) => { if (!canvas || !videoRef.current) return; const video = videoRef.current; try { if (document.pictureInPictureElement === video) { await document.exitPictureInPicture(); setIsPipActive(false); } else { // Capture a stream of the Canvas at 30 fps const stream = canvas.captureStream ? canvas.captureStream(30) : (canvas as any).mozCaptureStream ? (canvas as any).mozCaptureStream(30) : null; if (!stream) { throw new Error("Canvas.captureStream() is not supported on this browser."); } video.srcObject = stream; await new Promise((resolve) => { video.onloadedmetadata = () => { video.play().then(() => resolve()); }; }); await video.requestPictureInPicture(); setIsPipActive(true); } } catch (error) { console.error("Picture-in-Picture failed:", error); alert("Picture-in-Picture error: " + (error instanceof Error ? error.message : String(error))); } }, []); const isSupported = typeof window !== 'undefined' && 'pictureInPictureEnabled' in document; return { togglePip, isPipActive, isSupported }; }; export default usePictureInPicture;