import { ProviderTaskUncertainError } from "./video-task-lifecycle"; import "server-only"; import { mkdtemp, readFile, rm } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { uploadFile } from "@/lib/storage/service"; import { videoUpscaleSchema } from "./video-upscale-contract"; import { remoteUpscale, type UpscaleCheckpoint } from "./video-upscale-remote"; export async function executeVideoUpscale( params: Record, userId: string, taskId: string, lifecycle: { resume?: UpscaleCheckpoint; active: () => Promise; save: (value: Record) => Promise; } ) { const input = videoUpscaleSchema.parse(params), dir = await mkdtemp(path.join(tmpdir(), "upscale-")); try { const output = await remoteUpscale(input, userId, taskId, dir, { resume: lifecycle.resume, active: lifecycle.active, save: (remote, stage) => lifecycle.save({ upscale: { remote, stage } }), }); await lifecycle.active(); const file = await readFile(output.file); let stored; try { stored = await uploadFile( `video-upscale-${taskId}.mp4`, (file.byteOffset === 0 && file.byteLength === file.buffer.byteLength ? file.buffer : file.buffer.slice( file.byteOffset, file.byteOffset + file.byteLength )) as ArrayBuffer ); } catch { throw new ProviderTaskUncertainError( "高清结果已生成,归档暂时失败,将继续归档同一结果" ); } return { url: stored.url, metadata: { width: output.width, height: output.height, durationSeconds: output.duration, fps: output.fps, frames: output.frames, hasAudio: output.audio, engine: "Real-ESRGAN", model: "realesr-general-x4v3", resolution: input.resolution, }, }; } finally { await rm(dir, { recursive: true, force: true }); } }