hash web worker video

26 阅读1分钟
import { useEffect, useRef, useState } from 'react';
import VideoHashWorker from '../utils/videoHash.worker.ts?worker';

const VideoHashCalculator = () => {
  const [file, setFile] = useState<File | null>(null);
  const [hash, setHash] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const workerRef = useRef<Worker | null>(null);

  useEffect(() => {
    workerRef.current = new VideoHashWorker();

    workerRef.current.onmessage = (e: MessageEvent<{ hash?: string; error?: string }>) => {
      if (e.data.hash) {
        setHash(e.data.hash);
        setError(null);
      } else if (e.data.error) {
        setError(e.data.error);
        setHash(null);
      }
    };

    return () => {
      workerRef.current?.terminate();
    };
  }, []);

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFile = e.target.files?.[0];
    if (selectedFile) {
      setFile(selectedFile);
      workerRef.current?.postMessage(selectedFile);
    }
  };

  return (
    <div>
      <h2>视频哈希计算器</h2>
      <input type="file" accept="video/*" onChange={handleFileChange} />
      {hash && <p>哈希值: {hash}</p>}
      {error && <p style={{ color: 'red' }}>错误: {error}</p>}
    </div>
  );
};

export default VideoHashCalculator;

// 计算视频文件的哈希值
const calculateVideoHash = async (videoFile: File): Promise<string> => {
  const arrayBuffer = await videoFile.arrayBuffer();
  const hashBuffer = await crypto.subtle.digest('SHA-256', arrayBuffer);
  const hashArray = Array.from(new Uint8Array(hashBuffer));
  const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
  return hashHex;
};

// 监听主线程消息
self.onmessage = async (e: MessageEvent<File>) => {
  try {
    const videoFile = e.data;
    const hash = await calculateVideoHash(videoFile);
    self.postMessage({ hash });
  } catch (error) {
    self.postMessage({ error: error instanceof Error ? error.message : 'Unknown error' });
  }
};