diff --git a/services/mam-api/src/routes/sequences.js b/services/mam-api/src/routes/sequences.js index 97fc0bf..778836a 100644 --- a/services/mam-api/src/routes/sequences.js +++ b/services/mam-api/src/routes/sequences.js @@ -10,27 +10,33 @@ router.use(requireAuth); // ── 59.94 DF timecode helpers (for EDL export) ──────────────────────────────── const NOM = 60; // nominal integer fps const DROP = 4; // frames dropped per minute (except every 10th) -const FRAMES_PER_MIN = NOM * 60 - DROP; // 3596 +const FRAMES_FIRST_MIN = NOM * 60; // 3600 — first (non-drop) minute per 10-min group +const FRAMES_PER_MIN = NOM * 60 - DROP; // 3596 const FRAMES_PER_10MIN = FRAMES_PER_MIN * 10 + DROP; // 35964 -const FRAMES_PER_HOUR = FRAMES_PER_10MIN * 6; // 215784 +const FRAMES_PER_HOUR = FRAMES_PER_10MIN * 6; // 215784 function pad2(n) { return String(Math.floor(n)).padStart(2, '0'); } function framesToTC(totalFrames) { - const fc = Math.max(0, Math.round(totalFrames)); - const h = Math.floor(fc / FRAMES_PER_HOUR); - let rem = fc % FRAMES_PER_HOUR; - const tm = Math.floor(rem / FRAMES_PER_10MIN); - rem = rem % FRAMES_PER_10MIN; - let m = 0; - if (rem >= DROP) { - m = Math.floor((rem - DROP) / FRAMES_PER_MIN) + 1; - rem = (rem - DROP) % FRAMES_PER_MIN; + const fc = Math.max(0, Math.round(totalFrames)); + const h = Math.floor(fc / FRAMES_PER_HOUR); + let rem = fc % FRAMES_PER_HOUR; + const tm = Math.floor(rem / FRAMES_PER_10MIN); + rem = rem % FRAMES_PER_10MIN; + let m, ss, ff; + // The first minute of each 10-minute group is non-drop (rem < 3600). + // Minutes 1-9 are drop-frame and start at frame label :00;04. + if (rem < FRAMES_FIRST_MIN) { + m = 0; ss = Math.floor(rem / NOM); ff = rem % NOM; + } else { + rem -= FRAMES_FIRST_MIN; + m = Math.floor(rem / FRAMES_PER_MIN) + 1; + const remInMin = rem % FRAMES_PER_MIN; + const adj = remInMin + DROP; // shift so label starts at :00;04 + ss = Math.floor(adj / NOM); ff = adj % NOM; } - const M = tm * 10 + m; - const s = Math.floor(rem / NOM); - const ff = rem % NOM; - return `${pad2(h)}:${pad2(M)}:${pad2(s)};${pad2(ff)}`; + const M = tm * 10 + m; + return `${pad2(h)}:${pad2(M)}:${pad2(ss)};${pad2(ff)}`; } function generateEDL(seqName, clips) {