fix(video): develop
This commit is contained in:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user