(html: string, totalDuration: number)
| 191 | // ── Timing normalization agent ──────────────────────────────────────────────── |
| 192 | |
| 193 | export async function normalizeTiming(html: string, totalDuration: number): Promise<string> { |
| 194 | const comp = await openComposition(html); |
| 195 | |
| 196 | const timedEls = comp.getElements().filter((el) => el.start !== null && el.duration !== null); |
| 197 | |
| 198 | const lastEnd = timedEls.reduce( |
| 199 | (max, el) => Math.max(max, (el.start ?? 0) + (el.duration ?? 0)), |
| 200 | 0, |
| 201 | ); |
| 202 | if (lastEnd === 0) return comp.serialize(); |
| 203 | |
| 204 | const scale = totalDuration / lastEnd; |
| 205 | |
| 206 | comp.batch(() => { |
| 207 | for (const el of timedEls) { |
| 208 | comp.setTiming(el.id, { |
| 209 | start: Math.round((el.start ?? 0) * scale * 100) / 100, |
| 210 | duration: Math.round((el.duration ?? 0) * scale * 100) / 100, |
| 211 | }); |
| 212 | } |
| 213 | comp.dispatch({ type: "setCompositionMetadata", duration: totalDuration }); |
| 214 | }); |
| 215 | |
| 216 | return comp.serialize(); |
| 217 | } |
nothing calls this directly
no test coverage detected