// this looks really great! // https://replicate.com/zsxkib/st-mfnet?prediction=bufijj3b45cjoe43pzloqkcghy "use server" import Replicate from "replicate" import { sleep } from "../../utils/misc/sleep.mts" const replicateToken = `${process.env.VC_REPLICATE_API_TOKEN || ""}` const replicateModel = `${process.env.VC_VIDEO_INTERPOLATION_STMFNET_REPLICATE_MODEL || ""}` const replicateModelVersion = `${process.env.VC_VIDEO_INTERPOLATION_STMFNET_REPLICATE_MODEL_VERSION || ""}` if (!replicateToken) { throw new Error(`you need to configure your VC_REPLICATE_API_TOKEN`) } const replicate = new Replicate({ auth: replicateToken }) /** * Interpolate a video using Replicate * * Important note: the video will lose its sound, if any! * * With the current settingd, duration of the original video will be preserved * (but we could make slow-mo too) */ export async function interpolateVideoWithReplicate({ video, // so arguably 60 would look smoother, but we are tying to reach for a "movie" kind of feel here nbFrames = 24, }: { video: string /** * Number of frame (duration of the original video will be preserved) */ nbFrames?: number // min 1, max: 240 }): Promise { if (!video) { throw new Error(`no video provided`) } if (!replicateModel) { throw new Error(`you need to configure your VC_VIDEO_INTERPOLATION_STMFNET_REPLICATE_MODEL`) } if (!replicateModelVersion) { throw new Error(`you need to configure your VC_VIDEO_INTERPOLATION_STMFNET_REPLICATE_MODEL_VERSION`) } // for params and doc see https://replicate.com/zsxkib/st-mfnet const prediction = await replicate.predictions.create({ version: replicateModelVersion, input: { mp4: video, // I think it should be a base64 object? framerate_multiplier: 2, // can be one of 2, 4, 8, 16, 32 // note: for now we use the simplest setting, which is to keep the original video duration // if we don't keep the original duration, the video will look like a slow motion animation // which may be a desired effect, but let's keep it simple for now keep_original_duration: true, // false, custom_fps: nbFrames // min 1, max: 240 } }) // console.log("prediction:", prediction) // Replicate requires at least 8 seconds of mandatory delay await sleep(10000) let res: Response let pollingCount = 0 do { // This is normally a fast model, so let's check every 2 seconds await sleep(2000) res = await fetch(`https://api.replicate.com/v1/predictions/${prediction.id}`, { method: "GET", headers: { Authorization: `Token ${replicateToken}`, }, cache: 'no-store', }) if (res.status === 200) { const response = (await res.json()) as any const error = `${response?.error || ""}` if (error) { throw new Error(error) } } pollingCount++ // To prevent indefinite polling, we can stop after a certain number if (pollingCount >= 30) { throw new Error('Request time out.') } } while (true) }