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
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' })
}
}