feat(review): flag handles in the review player (metadata only)
Deploy / deploy (push) Successful in 3m31s
Deploy / deploy (push) Successful in 3m31s
Renders run 8 frames past the cut at each end. Directors were flagging glitches in unfixed handles as shot problems, so the player now marks them — without trimming or burning anything into the EXRs/MOV/MP4. - Version.handleHead/handleTail/pictureStartFrame, Export.handleHead/ handleTail; migration backfills pipeline exports and their preview versions from the manifest's handleFrames (else 8) - AE panel: "Includes handles [8] frames each end" -> manifest.review; older manifests fall back to source.handleFrames - finalize copies handles onto the Version; worker 1.6.4 reports the head slate length (pictureStartSeconds), else the player infers it as MP4 frames - EXR frameCount - Player: hatched HANDLE / SLATE regions and cut marks on the timeline, "HEAD/TAIL HANDLE · NOT IN EDIT" overlay on handle frames, HANDLE badge on notes, "Edit range only" toggle (default on in the client portal) - Staff Handles editor on the review page for manual uploads/corrections Also fixes two player bugs found while testing: timeToFrame floored float error (every seek landed a frame early), and J/reverse never ran (the keyboard effect's cleanup stopped it on the next render). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -259,3 +259,35 @@ export async function getVersionComments(versionId: string) {
|
||||
orderBy: { frameNumber: "asc" },
|
||||
});
|
||||
}
|
||||
|
||||
const updateVersionHandlesSchema = z.object({
|
||||
versionId: z.string().cuid(),
|
||||
/** 0/0 = no handles (every frame is in the edit). */
|
||||
handleHead: z.number().int().min(0).max(1000),
|
||||
handleTail: z.number().int().min(0).max(1000),
|
||||
/** Slate frames before the picture; null = infer from the media. */
|
||||
pictureStartFrame: z.number().int().min(0).max(1000).nullable(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Marks which frames of a version are handles (past the cut at each end), so
|
||||
* the review player can flag them. Review metadata only — the media and any
|
||||
* delivered files are untouched. Staff only: a client can't redefine the cut.
|
||||
*/
|
||||
export async function updateVersionHandles(data: z.infer<typeof updateVersionHandlesSchema>) {
|
||||
const session = await auth();
|
||||
if (!session?.user) throw new Error("Unauthorized");
|
||||
if (session.user.role === "CLIENT") throw new Error("Forbidden");
|
||||
|
||||
const parsed = updateVersionHandlesSchema.parse(data);
|
||||
const none = parsed.handleHead === 0 && parsed.handleTail === 0;
|
||||
await db.version.update({
|
||||
where: { id: parsed.versionId },
|
||||
data: {
|
||||
handleHead: none ? null : parsed.handleHead,
|
||||
handleTail: none ? null : parsed.handleTail,
|
||||
pictureStartFrame: parsed.pictureStartFrame,
|
||||
},
|
||||
});
|
||||
revalidatePath(`/review/${parsed.versionId}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user