CoolFace
Apppublic

coyotte508/fastvlm-webgpu

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
App.tsx110 linesDownload Raw Back to src
1import { useState, useEffect, useRef, useCallback, useMemo } from "react";2import LoadingScreen from "./components/LoadingScreen";3import CaptioningView from "./components/CaptioningView";4import WelcomeScreen from "./components/WelcomeScreen";5import WebcamPermissionDialog from "./components/WebcamPermissionDialog";6import type { AppState } from "./types";7 8export default function App() {9  const [appState, setAppState] = useState<AppState>("requesting-permission");10  const [webcamStream, setWebcamStream] = useState<MediaStream | null>(null);11  const [isVideoReady, setIsVideoReady] = useState(false);12  const videoRef = useRef<HTMLVideoElement | null>(null);13 14  const handlePermissionGranted = useCallback((stream: MediaStream) => {15    setWebcamStream(stream);16    setAppState("welcome");17  }, []);18 19  const handleStart = useCallback(() => {20    setAppState("loading");21  }, []);22 23  const handleLoadingComplete = useCallback(() => {24    setAppState("captioning");25  }, []);26 27  const playVideo = useCallback(async (video: HTMLVideoElement) => {28    try {29      await video.play();30    } catch (error) {31      console.error("Failed to play video:", error);32    }33  }, []);34 35  const setupVideo = useCallback(36    (video: HTMLVideoElement, stream: MediaStream) => {37      video.srcObject = stream;38 39      const handleCanPlay = () => {40        setIsVideoReady(true);41        playVideo(video);42      };43 44      video.addEventListener("canplay", handleCanPlay, { once: true });45 46      return () => {47        video.removeEventListener("canplay", handleCanPlay);48      };49    },50    [playVideo],51  );52 53  useEffect(() => {54    if (webcamStream && videoRef.current) {55      const video = videoRef.current;56 57      video.srcObject = null;58      video.load();59 60      const cleanup = setupVideo(video, webcamStream);61      return cleanup;62    }63  }, [webcamStream, setupVideo]);64 65  const videoBlurState = useMemo(() => {66    switch (appState) {67      case "requesting-permission":68        return "blur(20px) brightness(0.2) saturate(0.5)";69      case "welcome":70        return "blur(12px) brightness(0.3) saturate(0.7)";71      case "loading":72        return "blur(8px) brightness(0.4) saturate(0.8)";73      case "captioning":74        return "none";75      default:76        return "blur(20px) brightness(0.2) saturate(0.5)";77    }78  }, [appState]);79 80  return (81    <div className="App relative h-screen overflow-hidden">82      <div className="absolute inset-0 bg-gray-900" />83 84      {webcamStream && (85        <video86          ref={videoRef}87          autoPlay88          muted89          playsInline90          className="absolute inset-0 w-full h-full object-cover transition-all duration-1000 ease-out"91          style={{92            filter: videoBlurState,93            opacity: isVideoReady ? 1 : 0,94          }}95        />96      )}97 98      {appState !== "captioning" && <div className="absolute inset-0 bg-gray-900/80 backdrop-blur-sm" />}99 100      {appState === "requesting-permission" && <WebcamPermissionDialog onPermissionGranted={handlePermissionGranted} />}101 102      {appState === "welcome" && <WelcomeScreen onStart={handleStart} />}103 104      {appState === "loading" && <LoadingScreen onComplete={handleLoadingComplete} />}105 106      {appState === "captioning" && <CaptioningView videoRef={videoRef} />}107    </div>108  );109}110