Remove video canvas demo shells and fix media upload timeouts
- Starter/toolbox presets no longer seed fake generated results; demo fallback media URLs in tool actions now fail with honest guidance - Delete dead demo scene components, fake director console, demo history constants and unreachable submit toast fallbacks - Smart edit dialog accepts desktop drag-and-drop video files - Raise media upload client timeout to 10 minutes and surface friendly timeout errors instead of raw 'signal timed out'
This commit is contained in:
parent
3002704d77
commit
a4354dc535
File diff suppressed because it is too large
Load Diff
@ -90,6 +90,23 @@ export function SmartEditDialog({
|
||||
[zoom, setZoom] = useState(1),
|
||||
[snap, setSnap] = useState(true);
|
||||
const [configure, setConfigure] = useState(false);
|
||||
const [videoDragActive, setVideoDragActive] = useState(false);
|
||||
const videoDragDepthRef = useRef(0);
|
||||
const uploadVideoFiles = async (files: File[]) => {
|
||||
if (!files.length) return;
|
||||
if (files.length + draft.assets.length > 12) {
|
||||
setError("最多 12 个素材");
|
||||
return;
|
||||
}
|
||||
setBusy(true);
|
||||
try {
|
||||
for (const file of files) await upload(file, "video");
|
||||
} catch (e) {
|
||||
setError((e as Error).message);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
};
|
||||
const applied = useRef(planTaskId);
|
||||
useEffect(() => {
|
||||
if (planTaskId && planTaskId !== applied.current) {
|
||||
@ -112,7 +129,7 @@ export function SmartEditDialog({
|
||||
fetch("/api/canvas/smart-edit/capabilities", { signal: controller.signal })
|
||||
.then(async (r) => {
|
||||
const data = await r.json();
|
||||
if (!r.ok) throw Error(data.error);
|
||||
if (!r.ok) throw new Error(data.error);
|
||||
setCap(data);
|
||||
})
|
||||
.catch((e) => {
|
||||
@ -185,17 +202,26 @@ export function SmartEditDialog({
|
||||
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
||||
};
|
||||
const upload = async (file: File, kind: "video" | "audio") => {
|
||||
if (file.size > 125 * 1024 * 1024) throw Error("单个素材不得超过 125 MiB");
|
||||
if (file.size > 125 * 1024 * 1024) throw new Error("单个素材不得超过 125 MiB");
|
||||
const form = new FormData();
|
||||
form.append("file", file);
|
||||
const response = await fetch("/api/canvas/media/upload", {
|
||||
method: "POST",
|
||||
body: form,
|
||||
signal: AbortSignal.timeout(120000),
|
||||
});
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch("/api/canvas/media/upload", {
|
||||
method: "POST",
|
||||
body: form,
|
||||
signal: AbortSignal.timeout(600000),
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
e instanceof DOMException && (e.name === "TimeoutError" || e.name === "AbortError")
|
||||
? "上传超时,请检查网络后重试,或改用更小的素材"
|
||||
: "上传失败,请检查网络后重试",
|
||||
);
|
||||
}
|
||||
const result = await response.json();
|
||||
const url = result.url || result.data?.url;
|
||||
if (!response.ok || !url) throw Error(result.error || "上传失败");
|
||||
if (!response.ok || !url) throw new Error(result.error || "上传失败");
|
||||
if (kind === "audio") patch({ music: { url, gain: 0.2, start: 0 } });
|
||||
else
|
||||
patch({
|
||||
@ -308,7 +334,43 @@ export function SmartEditDialog({
|
||||
aria-modal="true"
|
||||
aria-label="智能剪辑"
|
||||
className="fixed inset-0 z-[160] flex flex-col bg-[#171717] text-white"
|
||||
onDragEnter={(e) => {
|
||||
if (!Array.from(e.dataTransfer.types).includes("Files")) return;
|
||||
e.preventDefault();
|
||||
videoDragDepthRef.current += 1;
|
||||
setVideoDragActive(true);
|
||||
}}
|
||||
onDragOver={(e) => {
|
||||
if (!Array.from(e.dataTransfer.types).includes("Files")) return;
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = "copy";
|
||||
}}
|
||||
onDragLeave={(e) => {
|
||||
videoDragDepthRef.current = Math.max(0, videoDragDepthRef.current - 1);
|
||||
if (!videoDragDepthRef.current) setVideoDragActive(false);
|
||||
}}
|
||||
onDrop={(e) => {
|
||||
if (!Array.from(e.dataTransfer.types).includes("Files")) return;
|
||||
e.preventDefault();
|
||||
videoDragDepthRef.current = 0;
|
||||
setVideoDragActive(false);
|
||||
const files = Array.from(e.dataTransfer.files).filter((file) =>
|
||||
file.type.startsWith("video/"),
|
||||
);
|
||||
if (!files.length) {
|
||||
setError("请拖入 MP4、MOV 或 WebM 视频素材");
|
||||
return;
|
||||
}
|
||||
void uploadVideoFiles(files);
|
||||
}}
|
||||
>
|
||||
{videoDragActive ? (
|
||||
<div className="pointer-events-none fixed inset-0 z-[300] flex items-center justify-center border-4 border-dashed border-cyan-300/70 bg-cyan-300/5">
|
||||
<span className="rounded-lg bg-black/70 px-4 py-2 text-sm">
|
||||
松开以上传视频素材
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
<header className="flex shrink-0 items-center justify-between border-b border-white/15 px-5 py-3">
|
||||
<h2>智能剪辑 · {plan?.title || "从素材到成片"}</h2>
|
||||
{plan && (
|
||||
@ -371,18 +433,7 @@ export function SmartEditDialog({
|
||||
onChange={async (e) => {
|
||||
const files = Array.from(e.target.files || []);
|
||||
e.target.value = "";
|
||||
if (files.length + draft.assets.length > 12) {
|
||||
setError("最多 12 个素材");
|
||||
return;
|
||||
}
|
||||
setBusy(true);
|
||||
try {
|
||||
for (const file of files) await upload(file, "video");
|
||||
} catch (e) {
|
||||
setError((e as Error).message);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
await uploadVideoFiles(files);
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
|
||||
@ -236,14 +236,23 @@ export function SmartEditNodeComposer({
|
||||
try {
|
||||
const body = new FormData();
|
||||
body.append("file", file);
|
||||
const response = await fetch("/api/canvas/media/upload", {
|
||||
method: "POST",
|
||||
body,
|
||||
signal: AbortSignal.timeout(120000),
|
||||
});
|
||||
let response: Response;
|
||||
try {
|
||||
response = await fetch("/api/canvas/media/upload", {
|
||||
method: "POST",
|
||||
body,
|
||||
signal: AbortSignal.timeout(600000),
|
||||
});
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
e instanceof DOMException && (e.name === "TimeoutError" || e.name === "AbortError")
|
||||
? "上传超时,请检查网络后重试,或改用更小的素材"
|
||||
: "上传失败,请检查网络后重试",
|
||||
);
|
||||
}
|
||||
const data = await response.json(),
|
||||
url = data.url || data.data?.url;
|
||||
if (!response.ok || !url) throw Error(data.error || "音乐上传失败");
|
||||
if (!response.ok || !url) throw new Error(data.error || "音乐上传失败");
|
||||
onDraft({ music: { url, gain: 0.2, start: 0 } });
|
||||
} catch (e) {
|
||||
setError(e instanceof Error ? e.message : "音乐上传失败");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user