fix(video): develop

This commit is contained in:
zhangheng
2026-02-12 17:30:29 +08:00
parent 311a92f3fd
commit 6a5dbd776f
25 changed files with 229 additions and 54 deletions

View File

@@ -6,6 +6,7 @@ import {
Card,
Container,
FileInput,
Flex,
Group,
Image,
Loader,
@@ -25,6 +26,7 @@ import {
import { useEffect, useRef, useState } from "react"
import { appendCapped } from "./cap"
import type { WorkerResponse } from "./ffmpeg.worker"
import { getServerImage } from "@/components/label/api/label"
export default function VideoFrameExtractor() {
const [loaded, setLoaded] = useState(false)
@@ -155,6 +157,69 @@ export default function VideoFrameExtractor() {
}
}, [])
/**
* 将视频 Base64 转换为 File 对象
* @param {string} base64String - 视频 Base64 字符串
* @param {string} fileName - 文件名 (例如 'video.mp4')
* @returns {File}
*/
function videoBase64ToFile(base64String: string, fileName: string) {
// 1. 提取 MIME 类型和数据
const parts = base64String.split(",")
const mime = parts[0].match(/:(.*?);/)?.[1] // 可能是 video/mp4, video/webm 等
// 2. 解码
const bstr = atob(parts[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
// 3. 填充字节数组
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
// 4. 返回 File 对象
return new File([u8arr], fileName, { type: mime })
}
const getServerVideo = async () => {
const params = {
data_names: ["6874b86e341d1d0e4c75d0d5.h264"],
data_type: 0,
project_id: 9,
}
let text
const response = await getServerImage(params)
text = `data:video/h264;base64,${response}`
const fileRes = videoBase64ToFile(text, "6874b86e341d1d0e4c75d0d5.h264")
// const videoFile = new File([response], "6874b86e341d1d0e4c75d0d5.264", {
// type: "video/264",
// })
setFile(fileRes)
}
function downloadFile(file: File | null) {
if (!file) return
// 创建一个临时的 DOM URL 指向内存中的文件
const url = URL.createObjectURL(file)
// 创建一个隐藏的 a 标签
const a = document.createElement("a")
a.style.display = "none"
a.href = url
a.download = file.name // 设置下载后的文件名
// 将标签添加到文档中并触发点击
document.body.appendChild(a)
a.click()
// 清理工作:移除标签并释放内存 URL
document.body.removeChild(a)
window.URL.revokeObjectURL(url)
}
const processVideo = () => {
if (!file || !loaded || !workerRef.current) return
@@ -215,11 +280,21 @@ export default function VideoFrameExtractor() {
)}
<Card withBorder shadow="sm" p="lg" radius="md">
<Flex gap={"md"}>
<Button onClick={getServerVideo}>getServerVideo</Button>
<Button
onClick={() => {
downloadFile(file)
}}>
downloadFile
</Button>
</Flex>
<Stack gap="md">
<FileInput
label="Select Video File"
placeholder="Click to select MP4, WebM..."
accept="video/*"
// accept="video/*"
leftSection={<IconMovie size={16} />}
value={file}
onChange={setFile}