@vosjs/studio-core 0.10.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +268 -39
- package/dist/index.js +501 -180
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -424,12 +424,358 @@ function projectFromArtifact(artifact, videoUrl, opts = {}) {
|
|
|
424
424
|
return { doc, videoUrl };
|
|
425
425
|
}
|
|
426
426
|
|
|
427
|
+
// src/lower/motion.ts
|
|
428
|
+
import { sortKeyframes } from "@vosjs/timeline";
|
|
429
|
+
|
|
430
|
+
// src/anim.ts
|
|
431
|
+
var CARD_ENTER_KINDS = [
|
|
432
|
+
"none",
|
|
433
|
+
"fade",
|
|
434
|
+
"rise",
|
|
435
|
+
"tilt-in",
|
|
436
|
+
"pull-out"
|
|
437
|
+
];
|
|
438
|
+
var CARD_EXIT_KINDS = ["none", "fade", "recede"];
|
|
439
|
+
var TEXT_ENTER_KINDS = [
|
|
440
|
+
"none",
|
|
441
|
+
"fade",
|
|
442
|
+
"rise",
|
|
443
|
+
"pop",
|
|
444
|
+
"blur",
|
|
445
|
+
"typewriter"
|
|
446
|
+
];
|
|
447
|
+
var TEXT_EXIT_KINDS = ["none", "fade", "rise"];
|
|
448
|
+
var MEDIA_ENTER_KINDS = ["none", "fade", "rise"];
|
|
449
|
+
var MEDIA_EXIT_KINDS = ["none", "fade", "rise"];
|
|
450
|
+
var IDLE_KINDS = ["spin", "float"];
|
|
451
|
+
var UNIT_KINDS = /* @__PURE__ */ new Set(["pop", "blur", "typewriter"]);
|
|
452
|
+
function animStep(step) {
|
|
453
|
+
if (step == null) return null;
|
|
454
|
+
if (typeof step === "string") return { kind: step };
|
|
455
|
+
return step;
|
|
456
|
+
}
|
|
457
|
+
function enterOf(anim) {
|
|
458
|
+
return animStep(anim?.enter);
|
|
459
|
+
}
|
|
460
|
+
function exitOf(anim) {
|
|
461
|
+
return animStep(anim?.exit);
|
|
462
|
+
}
|
|
463
|
+
function isUnitStep(step) {
|
|
464
|
+
if (!step) return false;
|
|
465
|
+
if (UNIT_KINDS.has(step.kind)) return true;
|
|
466
|
+
if (step.kind !== "fade" && step.kind !== "rise") return false;
|
|
467
|
+
return step.unit !== void 0 || step.stagger !== void 0 || step.seconds !== void 0 || step.direction !== void 0;
|
|
468
|
+
}
|
|
469
|
+
function overlayFxSpec(clip) {
|
|
470
|
+
const step = enterOf(clip.anim);
|
|
471
|
+
if (!isUnitStep(step) || !step || step.kind === "none") return null;
|
|
472
|
+
const kind = step.kind;
|
|
473
|
+
const fx = kind === "fade" || kind === "rise" || kind === "pop" || kind === "blur" || kind === "typewriter" ? kind : "rise";
|
|
474
|
+
return {
|
|
475
|
+
fx,
|
|
476
|
+
...step.unit !== void 0 ? { unit: step.unit } : {},
|
|
477
|
+
...step.direction !== void 0 ? { direction: step.direction } : {},
|
|
478
|
+
...step.stagger !== void 0 ? { stagger: step.stagger } : {},
|
|
479
|
+
...step.seconds !== void 0 ? { duration: step.seconds } : {}
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
var BLOCK_KINDS = /* @__PURE__ */ new Set(["none", "fade", "rise"]);
|
|
483
|
+
function enterKey(clip) {
|
|
484
|
+
const step = enterOf(clip.anim);
|
|
485
|
+
if (!step) return "rise";
|
|
486
|
+
return BLOCK_KINDS.has(step.kind) ? step.kind : "rise";
|
|
487
|
+
}
|
|
488
|
+
function exitKey(clip) {
|
|
489
|
+
const step = exitOf(clip.anim);
|
|
490
|
+
if (!step) return "fade";
|
|
491
|
+
return BLOCK_KINDS.has(step.kind) ? step.kind : "fade";
|
|
492
|
+
}
|
|
493
|
+
function idleKey(clip) {
|
|
494
|
+
const idle = clip.anim?.idle;
|
|
495
|
+
return idle === "spin" || idle === "float" ? idle : null;
|
|
496
|
+
}
|
|
497
|
+
function lastLayerEnd(doc) {
|
|
498
|
+
let end = 0;
|
|
499
|
+
for (const o of doc.overlays ?? []) end = Math.max(end, o.start + o.duration);
|
|
500
|
+
for (const o of doc.objects ?? [])
|
|
501
|
+
if (o.span) end = Math.max(end, o.span.start + o.span.duration);
|
|
502
|
+
return Number.isFinite(end) && end > 0 ? end : 0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// src/lower/motion.ts
|
|
506
|
+
import { splitBySpeed, totalDuration } from "@vosjs/timeline";
|
|
507
|
+
function docRestTime(doc) {
|
|
508
|
+
if (doc.endCard) return null;
|
|
509
|
+
const last = doc.segments.at(-1);
|
|
510
|
+
const hold = last?.hold;
|
|
511
|
+
if (typeof hold !== "number" || !(hold > 0)) return null;
|
|
512
|
+
const segs = doc.segments.length ? doc.segments : [{ in: 0, out: doc.source.meta.durationMs / 1e3 }];
|
|
513
|
+
const total = totalDuration(
|
|
514
|
+
withHolds(segs, splitBySpeed(segs, doc.speed ?? []))
|
|
515
|
+
);
|
|
516
|
+
const rest = total - hold;
|
|
517
|
+
if (!(rest >= 0)) return null;
|
|
518
|
+
return Math.round(rest * 1e3) / 1e3;
|
|
519
|
+
}
|
|
520
|
+
var ENTRANCE_SECONDS = 1.2;
|
|
521
|
+
var END_CARD_SECONDS = 2.5;
|
|
522
|
+
var END_CARD_RECEDE = 0.7;
|
|
523
|
+
var CARD_FADE_SECONDS = 0.35;
|
|
524
|
+
var TILT_IN_POSE = [-9, 14];
|
|
525
|
+
var PULL_OUT_LEVEL = 1.32;
|
|
526
|
+
var END_CARD_FROM = "endcard";
|
|
527
|
+
var HOLD_SOURCE_SPAN = 2e-3;
|
|
528
|
+
function cardEnter(frame) {
|
|
529
|
+
return enterOf(frame.anim);
|
|
530
|
+
}
|
|
531
|
+
function cardExit(frame) {
|
|
532
|
+
return exitOf(frame.anim);
|
|
533
|
+
}
|
|
534
|
+
function entranceSeconds(e) {
|
|
535
|
+
if (!e || e.kind === "none") return 0;
|
|
536
|
+
return Math.max(0.2, Math.min(3, e.seconds ?? ENTRANCE_SECONDS));
|
|
537
|
+
}
|
|
538
|
+
function exitSeconds(e) {
|
|
539
|
+
if (!e || e.kind === "none") return 0;
|
|
540
|
+
const house = e.kind === "fade" ? CARD_FADE_SECONDS : END_CARD_RECEDE;
|
|
541
|
+
return Math.max(0.1, Math.min(3, e.seconds ?? house));
|
|
542
|
+
}
|
|
543
|
+
function withHolds(docSegments, rated) {
|
|
544
|
+
const out = [];
|
|
545
|
+
const pending = docSegments.filter((s) => typeof s.hold === "number" && s.hold > 0).map((s) => ({ out: s.out, hold: s.hold, used: false }));
|
|
546
|
+
for (let i = 0; i < rated.length; i++) {
|
|
547
|
+
const piece = rated[i];
|
|
548
|
+
out.push(piece);
|
|
549
|
+
const next = rated[i + 1];
|
|
550
|
+
for (const p of pending) {
|
|
551
|
+
if (p.used) continue;
|
|
552
|
+
const endsHere = Math.abs(piece.out - p.out) < 1e-9;
|
|
553
|
+
const nextContinues = next && Math.abs(next.in - p.out) < 1e-9 && next.out > p.out;
|
|
554
|
+
if (endsHere && !nextContinues) {
|
|
555
|
+
out.push({
|
|
556
|
+
in: p.out - HOLD_SOURCE_SPAN,
|
|
557
|
+
out: p.out,
|
|
558
|
+
rate: HOLD_SOURCE_SPAN / p.hold
|
|
559
|
+
});
|
|
560
|
+
p.used = true;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
return out;
|
|
565
|
+
}
|
|
566
|
+
function entranceTiltKeyframes(e) {
|
|
567
|
+
const s = entranceSeconds(e);
|
|
568
|
+
if (!s || e?.kind !== "tilt-in") return [];
|
|
569
|
+
return [
|
|
570
|
+
{ t: 0, value: [...TILT_IN_POSE], ease: "none" },
|
|
571
|
+
{ t: s, value: [0, 0], ease: "power3.out" }
|
|
572
|
+
];
|
|
573
|
+
}
|
|
574
|
+
function entranceZoomKeyframes(e) {
|
|
575
|
+
const s = entranceSeconds(e);
|
|
576
|
+
if (!s) return [];
|
|
577
|
+
if (e?.kind === "pull-out")
|
|
578
|
+
return [
|
|
579
|
+
{ t: 0, value: [PULL_OUT_LEVEL, 0.5, 0.42], ease: "none" },
|
|
580
|
+
{ t: s, value: [1, 0.5, 0.5], ease: "power3.out" }
|
|
581
|
+
];
|
|
582
|
+
return [
|
|
583
|
+
{ t: 0, value: [1, 0.5, 0.5], ease: "none" },
|
|
584
|
+
{ t: s, value: [1, 0.5, 0.5], ease: "none" }
|
|
585
|
+
];
|
|
586
|
+
}
|
|
587
|
+
function prependEntrance(track, head) {
|
|
588
|
+
if (!head.length) return track;
|
|
589
|
+
const end = head[head.length - 1].t;
|
|
590
|
+
const rest = (track?.keyframes ?? []).filter((k) => k.t > end + 0.1);
|
|
591
|
+
return { keyframes: sortKeyframes([...head, ...rest]) };
|
|
592
|
+
}
|
|
593
|
+
function exitPose(e) {
|
|
594
|
+
return e?.kind === "fade" ? [1, 0, 0] : [0.9, -0.02, 0.22];
|
|
595
|
+
}
|
|
596
|
+
function cardPoseTrack(enter, exit, footageEnd, outputEnd2 = footageEnd) {
|
|
597
|
+
const keyframes = [];
|
|
598
|
+
const s = entranceSeconds(enter);
|
|
599
|
+
if (s) {
|
|
600
|
+
const from = enter?.kind === "rise" ? [0.96, 0.08, 0.7] : enter?.kind === "pull-out" || enter?.kind === "fade" ? enter.kind === "fade" ? [1, 0, 0] : [1, 0, 1] : [0.94, 0.05, 0.7];
|
|
601
|
+
keyframes.push({ t: 0, value: from, ease: "none" });
|
|
602
|
+
keyframes.push({ t: s, value: [1, 0, 1], ease: "power3.out" });
|
|
603
|
+
}
|
|
604
|
+
const x = exitSeconds(exit);
|
|
605
|
+
if (x > 0 && footageEnd > 0) {
|
|
606
|
+
const room = outputEnd2 - footageEnd;
|
|
607
|
+
const t0 = Math.max(s, room > 1e-6 ? footageEnd : footageEnd - x);
|
|
608
|
+
const t1 = room > 1e-6 ? t0 + Math.min(x, Math.max(0.1, room)) : t0 + x;
|
|
609
|
+
keyframes.push({ t: t0, value: [1, 0, 1], ease: "none" });
|
|
610
|
+
keyframes.push({ t: t1, value: exitPose(exit), ease: "power2.out" });
|
|
611
|
+
}
|
|
612
|
+
if (!keyframes.length) return void 0;
|
|
613
|
+
return { keyframes: sortKeyframes(keyframes) };
|
|
614
|
+
}
|
|
615
|
+
function endCardClips(card, doc, endStart) {
|
|
616
|
+
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
617
|
+
const anim = { enter: "rise", exit: "none" };
|
|
618
|
+
const clips = [];
|
|
619
|
+
const text = (id, body, preset, y, delay) => ({
|
|
620
|
+
id,
|
|
621
|
+
kind: "text",
|
|
622
|
+
text: body,
|
|
623
|
+
preset,
|
|
624
|
+
start: endStart + delay,
|
|
625
|
+
duration: Math.max(0.3, seconds - delay),
|
|
626
|
+
transform: { x: 0.5, y, scale: 1, rotation: 0 },
|
|
627
|
+
anim,
|
|
628
|
+
from: END_CARD_FROM,
|
|
629
|
+
align: "center",
|
|
630
|
+
...card.ink ? { color: card.ink } : {},
|
|
631
|
+
shadow: 0
|
|
632
|
+
});
|
|
633
|
+
if (card.headline?.trim())
|
|
634
|
+
clips.push(text("endcard-title", card.headline.trim(), "title", 0.44, 0.35));
|
|
635
|
+
if (card.sub?.trim())
|
|
636
|
+
clips.push(text("endcard-sub", card.sub.trim(), "caption", 0.57, 0.5));
|
|
637
|
+
const mark = card.mark;
|
|
638
|
+
const wide = !!mark && mark.aspect > 2.2;
|
|
639
|
+
if (mark && mark.key) {
|
|
640
|
+
const size = resolveExportSize(doc);
|
|
641
|
+
const designW = 1080 * size.width / Math.max(1, size.height);
|
|
642
|
+
const hPx = wide ? 44 : 30;
|
|
643
|
+
const clip = {
|
|
644
|
+
id: "endcard-markimg",
|
|
645
|
+
kind: "image",
|
|
646
|
+
key: mark.key,
|
|
647
|
+
width: Math.min(0.9, hPx * Math.max(0.2, mark.aspect) / designW),
|
|
648
|
+
radius: 0,
|
|
649
|
+
shadow: "none",
|
|
650
|
+
start: endStart + 0.65,
|
|
651
|
+
duration: Math.max(0.3, seconds - 0.65),
|
|
652
|
+
transform: { x: 0.5, y: wide ? 0.88 : 0.835, scale: 1, rotation: 0 },
|
|
653
|
+
anim,
|
|
654
|
+
from: END_CARD_FROM
|
|
655
|
+
};
|
|
656
|
+
clips.push(clip);
|
|
657
|
+
}
|
|
658
|
+
if (card.wordmark?.trim() && !wide)
|
|
659
|
+
clips.push(
|
|
660
|
+
text(
|
|
661
|
+
"endcard-mark",
|
|
662
|
+
card.wordmark.trim(),
|
|
663
|
+
"label",
|
|
664
|
+
mark && mark.key ? 0.895 : 0.88,
|
|
665
|
+
0.65
|
|
666
|
+
)
|
|
667
|
+
);
|
|
668
|
+
return clips;
|
|
669
|
+
}
|
|
670
|
+
function expandEndCard(doc, outputDuration) {
|
|
671
|
+
const card = doc.endCard;
|
|
672
|
+
if (!card || !doc.segments.length) return { doc, endStart: null, seconds: 0 };
|
|
673
|
+
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
674
|
+
const segments = doc.segments.map(
|
|
675
|
+
(s, i) => i === doc.segments.length - 1 ? { ...s, hold: (s.hold ?? 0) + seconds } : s
|
|
676
|
+
);
|
|
677
|
+
const endStart = outputDuration;
|
|
678
|
+
const overlays = [
|
|
679
|
+
...doc.overlays ?? [],
|
|
680
|
+
...endCardClips(card, doc, endStart)
|
|
681
|
+
];
|
|
682
|
+
return { doc: { ...doc, segments, overlays }, endStart, seconds };
|
|
683
|
+
}
|
|
684
|
+
var hasLegacyClipMotion = (o) => o.enter !== void 0 || o.exit !== void 0 || o.kind === "text" && o.fx !== void 0;
|
|
685
|
+
function migrateClipAnim(o) {
|
|
686
|
+
const anim = { ...o.anim ?? {} };
|
|
687
|
+
if (o.kind === "text" && o.fx) {
|
|
688
|
+
const fx = o.fx;
|
|
689
|
+
anim.enter = {
|
|
690
|
+
kind: fx.fx,
|
|
691
|
+
unit: fx.unit ?? "block",
|
|
692
|
+
...fx.direction !== void 0 ? { direction: fx.direction } : {},
|
|
693
|
+
...fx.stagger !== void 0 ? { stagger: fx.stagger } : {},
|
|
694
|
+
...fx.duration !== void 0 ? { seconds: fx.duration } : {}
|
|
695
|
+
};
|
|
696
|
+
} else if (o.enter !== void 0 && anim.enter === void 0) {
|
|
697
|
+
anim.enter = o.enter;
|
|
698
|
+
}
|
|
699
|
+
if (o.exit !== void 0 && anim.exit === void 0) anim.exit = o.exit;
|
|
700
|
+
return anim;
|
|
701
|
+
}
|
|
702
|
+
function migrateMotion(doc) {
|
|
703
|
+
const frame = doc.frame ?? {};
|
|
704
|
+
const segments = Array.isArray(doc.segments) ? doc.segments : [];
|
|
705
|
+
const overlays = Array.isArray(doc.overlays) ? doc.overlays : [];
|
|
706
|
+
const objects = Array.isArray(doc.objects) ? doc.objects : [];
|
|
707
|
+
const legacy = frame.entrance !== void 0 || doc.endCard !== void 0 || overlays.some(hasLegacyClipMotion) || objects.some((o) => o.animation !== void 0);
|
|
708
|
+
if (!legacy) return doc;
|
|
709
|
+
const out = { ...doc };
|
|
710
|
+
const nextFrame = { ...frame };
|
|
711
|
+
if (frame.entrance !== void 0) {
|
|
712
|
+
const e = frame.entrance;
|
|
713
|
+
if (e && e.kind !== "none") {
|
|
714
|
+
nextFrame.anim = {
|
|
715
|
+
...frame.anim ?? {},
|
|
716
|
+
enter: e.seconds !== void 0 ? { kind: e.kind, seconds: e.seconds } : e.kind
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
delete nextFrame.entrance;
|
|
720
|
+
}
|
|
721
|
+
let nextOverlays = overlays.map((o) => {
|
|
722
|
+
if (!hasLegacyClipMotion(o)) return o;
|
|
723
|
+
const next = { ...o, anim: migrateClipAnim(o) };
|
|
724
|
+
delete next.enter;
|
|
725
|
+
delete next.exit;
|
|
726
|
+
if (next.kind === "text") delete next.fx;
|
|
727
|
+
return next;
|
|
728
|
+
});
|
|
729
|
+
if (doc.endCard !== void 0) {
|
|
730
|
+
const card = doc.endCard;
|
|
731
|
+
if (card && segments.length) {
|
|
732
|
+
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
733
|
+
const rated = withHolds(segments, splitBySpeed(segments, doc.speed ?? []));
|
|
734
|
+
const endStart = totalDuration(rated);
|
|
735
|
+
nextOverlays = [...nextOverlays, ...endCardClips(card, doc, endStart)];
|
|
736
|
+
nextFrame.anim = {
|
|
737
|
+
...nextFrame.anim ?? {},
|
|
738
|
+
exit: {
|
|
739
|
+
kind: "recede",
|
|
740
|
+
seconds: Math.min(END_CARD_RECEDE, seconds * 0.4)
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
delete out.endCard;
|
|
745
|
+
}
|
|
746
|
+
const nextObjects = objects.map((o) => {
|
|
747
|
+
if (o.animation === void 0) return o;
|
|
748
|
+
const next = {
|
|
749
|
+
...o,
|
|
750
|
+
anim: {
|
|
751
|
+
...o.anim ?? {},
|
|
752
|
+
...o.anim?.idle === void 0 ? { idle: o.animation ?? null } : {}
|
|
753
|
+
}
|
|
754
|
+
};
|
|
755
|
+
delete next.animation;
|
|
756
|
+
return next;
|
|
757
|
+
});
|
|
758
|
+
if (doc.frame !== void 0 || nextFrame.anim !== void 0)
|
|
759
|
+
out.frame = nextFrame;
|
|
760
|
+
if (doc.overlays !== void 0 || nextOverlays.length)
|
|
761
|
+
out.overlays = nextOverlays;
|
|
762
|
+
if (doc.objects !== void 0) out.objects = nextObjects;
|
|
763
|
+
return out;
|
|
764
|
+
}
|
|
765
|
+
function outputEnd(doc, footageEnd) {
|
|
766
|
+
return Math.max(footageEnd, lastLayerEnd(doc));
|
|
767
|
+
}
|
|
768
|
+
|
|
427
769
|
// src/docVersion.ts
|
|
428
|
-
var DOC_SCHEMA_VERSION =
|
|
770
|
+
var DOC_SCHEMA_VERSION = 3;
|
|
429
771
|
function migrateHostedDoc(raw) {
|
|
430
772
|
const version = typeof raw.docSchemaVersion === "number" ? raw.docSchemaVersion : 0;
|
|
431
773
|
if (version >= DOC_SCHEMA_VERSION) return raw;
|
|
432
|
-
|
|
774
|
+
let doc = raw;
|
|
775
|
+
if (version < 3 && doc.source && typeof doc.source === "object") {
|
|
776
|
+
doc = migrateMotion(doc);
|
|
777
|
+
}
|
|
778
|
+
return { ...doc, docSchemaVersion: DOC_SCHEMA_VERSION };
|
|
433
779
|
}
|
|
434
780
|
|
|
435
781
|
// src/doc/studioDoc.ts
|
|
@@ -1452,7 +1798,7 @@ function overlaySegments(text, unit) {
|
|
|
1452
1798
|
}
|
|
1453
1799
|
var FX_DIR = { forward: 0, reverse: 1, center: 2 };
|
|
1454
1800
|
function resolveOverlayFx(clip, clipDuration) {
|
|
1455
|
-
const spec = clip.fx;
|
|
1801
|
+
const spec = overlayFxSpec(clip) ?? clip.fx ?? null;
|
|
1456
1802
|
if (!spec) return null;
|
|
1457
1803
|
const unit = spec.unit ?? "block";
|
|
1458
1804
|
const units = overlaySegments(clip.text, unit);
|
|
@@ -2772,164 +3118,6 @@ var STUDIO_FRAME = `(ctx, content, dt) => {
|
|
|
2772
3118
|
|
|
2773
3119
|
}`;
|
|
2774
3120
|
|
|
2775
|
-
// src/lower/motion.ts
|
|
2776
|
-
import { sortKeyframes } from "@vosjs/timeline";
|
|
2777
|
-
import { splitBySpeed, totalDuration } from "@vosjs/timeline";
|
|
2778
|
-
function docRestTime(doc) {
|
|
2779
|
-
if (doc.endCard) return null;
|
|
2780
|
-
const last = doc.segments.at(-1);
|
|
2781
|
-
const hold = last?.hold;
|
|
2782
|
-
if (typeof hold !== "number" || !(hold > 0)) return null;
|
|
2783
|
-
const segs = doc.segments.length ? doc.segments : [{ in: 0, out: doc.source.meta.durationMs / 1e3 }];
|
|
2784
|
-
const total = totalDuration(
|
|
2785
|
-
withHolds(segs, splitBySpeed(segs, doc.speed ?? []))
|
|
2786
|
-
);
|
|
2787
|
-
const rest = total - hold;
|
|
2788
|
-
if (!(rest >= 0)) return null;
|
|
2789
|
-
return Math.round(rest * 1e3) / 1e3;
|
|
2790
|
-
}
|
|
2791
|
-
var ENTRANCE_SECONDS = 1.2;
|
|
2792
|
-
var END_CARD_SECONDS = 2.5;
|
|
2793
|
-
var END_CARD_RECEDE = 0.7;
|
|
2794
|
-
var TILT_IN_POSE = [-9, 14];
|
|
2795
|
-
var PULL_OUT_LEVEL = 1.32;
|
|
2796
|
-
var HOLD_SOURCE_SPAN = 2e-3;
|
|
2797
|
-
function entranceSeconds(e) {
|
|
2798
|
-
if (!e || e.kind === "none") return 0;
|
|
2799
|
-
return Math.max(0.2, Math.min(3, e.seconds ?? ENTRANCE_SECONDS));
|
|
2800
|
-
}
|
|
2801
|
-
function withHolds(docSegments, rated) {
|
|
2802
|
-
const out = [];
|
|
2803
|
-
const pending = docSegments.filter((s) => typeof s.hold === "number" && s.hold > 0).map((s) => ({ out: s.out, hold: s.hold, used: false }));
|
|
2804
|
-
for (let i = 0; i < rated.length; i++) {
|
|
2805
|
-
const piece = rated[i];
|
|
2806
|
-
out.push(piece);
|
|
2807
|
-
const next = rated[i + 1];
|
|
2808
|
-
for (const p of pending) {
|
|
2809
|
-
if (p.used) continue;
|
|
2810
|
-
const endsHere = Math.abs(piece.out - p.out) < 1e-9;
|
|
2811
|
-
const nextContinues = next && Math.abs(next.in - p.out) < 1e-9 && next.out > p.out;
|
|
2812
|
-
if (endsHere && !nextContinues) {
|
|
2813
|
-
out.push({
|
|
2814
|
-
in: p.out - HOLD_SOURCE_SPAN,
|
|
2815
|
-
out: p.out,
|
|
2816
|
-
rate: HOLD_SOURCE_SPAN / p.hold
|
|
2817
|
-
});
|
|
2818
|
-
p.used = true;
|
|
2819
|
-
}
|
|
2820
|
-
}
|
|
2821
|
-
}
|
|
2822
|
-
return out;
|
|
2823
|
-
}
|
|
2824
|
-
function entranceTiltKeyframes(e) {
|
|
2825
|
-
const s = entranceSeconds(e);
|
|
2826
|
-
if (!s || e?.kind !== "tilt-in") return [];
|
|
2827
|
-
return [
|
|
2828
|
-
{ t: 0, value: [...TILT_IN_POSE], ease: "none" },
|
|
2829
|
-
{ t: s, value: [0, 0], ease: "power3.out" }
|
|
2830
|
-
];
|
|
2831
|
-
}
|
|
2832
|
-
function entranceZoomKeyframes(e) {
|
|
2833
|
-
const s = entranceSeconds(e);
|
|
2834
|
-
if (!s) return [];
|
|
2835
|
-
if (e?.kind === "pull-out")
|
|
2836
|
-
return [
|
|
2837
|
-
{ t: 0, value: [PULL_OUT_LEVEL, 0.5, 0.42], ease: "none" },
|
|
2838
|
-
{ t: s, value: [1, 0.5, 0.5], ease: "power3.out" }
|
|
2839
|
-
];
|
|
2840
|
-
return [
|
|
2841
|
-
{ t: 0, value: [1, 0.5, 0.5], ease: "none" },
|
|
2842
|
-
{ t: s, value: [1, 0.5, 0.5], ease: "none" }
|
|
2843
|
-
];
|
|
2844
|
-
}
|
|
2845
|
-
function prependEntrance(track, head) {
|
|
2846
|
-
if (!head.length) return track;
|
|
2847
|
-
const end = head[head.length - 1].t;
|
|
2848
|
-
const rest = (track?.keyframes ?? []).filter((k) => k.t > end + 0.1);
|
|
2849
|
-
return { keyframes: sortKeyframes([...head, ...rest]) };
|
|
2850
|
-
}
|
|
2851
|
-
function cardPoseTrack(e, endStart, endSeconds) {
|
|
2852
|
-
const keyframes = [];
|
|
2853
|
-
const s = entranceSeconds(e);
|
|
2854
|
-
if (s) {
|
|
2855
|
-
const from = e?.kind === "rise" ? [0.96, 0.08, 0.7] : e?.kind === "pull-out" ? [1, 0, 1] : [0.94, 0.05, 0.7];
|
|
2856
|
-
keyframes.push({ t: 0, value: from, ease: "none" });
|
|
2857
|
-
keyframes.push({ t: s, value: [1, 0, 1], ease: "power3.out" });
|
|
2858
|
-
}
|
|
2859
|
-
if (endStart !== null && endSeconds > 0) {
|
|
2860
|
-
const t0 = Math.max(endStart, s);
|
|
2861
|
-
keyframes.push({ t: t0, value: [1, 0, 1], ease: "none" });
|
|
2862
|
-
keyframes.push({
|
|
2863
|
-
t: t0 + Math.min(END_CARD_RECEDE, endSeconds * 0.4),
|
|
2864
|
-
value: [0.9, -0.02, 0.22],
|
|
2865
|
-
ease: "power2.out"
|
|
2866
|
-
});
|
|
2867
|
-
}
|
|
2868
|
-
if (!keyframes.length) return void 0;
|
|
2869
|
-
return { keyframes: sortKeyframes(keyframes) };
|
|
2870
|
-
}
|
|
2871
|
-
function expandEndCard(doc, outputDuration) {
|
|
2872
|
-
const card = doc.endCard;
|
|
2873
|
-
if (!card || !doc.segments.length) return { doc, endStart: null, seconds: 0 };
|
|
2874
|
-
const seconds = Math.max(1, Math.min(8, card.seconds ?? END_CARD_SECONDS));
|
|
2875
|
-
const segments = doc.segments.map(
|
|
2876
|
-
(s, i) => i === doc.segments.length - 1 ? { ...s, hold: (s.hold ?? 0) + seconds } : s
|
|
2877
|
-
);
|
|
2878
|
-
const endStart = outputDuration;
|
|
2879
|
-
const clips = [];
|
|
2880
|
-
const text = (id, body, preset, y, delay) => ({
|
|
2881
|
-
id,
|
|
2882
|
-
kind: "text",
|
|
2883
|
-
text: body,
|
|
2884
|
-
preset,
|
|
2885
|
-
start: endStart + delay,
|
|
2886
|
-
duration: Math.max(0.3, seconds - delay),
|
|
2887
|
-
transform: { x: 0.5, y, scale: 1, rotation: 0 },
|
|
2888
|
-
enter: "rise",
|
|
2889
|
-
exit: "none",
|
|
2890
|
-
align: "center",
|
|
2891
|
-
...card.ink ? { color: card.ink } : {},
|
|
2892
|
-
shadow: 0
|
|
2893
|
-
});
|
|
2894
|
-
if (card.headline?.trim())
|
|
2895
|
-
clips.push(text("endcard-title", card.headline.trim(), "title", 0.44, 0.35));
|
|
2896
|
-
if (card.sub?.trim())
|
|
2897
|
-
clips.push(text("endcard-sub", card.sub.trim(), "caption", 0.57, 0.5));
|
|
2898
|
-
const mark = card.mark;
|
|
2899
|
-
const wide = !!mark && mark.aspect > 2.2;
|
|
2900
|
-
if (mark && mark.key) {
|
|
2901
|
-
const size = resolveExportSize(doc);
|
|
2902
|
-
const designW = 1080 * size.width / Math.max(1, size.height);
|
|
2903
|
-
const hPx = wide ? 44 : 30;
|
|
2904
|
-
const clip = {
|
|
2905
|
-
id: "endcard-markimg",
|
|
2906
|
-
kind: "image",
|
|
2907
|
-
key: mark.key,
|
|
2908
|
-
width: Math.min(0.9, hPx * Math.max(0.2, mark.aspect) / designW),
|
|
2909
|
-
radius: 0,
|
|
2910
|
-
shadow: "none",
|
|
2911
|
-
start: endStart + 0.65,
|
|
2912
|
-
duration: Math.max(0.3, seconds - 0.65),
|
|
2913
|
-
transform: { x: 0.5, y: wide ? 0.88 : 0.835, scale: 1, rotation: 0 },
|
|
2914
|
-
enter: "rise",
|
|
2915
|
-
exit: "none"
|
|
2916
|
-
};
|
|
2917
|
-
clips.push(clip);
|
|
2918
|
-
}
|
|
2919
|
-
if (card.wordmark?.trim() && !wide)
|
|
2920
|
-
clips.push(
|
|
2921
|
-
text(
|
|
2922
|
-
"endcard-mark",
|
|
2923
|
-
card.wordmark.trim(),
|
|
2924
|
-
"label",
|
|
2925
|
-
mark && mark.key ? 0.895 : 0.88,
|
|
2926
|
-
0.65
|
|
2927
|
-
)
|
|
2928
|
-
);
|
|
2929
|
-
const overlays = [...doc.overlays ?? [], ...clips];
|
|
2930
|
-
return { doc: { ...doc, segments, overlays }, endStart, seconds };
|
|
2931
|
-
}
|
|
2932
|
-
|
|
2933
3121
|
// src/lower/extractClicks.ts
|
|
2934
3122
|
import { segmentRate, sourceToTimeline } from "@vosjs/timeline";
|
|
2935
3123
|
var CLICK_FX_PRE = 0.06;
|
|
@@ -3772,6 +3960,15 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3772
3960
|
// range); the paused/seek path needs nothing \u2014 mapTime already lands srcT.
|
|
3773
3961
|
var srcRate = TL.rateAt ? TL.rateAt(d.segments || [], t) : 1
|
|
3774
3962
|
var playRate = Math.min(16, Math.max(0.0625, srcRate))
|
|
3963
|
+
// Where the FOOTAGE ends in output seconds. The output may outlast it
|
|
3964
|
+
// (clips placed after the footage), and a hold is a freeze piece whose
|
|
3965
|
+
// rate is tiny: in both the element must stay PAUSED on its frame. An
|
|
3966
|
+
// ended element's play() rewinds it to zero and the drift guard then
|
|
3967
|
+
// seeks it back, which reads as frames jumping back and forth; a hold
|
|
3968
|
+
// crawling at the clamped 1/16 speed toward that same end was the same
|
|
3969
|
+
// bug in slow motion.
|
|
3970
|
+
var footEnd = TL.totalDuration ? TL.totalDuration(d.segments || []) : Infinity
|
|
3971
|
+
var frozen = srcRate < 0.01 || t >= footEnd - 1e-3
|
|
3775
3972
|
// Drive a <video> to the on-screen SOURCE moment: play natively while playing (drift
|
|
3776
3973
|
// correction covers cut-boundary jumps), else step to the exact frame (registering a
|
|
3777
3974
|
// decode promise so the deterministic export awaits it). Shared by the screen video
|
|
@@ -3779,7 +3976,7 @@ var ON_FRAME = `(ctx, content, dt) => {
|
|
|
3779
3976
|
${FRAME_STEP_SRC}
|
|
3780
3977
|
function syncVid(vid) {
|
|
3781
3978
|
try {
|
|
3782
|
-
if (playing) {
|
|
3979
|
+
if (playing && !frozen) {
|
|
3783
3980
|
if (vid.playbackRate !== playRate) {
|
|
3784
3981
|
vid.playbackRate = playRate
|
|
3785
3982
|
// Resampled (tape-style) speed, matching the export's offline mix.
|
|
@@ -4622,7 +4819,7 @@ function studioLayerData(layers, duration) {
|
|
|
4622
4819
|
ry: round5(o.transform3d.ry),
|
|
4623
4820
|
rz: round5(o.transform3d.rz),
|
|
4624
4821
|
scale: round5(o.transform3d.scale || OBJECT_DEFAULT_SCALE),
|
|
4625
|
-
anim: o
|
|
4822
|
+
anim: idleKey(o),
|
|
4626
4823
|
// Pose keyframes: clip-local [x,y,z,rx,ry,rz,scale] track,
|
|
4627
4824
|
// sampled at t − span.start. Omitted when absent — parity.
|
|
4628
4825
|
...(() => {
|
|
@@ -4654,8 +4851,8 @@ function studioLayerData(layers, duration) {
|
|
|
4654
4851
|
y: round5(o.transform.y),
|
|
4655
4852
|
scale: round5(o.transform.scale || 1),
|
|
4656
4853
|
rot: round5(o.transform.rotation || 0),
|
|
4657
|
-
enter: o
|
|
4658
|
-
exit: o
|
|
4854
|
+
enter: enterKey(o),
|
|
4855
|
+
exit: exitKey(o),
|
|
4659
4856
|
// Pose keyframes: a CLIP-LOCAL [x, y, scale, rot, opacity]
|
|
4660
4857
|
// track, sampled in ON_FRAME at t − start. Omitted when the clip
|
|
4661
4858
|
// has no motion — data byte parity.
|
|
@@ -4743,11 +4940,10 @@ function studioLayerData(layers, duration) {
|
|
|
4743
4940
|
};
|
|
4744
4941
|
}
|
|
4745
4942
|
function lowerToComposition(input) {
|
|
4746
|
-
const
|
|
4747
|
-
const expanded = expandEndCard(input, before);
|
|
4748
|
-
const doc = expanded.doc;
|
|
4943
|
+
const doc = migrateMotion(input);
|
|
4749
4944
|
const rated = ratedSegments(doc);
|
|
4750
|
-
const
|
|
4945
|
+
const footageEnd = durationSec(doc, rated);
|
|
4946
|
+
const duration = outputEnd(doc, footageEnd);
|
|
4751
4947
|
const fx = doc.cursor.clickFx;
|
|
4752
4948
|
const smoothed = smoothCursor(doc.source.cursor, {
|
|
4753
4949
|
factor: doc.cursor.smoothing,
|
|
@@ -4821,7 +5017,7 @@ function lowerToComposition(input) {
|
|
|
4821
5017
|
// A pull-out entrance writes the track's head.
|
|
4822
5018
|
zoomTrack: prependEntrance(
|
|
4823
5019
|
zoomTrackFromDoc(zoomSpans, rated, zoomStyle),
|
|
4824
|
-
entranceZoomKeyframes(doc.frame
|
|
5020
|
+
entranceZoomKeyframes(cardEnter(doc.frame))
|
|
4825
5021
|
),
|
|
4826
5022
|
// Tilt spans: OUTPUT-time [rx, ry] degree track. The rest pose is
|
|
4827
5023
|
// FLAT — there is no static card tilt any more — and the motion constants
|
|
@@ -4830,18 +5026,19 @@ function lowerToComposition(input) {
|
|
|
4830
5026
|
// spans and no tilt-in entrance — byte parity. The entrance is a
|
|
4831
5027
|
// producer of this track, never a second pose.
|
|
4832
5028
|
...(() => {
|
|
4833
|
-
const head = entranceTiltKeyframes(doc.frame
|
|
5029
|
+
const head = entranceTiltKeyframes(cardEnter(doc.frame));
|
|
4834
5030
|
const spans = doc.tilt && doc.tilt.length ? tiltTrackFromDoc(doc.tilt, rated, zoomStyle.tilt) : void 0;
|
|
4835
5031
|
const track = prependEntrance(spans, head);
|
|
4836
5032
|
return track ? { tiltTrack: track } : {};
|
|
4837
5033
|
})(),
|
|
4838
|
-
// The card's pose through
|
|
4839
|
-
//
|
|
5034
|
+
// The card's pose through its enter and its exit: [scale, dy, opacity]
|
|
5035
|
+
// in output seconds. Absent when the card carries neither.
|
|
4840
5036
|
...(() => {
|
|
4841
5037
|
const track = cardPoseTrack(
|
|
4842
|
-
doc.frame
|
|
4843
|
-
|
|
4844
|
-
|
|
5038
|
+
cardEnter(doc.frame),
|
|
5039
|
+
cardExit(doc.frame),
|
|
5040
|
+
footageEnd,
|
|
5041
|
+
duration
|
|
4845
5042
|
);
|
|
4846
5043
|
return track ? { cardPoseTrack: track } : {};
|
|
4847
5044
|
})()
|
|
@@ -5292,11 +5489,15 @@ function zoomCoversRect(span, rect, layout, tol = 0.02) {
|
|
|
5292
5489
|
return rect.x >= w.x0 - tol && rect.x + rect.w <= w.x1 + tol && rect.y >= w.y0 - tol && rect.y + rect.h <= w.y1 + tol;
|
|
5293
5490
|
}
|
|
5294
5491
|
|
|
5492
|
+
// src/digest/style.ts
|
|
5493
|
+
import { totalDuration as totalDuration4 } from "@vosjs/timeline";
|
|
5494
|
+
|
|
5295
5495
|
// src/audioBeds.ts
|
|
5296
5496
|
import { totalDuration as totalDuration3 } from "@vosjs/timeline";
|
|
5297
5497
|
var round32 = (v) => Math.round(v * 1e3) / 1e3;
|
|
5298
5498
|
function docOutputDuration(doc) {
|
|
5299
|
-
|
|
5499
|
+
const footage = totalDuration3(ratedSegments(doc));
|
|
5500
|
+
return isRecordingDoc(doc) ? outputEnd(migrateMotion(doc), footage) : footage;
|
|
5300
5501
|
}
|
|
5301
5502
|
function musicBedClip(input) {
|
|
5302
5503
|
const track = round32(input.trackDuration);
|
|
@@ -5418,7 +5619,7 @@ var LAYOUT_FRAME_FIELDS = [
|
|
|
5418
5619
|
"focus",
|
|
5419
5620
|
"focusFollow",
|
|
5420
5621
|
"parallax",
|
|
5421
|
-
"
|
|
5622
|
+
"anim"
|
|
5422
5623
|
];
|
|
5423
5624
|
var STAGE_CLIP_PREFIX = "stage-";
|
|
5424
5625
|
var REST_TILT_ID = "rest";
|
|
@@ -5504,6 +5705,99 @@ function copyLayout(from, to, opts = {}) {
|
|
|
5504
5705
|
if (typeof hold === "number" && hold > 0 && last) last.hold = hold;
|
|
5505
5706
|
return { doc, notes };
|
|
5506
5707
|
}
|
|
5708
|
+
var shiftBy = (at, templateEnd, takeEnd) => at === "start" ? 0 : at === "end" ? takeEnd - templateEnd : at;
|
|
5709
|
+
function clipsFrom(doc, from) {
|
|
5710
|
+
return {
|
|
5711
|
+
overlays: (doc.overlays ?? []).filter((o) => o.from === from),
|
|
5712
|
+
objects: (doc.objects ?? []).filter((o) => o.from === from),
|
|
5713
|
+
audio: (doc.audio ?? []).filter((a) => a.from === from)
|
|
5714
|
+
};
|
|
5715
|
+
}
|
|
5716
|
+
function dropTemplate(doc, from) {
|
|
5717
|
+
const has = clipsFrom(doc, from);
|
|
5718
|
+
if (!has.overlays.length && !has.objects.length && !has.audio.length)
|
|
5719
|
+
return doc;
|
|
5720
|
+
const out = { ...doc };
|
|
5721
|
+
if (doc.overlays) out.overlays = doc.overlays.filter((o) => o.from !== from);
|
|
5722
|
+
if (doc.objects) out.objects = doc.objects.filter((o) => o.from !== from);
|
|
5723
|
+
out.audio = doc.audio.filter((a) => a.from !== from);
|
|
5724
|
+
return out;
|
|
5725
|
+
}
|
|
5726
|
+
function applyTemplate(template, take, opts) {
|
|
5727
|
+
const from = opts.from ?? "template";
|
|
5728
|
+
const notes = [];
|
|
5729
|
+
const base = dropTemplate(take, from);
|
|
5730
|
+
const doc = structuredClone(base);
|
|
5731
|
+
const templateEnd = totalDuration4(ratedSegments(template));
|
|
5732
|
+
const takeEnd = totalDuration4(ratedSegments(take));
|
|
5733
|
+
const shift = shiftBy(opts.at, templateEnd, takeEnd);
|
|
5734
|
+
const own = new Map((take.overlays ?? []).map((o) => [o.id, o]));
|
|
5735
|
+
const overlays = (doc.overlays ?? []).filter(
|
|
5736
|
+
(o) => !(template.overlays ?? []).some((t) => t.id === o.id)
|
|
5737
|
+
);
|
|
5738
|
+
const skipped = [];
|
|
5739
|
+
for (const clip of template.overlays ?? []) {
|
|
5740
|
+
const next = structuredClone(clip);
|
|
5741
|
+
next.start = Math.max(0, round33(clip.start + shift));
|
|
5742
|
+
next.from = from;
|
|
5743
|
+
const mine = own.get(clip.id);
|
|
5744
|
+
if (next.kind === "text") {
|
|
5745
|
+
const word = opts.words?.[clip.id];
|
|
5746
|
+
if (word !== void 0) next.text = word;
|
|
5747
|
+
else if (mine?.kind === "text") next.text = mine.text;
|
|
5748
|
+
} else if (opts.keys?.[clip.id]) {
|
|
5749
|
+
next.key = opts.keys[clip.id];
|
|
5750
|
+
} else if (mine && mine.kind !== "text") {
|
|
5751
|
+
next.key = mine.key;
|
|
5752
|
+
} else if (!/^(https?:|\/\/)/.test(next.key)) {
|
|
5753
|
+
skipped.push(clip.id);
|
|
5754
|
+
continue;
|
|
5755
|
+
}
|
|
5756
|
+
overlays.push(next);
|
|
5757
|
+
}
|
|
5758
|
+
if (skipped.length)
|
|
5759
|
+
notes.push(
|
|
5760
|
+
`${skipped.join(", ")}: the template's media key is its own; pass keys[id] or the take's clip`
|
|
5761
|
+
);
|
|
5762
|
+
if (overlays.length || doc.overlays) doc.overlays = overlays;
|
|
5763
|
+
const objects = (doc.objects ?? []).filter(
|
|
5764
|
+
(o) => !(template.objects ?? []).some((t) => t.id === o.id)
|
|
5765
|
+
);
|
|
5766
|
+
for (const clip of template.objects ?? []) {
|
|
5767
|
+
const next = structuredClone(clip);
|
|
5768
|
+
if (next.span)
|
|
5769
|
+
next.span.start = Math.max(0, round33(next.span.start + shift));
|
|
5770
|
+
next.from = from;
|
|
5771
|
+
objects.push(next);
|
|
5772
|
+
}
|
|
5773
|
+
if (objects.length || doc.objects) doc.objects = objects;
|
|
5774
|
+
const audio = doc.audio.filter(
|
|
5775
|
+
(a) => !template.audio.some((t) => t.id === a.id)
|
|
5776
|
+
);
|
|
5777
|
+
for (const clip of template.audio) {
|
|
5778
|
+
const next = structuredClone(clip);
|
|
5779
|
+
next.start = Math.max(0, round33(clip.start + shift));
|
|
5780
|
+
next.from = from;
|
|
5781
|
+
audio.push(next);
|
|
5782
|
+
}
|
|
5783
|
+
doc.audio = audio;
|
|
5784
|
+
if (template.frame.anim) {
|
|
5785
|
+
doc.frame = {
|
|
5786
|
+
...doc.frame,
|
|
5787
|
+
anim: { ...doc.frame.anim ?? {}, ...template.frame.anim }
|
|
5788
|
+
};
|
|
5789
|
+
}
|
|
5790
|
+
if (opts.look) {
|
|
5791
|
+
const laid = copyLayout(template, doc, { keys: opts.keys });
|
|
5792
|
+
laid.doc.overlays = (laid.doc.overlays ?? []).map(
|
|
5793
|
+
(o) => isStageClip(o) ? { ...o, from } : o
|
|
5794
|
+
);
|
|
5795
|
+
notes.push(...laid.notes);
|
|
5796
|
+
return { doc: laid.doc, notes };
|
|
5797
|
+
}
|
|
5798
|
+
return { doc, notes };
|
|
5799
|
+
}
|
|
5800
|
+
var round33 = (v) => Math.round(v * 1e3) / 1e3;
|
|
5507
5801
|
|
|
5508
5802
|
// src/digest/geometry.ts
|
|
5509
5803
|
var CROP_MIN_FRAC = 0.25;
|
|
@@ -5580,7 +5874,6 @@ function cropBox(m, geo, meta) {
|
|
|
5580
5874
|
}
|
|
5581
5875
|
|
|
5582
5876
|
// src/digest/build.ts
|
|
5583
|
-
import { totalDuration as totalDuration4 } from "@vosjs/timeline";
|
|
5584
5877
|
var DIGEST_VERSION = 1;
|
|
5585
5878
|
function buildDigest(input) {
|
|
5586
5879
|
const { doc, meta } = { doc: input.doc, meta: input.doc.source.meta };
|
|
@@ -5648,7 +5941,7 @@ function buildDigest(input) {
|
|
|
5648
5941
|
};
|
|
5649
5942
|
}
|
|
5650
5943
|
function outputDurationOf(doc) {
|
|
5651
|
-
return
|
|
5944
|
+
return docOutputDuration(doc);
|
|
5652
5945
|
}
|
|
5653
5946
|
function round8(v) {
|
|
5654
5947
|
return Math.round(v * 1e3) / 1e3;
|
|
@@ -7541,6 +7834,9 @@ export {
|
|
|
7541
7834
|
CAM_SPAN_MIN,
|
|
7542
7835
|
CAPTURE_COVERAGE_MIN,
|
|
7543
7836
|
CARD_EDGE_OVERDRAW,
|
|
7837
|
+
CARD_ENTER_KINDS,
|
|
7838
|
+
CARD_EXIT_KINDS,
|
|
7839
|
+
CARD_FADE_SECONDS,
|
|
7544
7840
|
CARD_FOV,
|
|
7545
7841
|
CARD_Z,
|
|
7546
7842
|
CHANNEL_SPECS_HASH,
|
|
@@ -7579,6 +7875,8 @@ export {
|
|
|
7579
7875
|
DIGEST_VERSION,
|
|
7580
7876
|
DOC_SCHEMA_VERSION,
|
|
7581
7877
|
DRAG_FIT_LEVEL,
|
|
7878
|
+
END_CARD_FROM,
|
|
7879
|
+
END_CARD_RECEDE,
|
|
7582
7880
|
END_CARD_SECONDS,
|
|
7583
7881
|
ENTRANCE_SECONDS,
|
|
7584
7882
|
EXPORT_RESOLUTION_OPTIONS,
|
|
@@ -7589,8 +7887,11 @@ export {
|
|
|
7589
7887
|
FRAME_BORDER_DEFAULT,
|
|
7590
7888
|
FRAME_BORDER_WIDTH_DEFAULT,
|
|
7591
7889
|
HOUSE_GRADIENT,
|
|
7890
|
+
IDLE_KINDS,
|
|
7592
7891
|
LAYOUT_FRAME_FIELDS,
|
|
7593
7892
|
LOOK_KINDS,
|
|
7893
|
+
MEDIA_ENTER_KINDS,
|
|
7894
|
+
MEDIA_EXIT_KINDS,
|
|
7594
7895
|
MINIMAL_BAR_THEMES,
|
|
7595
7896
|
MOTION_DELTA,
|
|
7596
7897
|
MOTION_EASE,
|
|
@@ -7621,6 +7922,8 @@ export {
|
|
|
7621
7922
|
TEXT3D_DEPTH_DEFAULT,
|
|
7622
7923
|
TEXT3D_DEPTH_MAX,
|
|
7623
7924
|
TEXT3D_DEPTH_MIN,
|
|
7925
|
+
TEXT_ENTER_KINDS,
|
|
7926
|
+
TEXT_EXIT_KINDS,
|
|
7624
7927
|
TEXT_PRESETS,
|
|
7625
7928
|
TILT_AUTO_DEAD_ZONE,
|
|
7626
7929
|
TILT_AUTO_MIN,
|
|
@@ -7651,7 +7954,9 @@ export {
|
|
|
7651
7954
|
ZOOM_STYLE_OPTIONS,
|
|
7652
7955
|
anchorKindOf,
|
|
7653
7956
|
anchorSourceDuration,
|
|
7957
|
+
animStep,
|
|
7654
7958
|
applyLook,
|
|
7959
|
+
applyTemplate,
|
|
7655
7960
|
aspectRatioValue,
|
|
7656
7961
|
audioLane,
|
|
7657
7962
|
backdropMedia,
|
|
@@ -7663,6 +7968,8 @@ export {
|
|
|
7663
7968
|
camRectFromPose,
|
|
7664
7969
|
camRestPose,
|
|
7665
7970
|
camTrackFromDoc,
|
|
7971
|
+
cardEnter,
|
|
7972
|
+
cardExit,
|
|
7666
7973
|
cardInset,
|
|
7667
7974
|
cardPointToScreen,
|
|
7668
7975
|
cardPoseTrack,
|
|
@@ -7674,6 +7981,7 @@ export {
|
|
|
7674
7981
|
clampZoomLevel,
|
|
7675
7982
|
clipEnvelope,
|
|
7676
7983
|
clipLength,
|
|
7984
|
+
clipsFrom,
|
|
7677
7985
|
computeCardLayout,
|
|
7678
7986
|
computeMicRms,
|
|
7679
7987
|
computePeaks,
|
|
@@ -7689,11 +7997,18 @@ export {
|
|
|
7689
7997
|
docRestTime,
|
|
7690
7998
|
docToCropSpace,
|
|
7691
7999
|
docToFullSpace,
|
|
8000
|
+
dropTemplate,
|
|
7692
8001
|
duckCurve,
|
|
7693
8002
|
effectiveSegments,
|
|
8003
|
+
endCardClips,
|
|
8004
|
+
enterKey,
|
|
8005
|
+
enterOf,
|
|
7694
8006
|
entranceSeconds,
|
|
7695
8007
|
envelopeAt,
|
|
7696
8008
|
envelopeValueAt,
|
|
8009
|
+
exitKey,
|
|
8010
|
+
exitOf,
|
|
8011
|
+
exitSeconds,
|
|
7697
8012
|
expandEndCard,
|
|
7698
8013
|
expectedFrameSize,
|
|
7699
8014
|
exportSizeFor,
|
|
@@ -7704,6 +8019,7 @@ export {
|
|
|
7704
8019
|
hexToRgbTriplet,
|
|
7705
8020
|
houseLook,
|
|
7706
8021
|
idleGaps,
|
|
8022
|
+
idleKey,
|
|
7707
8023
|
isLookKind,
|
|
7708
8024
|
isMusicBed,
|
|
7709
8025
|
isPlayback,
|
|
@@ -7711,6 +8027,8 @@ export {
|
|
|
7711
8027
|
isRecordingDoc,
|
|
7712
8028
|
isRejected,
|
|
7713
8029
|
isStageClip,
|
|
8030
|
+
isUnitStep,
|
|
8031
|
+
lastLayerEnd,
|
|
7714
8032
|
layoutOf,
|
|
7715
8033
|
levelForFocusFraction,
|
|
7716
8034
|
lookFromBrand,
|
|
@@ -7720,6 +8038,7 @@ export {
|
|
|
7720
8038
|
lowerToComposition,
|
|
7721
8039
|
micLane,
|
|
7722
8040
|
migrateHostedDoc,
|
|
8041
|
+
migrateMotion,
|
|
7723
8042
|
momentsFromDoc,
|
|
7724
8043
|
motionTrack,
|
|
7725
8044
|
musicBedClip,
|
|
@@ -7728,11 +8047,13 @@ export {
|
|
|
7728
8047
|
objectMotionPoseAt,
|
|
7729
8048
|
objectsLane,
|
|
7730
8049
|
outputDurationOf,
|
|
8050
|
+
outputEnd,
|
|
7731
8051
|
outputRangeToSource,
|
|
7732
8052
|
overlapFraction,
|
|
7733
8053
|
overlayFaceFor,
|
|
7734
8054
|
overlayFontFaces,
|
|
7735
8055
|
overlayFontString,
|
|
8056
|
+
overlayFxSpec,
|
|
7736
8057
|
overlayHit,
|
|
7737
8058
|
overlayLines,
|
|
7738
8059
|
overlayMotionBase,
|