import { transcribeOneAction, whisperVideoAction, } from "../../../channels/[slug]/videos/[id]/videoActions"; import { jobResponse, ops, opsFail, optString, reqSlug, reqVideoId } from "../_lib"; export const dynamic = "force-dynamic"; // POST { slug, id, file? } // // One video, transcribed — the video page's two buttons: // - with "file" (an audio file in the video's dir, e.g. "audio.mp3"): that // file, through the worker pool (transcribeOneAction — the per-file // Transcribe on the Files list); // - without: the page's Transcribe (whisperVideoAction), which uses the audio // on disk, or first downloads it through the channel's managed path when // there is none (the disk floor applies to that download only). // A job on the video's platform queue: { ok, jobId }, so --wait follows it. // The file name is one path segment; a refused one is the action's sentence. export async function POST(request: Request) { return ops(request, ["slug", "id", "file"], async (body) => { const slug = reqSlug(body, "slug"); const id = reqVideoId(body, "id"); const file = optString(body, "file"); // One path segment, checked at the door as reqVideoId checks an id: the // name is joined under the video's directory. if (file !== undefined && (file === "" || /[/\\\0]/.test(file) || file.startsWith("."))) { return opsFail(`"${file}" is not a file name in the video's directory`); } return jobResponse( file !== undefined ? await transcribeOneAction(slug, id, file) : await whisperVideoAction(slug, id), ); }); }