@cueframe/kernel 0.1.0 → 0.1.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/LICENSE +661 -0
- package/dist/_members/composition/ops/compositionOps.d.ts +1 -0
- package/dist/_members/composition/projection/behind-readiness.d.ts +127 -0
- package/dist/_members/composition/projection/index.d.ts +2 -0
- package/dist/_members/composition/projection/reframe-readiness.d.ts +156 -0
- package/dist/_members/composition/validators/composition.d.ts +42 -25
- package/dist/_members/composition/validators/render.d.ts +32 -0
- package/dist/_members/core/render/compositionRender.d.ts +17 -1
- package/dist/_members/core/render/types.d.ts +31 -0
- package/dist/authoring/build-tools.js +6 -6
- package/dist/authoring/context.js +4 -4
- package/dist/authoring/tools.js +5 -5
- package/dist/authoring.js +11 -9
- package/dist/{chunk-ZB3C3HM7.js → chunk-7FO3ZJ43.js} +3 -0
- package/dist/{chunk-ODL7GQJG.js → chunk-AP6ZIVAV.js} +2 -2
- package/dist/{chunk-IBYQG46O.js → chunk-AQBREB5O.js} +1 -1
- package/dist/{chunk-YIOY2XEO.js → chunk-DK2ODBNT.js} +15 -5
- package/dist/{chunk-JRQVPFLF.js → chunk-HY3RIEZW.js} +1 -1
- package/dist/{chunk-GEA7E2FL.js → chunk-JJ6XD7NG.js} +151 -1
- package/dist/{chunk-COYMZ76S.js → chunk-MBCXCJOE.js} +1 -1
- package/dist/{chunk-37NJ27UU.js → chunk-OCFDUCF4.js} +3 -0
- package/dist/{chunk-VOO5FQSS.js → chunk-PDYO3DOJ.js} +5 -5
- package/dist/{chunk-MXFAADCQ.js → chunk-PODIYN2K.js} +9 -2
- package/dist/{chunk-NFEGPWGS.js → chunk-TOJEXFXL.js} +1 -1
- package/dist/{chunk-LM4WDUQJ.js → chunk-UHGSZZDI.js} +1 -1
- package/dist/{chunk-XWKZB5U5.js → chunk-ZWMV6DD2.js} +24 -1
- package/dist/compose/renderer.js +3 -3
- package/dist/compose.js +6 -6
- package/dist/composition/graphics-plan.js +1 -1
- package/dist/composition/ops.js +3 -3
- package/dist/composition/primitive-catalog.js +1 -1
- package/dist/composition/projection.js +19 -3
- package/dist/composition/validators.js +6 -4
- package/dist/composition-ops.js +8 -6
- package/dist/composition.js +24 -6
- package/dist/{context-OKX3HHFS.js → context-YWUZDG5X.js} +4 -4
- package/dist/core/render.js +3 -3
- package/dist/core/select.js +2 -2
- package/dist/core.js +3 -3
- package/dist/errors.js +1 -1
- package/dist/mcp/adapter.js +1 -0
- package/dist/media-model/testing.js +1071 -718
- package/dist/nle-export/server.js +328 -130
- package/dist/nle-export.js +7 -6
- package/package.json +13 -14
- package/dist/_members/account-model/index.js +0 -4
- package/dist/_members/account-model/testing/conversationStoreContract.js +0 -168
- package/dist/_members/account-model/testing/index.js +0 -7
- package/dist/_members/account-model/testing/restorePointStoreContract.js +0 -69
- package/dist/_members/account-model/types/index.js +0 -1
- package/dist/_members/account-model/validators/contextFile.js +0 -18
- package/dist/_members/account-model/validators/conversation.js +0 -95
- package/dist/_members/account-model/validators/dashboardInsight.js +0 -16
- package/dist/_members/account-model/validators/index.js +0 -7
- package/dist/_members/account-model/validators/sessionToken.js +0 -49
- package/dist/_members/account-model/validators/uploadToken.js +0 -16
- package/dist/_members/account-model/validators/userSettings.js +0 -12
- package/dist/_members/account-model/validators/workingComposition.js +0 -20
- package/dist/_members/brand-derivation/constants.js +0 -20
- package/dist/_members/brand-derivation/contrastSafe.js +0 -114
- package/dist/_members/brand-derivation/index.js +0 -1
- package/dist/_members/cloud-import/chunk-XKO6ZSWI.js +0 -162
- package/dist/_members/cloud-import/chunk-XKO6ZSWI.js.map +0 -1
- package/dist/_members/cloud-import/index.js +0 -241
- package/dist/_members/cloud-import/index.js.map +0 -1
- package/dist/_members/cloud-import/multipartUpload.js +0 -7
- package/dist/_members/cloud-import/multipartUpload.js.map +0 -1
- package/dist/_members/composition/audio/audioMix.js +0 -61
- package/dist/_members/composition/audio/index.js +0 -5
- package/dist/_members/composition/audio/mixStaging.js +0 -195
- package/dist/_members/composition/audio/musicPack.generated.js +0 -136
- package/dist/_members/composition/audio/musicPack.js +0 -36
- package/dist/_members/composition/audio/pack.generated.js +0 -603
- package/dist/_members/composition/audio/pack.js +0 -48
- package/dist/_members/composition/audio/palette.js +0 -134
- package/dist/_members/composition/autozoom/index.js +0 -83
- package/dist/_members/composition/brand-kit.js +0 -45
- package/dist/_members/composition/brief/contract.js +0 -209
- package/dist/_members/composition/color-grade.js +0 -80
- package/dist/_members/composition/depth.js +0 -8
- package/dist/_members/composition/fixtures/index.js +0 -143
- package/dist/_members/composition/fixtures/vaayaErrored.d.ts +0 -25
- package/dist/_members/composition/fixtures/vaayaErrored.js +0 -203
- package/dist/_members/composition/fonts.js +0 -162
- package/dist/_members/composition/graphics-plan/compile.js +0 -221
- package/dist/_members/composition/graphics-plan/index.js +0 -10
- package/dist/_members/composition/graphics-plan/instantiateMotif.js +0 -44
- package/dist/_members/composition/graphics-plan/motion.js +0 -66
- package/dist/_members/composition/graphics-plan/schemas.js +0 -261
- package/dist/_members/composition/graphics-plan/solve.js +0 -145
- package/dist/_members/composition/index.js +0 -5
- package/dist/_members/composition/invariants/clipPlacement.js +0 -69
- package/dist/_members/composition/invariants/composition.js +0 -28
- package/dist/_members/composition/invariants/errors.js +0 -10
- package/dist/_members/composition/invariants/etag.js +0 -38
- package/dist/_members/composition/invariants/ids.js +0 -33
- package/dist/_members/composition/invariants/index.js +0 -9
- package/dist/_members/composition/invariants/keyframes.js +0 -45
- package/dist/_members/composition/invariants/markers.js +0 -29
- package/dist/_members/composition/invariants/time.js +0 -20
- package/dist/_members/composition/invariants/tracks.js +0 -304
- package/dist/_members/composition/ops/compositionOps.js +0 -1056
- package/dist/_members/composition/ops/headlessStore.js +0 -94
- package/dist/_members/composition/ops/index.js +0 -4
- package/dist/_members/composition/ops/selectors.js +0 -118
- package/dist/_members/composition/ops/timeline-word.js +0 -1
- package/dist/_members/composition/ops/transcript.js +0 -77
- package/dist/_members/composition/ops/types.js +0 -16
- package/dist/_members/composition/primitive-catalog/catalogQuery.js +0 -150
- package/dist/_members/composition/primitive-catalog/disabled.js +0 -32
- package/dist/_members/composition/primitive-catalog/generated/meta.js +0 -15161
- package/dist/_members/composition/primitive-catalog/index.js +0 -46
- package/dist/_members/composition/primitive-catalog/paramValidation.js +0 -231
- package/dist/_members/composition/primitive-catalog/projection.js +0 -164
- package/dist/_members/composition/primitive-catalog/types.js +0 -14
- package/dist/_members/composition/projection/behind-placement.js +0 -62
- package/dist/_members/composition/projection/brandKit.js +0 -482
- package/dist/_members/composition/projection/cardTokens.js +0 -209
- package/dist/_members/composition/projection/composition-floor.js +0 -582
- package/dist/_members/composition/projection/cropProjection.js +0 -257
- package/dist/_members/composition/projection/index.js +0 -7
- package/dist/_members/composition/projection/occlusion-budget.js +0 -104
- package/dist/_members/composition/projection/safe-zones.js +0 -99
- package/dist/_members/composition/reframe/aspectLoss.js +0 -115
- package/dist/_members/composition/reframe/coverage.js +0 -62
- package/dist/_members/composition/reframe/derive.js +0 -73
- package/dist/_members/composition/reframe/index.js +0 -109
- package/dist/_members/composition/reframe/kenBurns.js +0 -64
- package/dist/_members/composition/reframe/shotScale.js +0 -176
- package/dist/_members/composition/reframe/trajectory.js +0 -124
- package/dist/_members/composition/timeline/compound.js +0 -134
- package/dist/_members/composition/timeline/index.js +0 -9
- package/dist/_members/composition/timeline/intent.js +0 -228
- package/dist/_members/composition/timeline/keyframes.js +0 -121
- package/dist/_members/composition/timeline/link.js +0 -59
- package/dist/_members/composition/timeline/occupancy.js +0 -36
- package/dist/_members/composition/timeline/placement.js +0 -74
- package/dist/_members/composition/timeline/plan.js +0 -31
- package/dist/_members/composition/timeline/resolve.js +0 -170
- package/dist/_members/composition/timeline/trims.js +0 -278
- package/dist/_members/composition/types/index.js +0 -1
- package/dist/_members/composition/validators/brandKit.js +0 -295
- package/dist/_members/composition/validators/composePlan.js +0 -113
- package/dist/_members/composition/validators/composition.js +0 -703
- package/dist/_members/composition/validators/font.js +0 -34
- package/dist/_members/composition/validators/graphicKinds.js +0 -30
- package/dist/_members/composition/validators/index.js +0 -9
- package/dist/_members/composition/validators/project.js +0 -29
- package/dist/_members/composition/validators/registry.js +0 -41
- package/dist/_members/composition/validators/render.js +0 -139
- package/dist/_members/composition/validators/session.js +0 -37
- package/dist/_members/composition/validators/webhook.js +0 -72
- package/dist/_members/composition-ops/alphaLayers.js +0 -141
- package/dist/_members/composition-ops/index.js +0 -637
- package/dist/_members/composition-ops/materializeGrid.js +0 -99
- package/dist/_members/composition-ops/opRecorder.js +0 -196
- package/dist/_members/composition-ops/recordingStore.js +0 -14
- package/dist/_members/composition-ops/replaceRegion.js +0 -102
- package/dist/_members/composition-ops/testFixtures.js +0 -19
- package/dist/_members/core/index.js +0 -5
- package/dist/_members/core/render/bookends.js +0 -53
- package/dist/_members/core/render/captions.js +0 -127
- package/dist/_members/core/render/compositionRender.js +0 -1249
- package/dist/_members/core/render/deriveTrajectory.js +0 -889
- package/dist/_members/core/render/emphasis.js +0 -16
- package/dist/_members/core/render/eval/cropBox.js +0 -139
- package/dist/_members/core/render/eval/inclusion.js +0 -96
- package/dist/_members/core/render/eval/index.js +0 -146
- package/dist/_members/core/render/eval/metrics.js +0 -94
- package/dist/_members/core/render/exportSettings.js +0 -65
- package/dist/_members/core/render/index.js +0 -20
- package/dist/_members/core/render/mapFaceToPerson.js +0 -73
- package/dist/_members/core/render/types.js +0 -8
- package/dist/_members/core/render/vcam/cameraPath.js +0 -248
- package/dist/_members/core/render/vcam/constants.js +0 -115
- package/dist/_members/core/render/vcam/errorCodes.js +0 -39
- package/dist/_members/core/render/vcam/framing.js +0 -136
- package/dist/_members/core/render/vcam/requiredRegion.js +0 -137
- package/dist/_members/core/render/vcam/shots.js +0 -53
- package/dist/_members/core/render/vcam/subjectSet.js +0 -388
- package/dist/_members/core/select/errorCodes.js +0 -38
- package/dist/_members/core/select/index.js +0 -26
- package/dist/_members/core/select/model.js +0 -18
- package/dist/_members/core/select/select.js +0 -244
- package/dist/_members/core/select/stabilize.js +0 -242
- package/dist/_members/core/types.js +0 -7
- package/dist/_members/errors/index.js +0 -1
- package/dist/_members/errors/registry.js +0 -560
- package/dist/_members/foundation/codes/index.js +0 -31
- package/dist/_members/foundation/index.js +0 -2
- package/dist/_members/foundation/primitives/index.js +0 -5
- package/dist/_members/mcp/adapter.js +0 -771
- package/dist/_members/mcp/burnedNames.js +0 -73
- package/dist/_members/mcp/core.js +0 -390
- package/dist/_members/mcp/curation.js +0 -792
- package/dist/_members/mcp/executor.js +0 -142
- package/dist/_members/mcp/format.js +0 -9
- package/dist/_members/mcp/generated/catalogPreviews.js +0 -95
- package/dist/_members/mcp/generated/harness.js +0 -81
- package/dist/_members/mcp/generated/operations.js +0 -131
- package/dist/_members/mcp/index.js +0 -50
- package/dist/_members/mcp/internalLoopTools.js +0 -109
- package/dist/_members/mcp/prompts.js +0 -45
- package/dist/_members/mcp/resources.js +0 -166
- package/dist/_members/mcp/server.js +0 -340
- package/dist/_members/mcp/wait.js +0 -378
- package/dist/_members/mcp/x402Meta.js +0 -66
- package/dist/_members/media-model/api.js +0 -175
- package/dist/_members/media-model/index.js +0 -1
- package/dist/_members/media-model/media-kind.js +0 -116
- package/dist/_members/media-model/testing/index.js +0 -1
- package/dist/_members/media-model/testing/mediaStoreContract.js +0 -82
- package/dist/_members/media-model/transcriptSearch.js +0 -70
- package/dist/_members/media-model/transcriptSearchCases.json +0 -79
- package/dist/_members/nle-export/compact-timeline.js +0 -73
- package/dist/_members/nle-export/compact-timeline.js.map +0 -1
- package/dist/_members/nle-export/composition-to-input.js +0 -147
- package/dist/_members/nle-export/composition-to-input.js.map +0 -1
- package/dist/_members/nle-export/fcpxml.js +0 -159
- package/dist/_members/nle-export/fcpxml.js.map +0 -1
- package/dist/_members/nle-export/index.js +0 -12
- package/dist/_members/nle-export/index.js.map +0 -1
- package/dist/_members/nle-export/premiere.js +0 -161
- package/dist/_members/nle-export/premiere.js.map +0 -1
- package/dist/_members/nle-export/server/index.js +0 -2
- package/dist/_members/nle-export/server/index.js.map +0 -1
- package/dist/_members/nle-export/server/pack-zip.js +0 -38
- package/dist/_members/nle-export/server/pack-zip.js.map +0 -1
- package/dist/_members/nle-export/srt.js +0 -50
- package/dist/_members/nle-export/srt.js.map +0 -1
- package/dist/_members/nle-export/types.js +0 -9
- package/dist/_members/nle-export/types.js.map +0 -1
- package/dist/_members/nle-export/xml/index.js +0 -11
- package/dist/_members/nle-export/xml/index.js.map +0 -1
- package/dist/_members/nle-export/xml-utils.js +0 -48
- package/dist/_members/nle-export/xml-utils.js.map +0 -1
- package/dist/_members/perception/activeSpeaker.js +0 -103
- package/dist/_members/perception/audioQuality.js +0 -76
- package/dist/_members/perception/energyBeat.js +0 -99
- package/dist/_members/perception/identityMatch.js +0 -91
- package/dist/_members/perception/index.js +0 -48
- package/dist/_members/perception/visualQuality.js +0 -95
- package/dist/_members/plane/conformance.js +0 -90
- package/dist/_members/plane/contract.js +0 -49
- package/dist/_members/plane/index.js +0 -16
- package/dist/_members/primitives/backgrounds/index.js +0 -32
- package/dist/_members/primitives/backgrounds/index.js.map +0 -1
- package/dist/_members/primitives/captions/index.js +0 -398
- package/dist/_members/primitives/captions/index.js.map +0 -1
- package/dist/_members/primitives/chunk-2LVE4UIT.js +0 -139
- package/dist/_members/primitives/chunk-2LVE4UIT.js.map +0 -1
- package/dist/_members/primitives/chunk-3IQUH6KK.js +0 -20
- package/dist/_members/primitives/chunk-3IQUH6KK.js.map +0 -1
- package/dist/_members/primitives/chunk-3OMURV6Q.js +0 -112
- package/dist/_members/primitives/chunk-3OMURV6Q.js.map +0 -1
- package/dist/_members/primitives/chunk-4IS6TMEG.js +0 -21
- package/dist/_members/primitives/chunk-4IS6TMEG.js.map +0 -1
- package/dist/_members/primitives/chunk-5MWGAEGQ.js +0 -1644
- package/dist/_members/primitives/chunk-5MWGAEGQ.js.map +0 -1
- package/dist/_members/primitives/chunk-7RRPFPQK.js +0 -15
- package/dist/_members/primitives/chunk-7RRPFPQK.js.map +0 -1
- package/dist/_members/primitives/chunk-DH5TRZK2.js +0 -125
- package/dist/_members/primitives/chunk-DH5TRZK2.js.map +0 -1
- package/dist/_members/primitives/chunk-E3KNUSFG.js +0 -2337
- package/dist/_members/primitives/chunk-E3KNUSFG.js.map +0 -1
- package/dist/_members/primitives/chunk-G2B3G4HK.js +0 -47
- package/dist/_members/primitives/chunk-G2B3G4HK.js.map +0 -1
- package/dist/_members/primitives/chunk-HFPFGZXT.js +0 -1494
- package/dist/_members/primitives/chunk-HFPFGZXT.js.map +0 -1
- package/dist/_members/primitives/chunk-HIWVFZVH.js +0 -19
- package/dist/_members/primitives/chunk-HIWVFZVH.js.map +0 -1
- package/dist/_members/primitives/chunk-IDAL6G3Y.js +0 -134
- package/dist/_members/primitives/chunk-IDAL6G3Y.js.map +0 -1
- package/dist/_members/primitives/chunk-KNC6JP5F.js +0 -34
- package/dist/_members/primitives/chunk-KNC6JP5F.js.map +0 -1
- package/dist/_members/primitives/chunk-KYRDVZST.js +0 -459
- package/dist/_members/primitives/chunk-KYRDVZST.js.map +0 -1
- package/dist/_members/primitives/chunk-LWLHS2NS.js +0 -3410
- package/dist/_members/primitives/chunk-LWLHS2NS.js.map +0 -1
- package/dist/_members/primitives/chunk-QAQ3P7DR.js +0 -8855
- package/dist/_members/primitives/chunk-QAQ3P7DR.js.map +0 -1
- package/dist/_members/primitives/chunk-ROV2ODWC.js +0 -81
- package/dist/_members/primitives/chunk-ROV2ODWC.js.map +0 -1
- package/dist/_members/primitives/chunk-TCRC2FH3.js +0 -183
- package/dist/_members/primitives/chunk-TCRC2FH3.js.map +0 -1
- package/dist/_members/primitives/chunk-US4YEDAA.js +0 -96
- package/dist/_members/primitives/chunk-US4YEDAA.js.map +0 -1
- package/dist/_members/primitives/chunk-UVKRO5ER.js +0 -13
- package/dist/_members/primitives/chunk-UVKRO5ER.js.map +0 -1
- package/dist/_members/primitives/chunk-W4EIIF2I.js +0 -10
- package/dist/_members/primitives/chunk-W4EIIF2I.js.map +0 -1
- package/dist/_members/primitives/chunk-WPGKIPCO.js +0 -3563
- package/dist/_members/primitives/chunk-WPGKIPCO.js.map +0 -1
- package/dist/_members/primitives/chunk-WZFLEGMD.js +0 -1435
- package/dist/_members/primitives/chunk-WZFLEGMD.js.map +0 -1
- package/dist/_members/primitives/chunk-XHU3WBEI.js +0 -33
- package/dist/_members/primitives/chunk-XHU3WBEI.js.map +0 -1
- package/dist/_members/primitives/chunk-YN7WTZZ7.js +0 -46
- package/dist/_members/primitives/chunk-YN7WTZZ7.js.map +0 -1
- package/dist/_members/primitives/effects/index.js +0 -30
- package/dist/_members/primitives/effects/index.js.map +0 -1
- package/dist/_members/primitives/hero-text/index.js +0 -14
- package/dist/_members/primitives/hero-text/index.js.map +0 -1
- package/dist/_members/primitives/index.js +0 -64
- package/dist/_members/primitives/index.js.map +0 -1
- package/dist/_members/primitives/layouts/index.js +0 -24
- package/dist/_members/primitives/layouts/index.js.map +0 -1
- package/dist/_members/primitives/lib/easings.js +0 -26
- package/dist/_members/primitives/lib/easings.js.map +0 -1
- package/dist/_members/primitives/lib/index.js +0 -74
- package/dist/_members/primitives/lib/index.js.map +0 -1
- package/dist/_members/primitives/lib/palette.js +0 -72
- package/dist/_members/primitives/lib/palette.js.map +0 -1
- package/dist/_members/primitives/lib/preview.js +0 -8
- package/dist/_members/primitives/lib/preview.js.map +0 -1
- package/dist/_members/primitives/lib/schema.js +0 -12
- package/dist/_members/primitives/lib/schema.js.map +0 -1
- package/dist/_members/primitives/lib/seeded-random.js +0 -14
- package/dist/_members/primitives/lib/seeded-random.js.map +0 -1
- package/dist/_members/primitives/lib/text/contrast.js +0 -12
- package/dist/_members/primitives/lib/text/contrast.js.map +0 -1
- package/dist/_members/primitives/lib/text/fill.js +0 -8
- package/dist/_members/primitives/lib/text/fill.js.map +0 -1
- package/dist/_members/primitives/lib/text/fitText.js +0 -10
- package/dist/_members/primitives/lib/text/fitText.js.map +0 -1
- package/dist/_members/primitives/lib/text/marker.js +0 -8
- package/dist/_members/primitives/lib/text/marker.js.map +0 -1
- package/dist/_members/primitives/lib/text/motion.js +0 -16
- package/dist/_members/primitives/lib/text/motion.js.map +0 -1
- package/dist/_members/primitives/lib/text/recolor.js +0 -8
- package/dist/_members/primitives/lib/text/recolor.js.map +0 -1
- package/dist/_members/primitives/lib/text/spec.js +0 -1
- package/dist/_members/primitives/lib/text/spec.js.map +0 -1
- package/dist/_members/primitives/lib/text/stage.js +0 -8
- package/dist/_members/primitives/lib/text/stage.js.map +0 -1
- package/dist/_members/primitives/lib/text/typeface.js +0 -8
- package/dist/_members/primitives/lib/text/typeface.js.map +0 -1
- package/dist/_members/primitives/lib/tokens.js +0 -24
- package/dist/_members/primitives/lib/tokens.js.map +0 -1
- package/dist/_members/primitives/lib/types.js +0 -1
- package/dist/_members/primitives/lib/types.js.map +0 -1
- package/dist/_members/primitives/params-required.json +0 -153
- package/dist/_members/primitives/scenes/index.js +0 -25
- package/dist/_members/primitives/scenes/index.js.map +0 -1
- package/dist/_members/primitives/subject-foreground/index.js +0 -30
- package/dist/_members/primitives/subject-foreground/index.js.map +0 -1
- package/dist/_members/primitives/text/index.js +0 -57
- package/dist/_members/primitives/text/index.js.map +0 -1
- package/dist/_members/primitives/transitions/index.js +0 -67
- package/dist/_members/primitives/transitions/index.js.map +0 -1
- package/dist/_members/primitives/ui-blocks/index.js +0 -76
- package/dist/_members/primitives/ui-blocks/index.js.map +0 -1
- package/dist/_members/primitives/version-map.json +0 -105
- package/dist/_members/primitives/workspace.js +0 -60
- package/dist/_members/primitives/workspace.js.map +0 -1
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Layout stage (P1): ContentBeat → LayoutPlan. Deterministic placement that is
|
|
3
|
-
* content-aware BY CONSTRUCTION — every front element is solved clear of the
|
|
4
|
-
* composition-floor face keep-outs (reusing `placeInLegalArea`), so text can
|
|
5
|
-
* never land on the speaker. This is the "solver snaps to legal" half of the
|
|
6
|
-
* hybrid layout stage; P4 lets an agent PROPOSE boxes that this validates/snaps.
|
|
7
|
-
*
|
|
8
|
-
* A per-role TEMPLATE decomposes each graphic into ordered element slots; the
|
|
9
|
-
* solver finds one legal vertical band for the whole stack and lays the slots
|
|
10
|
-
* out within it. styleRole (→ brand token) and typeScaleStep (→ type scale) are
|
|
11
|
-
* assigned per slot, so nothing off-brand or raw-px is emitted.
|
|
12
|
-
*/
|
|
13
|
-
import { placeInLegalArea } from "../projection/composition-floor.js";
|
|
14
|
-
import { GRAPHICS_PLAN_VERSION, } from "./schemas.js";
|
|
15
|
-
/** Per-graphic-role templates: the ordered element slots + the band anchor
|
|
16
|
-
* preference. Widths/heights are conservative fractions the compiler can
|
|
17
|
-
* refine once real text metrics exist (P2).
|
|
18
|
-
*
|
|
19
|
-
* PARTIAL on purpose. The ARGUMENT roles (enumeration / sequence / comparison) have no template
|
|
20
|
-
* and must not have one: a `sequence` might be a reasoning-trace, a tool-call-stack or a bespoke
|
|
21
|
-
* component, and choosing between those is a DESIGN decision made with eyes on the frame — not a
|
|
22
|
-
* slot table. This deterministic solver only lays out the text-shaped roles; the designer owns
|
|
23
|
-
* the rest. `solveLayout` fails loud below rather than inventing a headline for a chain of steps.
|
|
24
|
-
*/
|
|
25
|
-
const TEMPLATES = {
|
|
26
|
-
"title-card": {
|
|
27
|
-
anchor: "free",
|
|
28
|
-
slots: [
|
|
29
|
-
{ role: "headline", styleRole: "heading", copyKey: "headline", h: 0.1, w: 0.82, typeScaleStep: 6 },
|
|
30
|
-
{ role: "sublabel", styleRole: "body", copyKey: "sub", h: 0.05, w: 0.7, typeScaleStep: 3 },
|
|
31
|
-
],
|
|
32
|
-
},
|
|
33
|
-
stat: {
|
|
34
|
-
anchor: "free",
|
|
35
|
-
slots: [
|
|
36
|
-
{ role: "value", styleRole: "accent", copyKey: "value", h: 0.13, w: 0.6, typeScaleStep: 7 },
|
|
37
|
-
{ role: "label", styleRole: "body", copyKey: "label", h: 0.05, w: 0.72, typeScaleStep: 3 },
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
"lower-third": {
|
|
41
|
-
anchor: "lower-third",
|
|
42
|
-
slots: [
|
|
43
|
-
{ role: "headline", styleRole: "heading", copyKey: "headline", h: 0.07, w: 0.7, typeScaleStep: 5 },
|
|
44
|
-
{ role: "sublabel", styleRole: "body", copyKey: "sub", h: 0.045, w: 0.62, typeScaleStep: 2 },
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
"pull-quote": {
|
|
48
|
-
anchor: "free",
|
|
49
|
-
slots: [{ role: "headline", styleRole: "heading", copyKey: "headline", h: 0.14, w: 0.82, typeScaleStep: 5 }],
|
|
50
|
-
},
|
|
51
|
-
hero: {
|
|
52
|
-
anchor: "free",
|
|
53
|
-
slots: [{ role: "headline", styleRole: "heading", copyKey: "headline", h: 0.18, w: 0.9, typeScaleStep: 8, z: "behind-subject" }],
|
|
54
|
-
},
|
|
55
|
-
"logo-tag": {
|
|
56
|
-
anchor: "bottom",
|
|
57
|
-
slots: [{ role: "logo", styleRole: "accent", copyKey: null, h: 0.06, w: 0.22 }],
|
|
58
|
-
},
|
|
59
|
-
};
|
|
60
|
-
const GAP = 0.02;
|
|
61
|
-
const clamp01 = (n) => Math.min(1, Math.max(0, n));
|
|
62
|
-
function clampRect(r) {
|
|
63
|
-
const x = clamp01(r.x);
|
|
64
|
-
const y = clamp01(r.y);
|
|
65
|
-
return { x, y, w: Math.min(r.w, 1 - x), h: Math.min(r.h, 1 - y) };
|
|
66
|
-
}
|
|
67
|
-
/** Top + bottom strips outside the title-safe area, as band blockers. */
|
|
68
|
-
function safeBands(safe) {
|
|
69
|
-
const m = clamp01((1 - safe.titleSafe) / 2);
|
|
70
|
-
if (m <= 0)
|
|
71
|
-
return [];
|
|
72
|
-
return [
|
|
73
|
-
{ x: 0, y: 0, w: 1, h: m },
|
|
74
|
-
{ x: 0, y: 1 - m, w: 1, h: m },
|
|
75
|
-
];
|
|
76
|
-
}
|
|
77
|
-
/** Center a block of `totalH` vertically, clamped inside the safe margins. */
|
|
78
|
-
function centeredBand(totalH, safe) {
|
|
79
|
-
const m = clamp01((1 - safe.titleSafe) / 2);
|
|
80
|
-
const y = Math.min(1 - m - totalH, Math.max(m, 0.5 - totalH / 2));
|
|
81
|
-
return { x: 0, y: Math.max(0, y), w: 1, h: totalH };
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Solve one beat's layout. Front stacks land in a legal band clear of the face;
|
|
85
|
-
* behind-subject heroes intentionally ignore the keep-out (the subject occludes
|
|
86
|
-
* them). An opener with no detected face centers vertically.
|
|
87
|
-
*/
|
|
88
|
-
export function solveLayout(beat, ctx) {
|
|
89
|
-
const tpl = TEMPLATES[beat.role];
|
|
90
|
-
if (!tpl) {
|
|
91
|
-
throw new Error(`graphics-plan/solve: role "${beat.role}" (beat "${beat.id}") is a DESIGNER-AUTHORED argument ` +
|
|
92
|
-
`role — the deterministic layout solver has no template for it, and must not invent one. ` +
|
|
93
|
-
`The designer picks the component and its layout with the frame in front of it.`);
|
|
94
|
-
}
|
|
95
|
-
const isBehind = tpl.slots.every((s) => s.z === "behind-subject");
|
|
96
|
-
const active = tpl.slots.filter((s) => s.copyKey === null || beat.copy[s.copyKey] != null);
|
|
97
|
-
if (active.length === 0) {
|
|
98
|
-
return { version: GRAPHICS_PLAN_VERSION, beatId: beat.id, frame: ctx.frame, keepOut: ctx.keepOut, safe: ctx.safe, elements: [] };
|
|
99
|
-
}
|
|
100
|
-
const totalH = active.reduce((s, x) => s + x.h, 0) + GAP * (active.length - 1);
|
|
101
|
-
const maxW = Math.max(...active.map((s) => s.w));
|
|
102
|
-
const hasFace = ctx.keepOut.length > 0;
|
|
103
|
-
// Band selection preserves the invariant: a front stack NEVER lands on the
|
|
104
|
-
// face. behind-subject heroes center by design; a face-free opener centers;
|
|
105
|
-
// otherwise the legal-area solver places clear of the face — and if NO legal
|
|
106
|
-
// band fits (face fills the frame), we DROP the graphic (empty elements)
|
|
107
|
-
// rather than fall back onto the speaker. Dropping is the safe failure: a
|
|
108
|
-
// graphic you can't place legally is worse than no graphic.
|
|
109
|
-
const band = isBehind
|
|
110
|
-
? centeredBand(totalH, ctx.safe)
|
|
111
|
-
: hasFace
|
|
112
|
-
? placeInLegalArea({ id: beat.id, anchor: tpl.anchor, minH: totalH, minW: maxW }, { faceKeepOut: ctx.keepOut, safeZones: safeBands(ctx.safe) })
|
|
113
|
-
: centeredBand(totalH, ctx.safe);
|
|
114
|
-
if (band === null) {
|
|
115
|
-
// Dropped, not occluding the face — and OBSERVABLE (distinct from no-copy).
|
|
116
|
-
return { version: GRAPHICS_PLAN_VERSION, beatId: beat.id, frame: ctx.frame, keepOut: ctx.keepOut, safe: ctx.safe, elements: [], dropped: { reason: "no legal band clear of the face keep-out" } };
|
|
117
|
-
}
|
|
118
|
-
const elements = [];
|
|
119
|
-
let cursor = band.y;
|
|
120
|
-
for (const s of active) {
|
|
121
|
-
// Place WITHIN the band's horizontal corridor (band.x..band.x+band.w) — NOT
|
|
122
|
-
// re-centered on 0.5. For an off-center (side-framed) face, placeInLegalArea
|
|
123
|
-
// shifts the corridor into the clear side; centering on 0.5 would put text
|
|
124
|
-
// back onto the speaker. Element width is capped to the corridor.
|
|
125
|
-
const w = Math.min(s.w, band.w, 0.92);
|
|
126
|
-
const x = band.x + (band.w - w) / 2;
|
|
127
|
-
const box = clampRect({ x, y: cursor, w, h: s.h });
|
|
128
|
-
const text = s.copyKey ? beat.copy[s.copyKey] : undefined;
|
|
129
|
-
elements.push({
|
|
130
|
-
elId: `${beat.id}-${s.role}`,
|
|
131
|
-
role: s.role,
|
|
132
|
-
box,
|
|
133
|
-
styleRole: s.styleRole,
|
|
134
|
-
z: s.z ?? "front",
|
|
135
|
-
...(text ? { text } : {}),
|
|
136
|
-
...(s.typeScaleStep != null ? { typeScaleStep: s.typeScaleStep } : {}),
|
|
137
|
-
});
|
|
138
|
-
cursor += s.h + GAP;
|
|
139
|
-
}
|
|
140
|
-
return { version: GRAPHICS_PLAN_VERSION, beatId: beat.id, frame: ctx.frame, keepOut: ctx.keepOut, safe: ctx.safe, elements };
|
|
141
|
-
}
|
|
142
|
-
/** True iff two rects overlap (used by tests + the P4 agent-proposal validator). */
|
|
143
|
-
export function rectsOverlap(a, b) {
|
|
144
|
-
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
|
|
145
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
/** What a track of this kind is allowed to carry, for the kinds we can judge.
|
|
2
|
-
* Anything absent here is not judged. */
|
|
3
|
-
const AUDIO_TRACK_KINDS = new Set(['audio']);
|
|
4
|
-
const VISUAL_TRACK_KINDS = new Set(['video', 'image']);
|
|
5
|
-
/**
|
|
6
|
-
* @param composition the FOLDED composition — checked on the result rather than
|
|
7
|
-
* on the ops, so it cannot be walked around by the shape of the batch (the
|
|
8
|
-
* same reasoning as the component gate beside it).
|
|
9
|
-
* @param mediaKindById `mediaId -> kind`. The desktop passes
|
|
10
|
-
* `getContext().media`; a server caller passes its media rows. A missing entry
|
|
11
|
-
* means "not judged".
|
|
12
|
-
*/
|
|
13
|
-
export function collectClipPlacementIssues(composition, mediaKindById) {
|
|
14
|
-
const issues = [];
|
|
15
|
-
const tracks = composition.tracks;
|
|
16
|
-
if (!Array.isArray(tracks))
|
|
17
|
-
return issues;
|
|
18
|
-
for (const track of tracks) {
|
|
19
|
-
const trackKind = typeof track.kind === 'string' ? track.kind : '';
|
|
20
|
-
const contents = Array.isArray(track.contents) ? track.contents : [];
|
|
21
|
-
for (const clip of contents) {
|
|
22
|
-
const clipId = typeof clip.id === 'string' ? clip.id : '(unnamed clip)';
|
|
23
|
-
// ── 1. A clip that occupies no time is not an edit ──────────────────
|
|
24
|
-
//
|
|
25
|
-
// The render lattice DROPS a clip too short to occupy a whole frame at
|
|
26
|
-
// its position (`timelineSpanFrames`), so a zero-duration clip is
|
|
27
|
-
// guaranteed to contribute nothing — it just makes the composition read
|
|
28
|
-
// as 0:00.00 while appearing to hold media.
|
|
29
|
-
const duration = clip.duration;
|
|
30
|
-
if (typeof duration !== 'number' || !(duration > 0)) {
|
|
31
|
-
issues.push({
|
|
32
|
-
clipId,
|
|
33
|
-
message: `clip \`${clipId}\` on track \`${trackKind || '?'}\` has duration ${String(duration)}. ` +
|
|
34
|
-
`A clip must occupy time: the render lattice drops anything shorter than one frame, ` +
|
|
35
|
-
`so this contributes nothing and leaves the composition reading 0:00.`,
|
|
36
|
-
});
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
// ── 2. Audio on a picture track (and the reverse) ───────────────────
|
|
40
|
-
const source = clip.source;
|
|
41
|
-
if (!source || source.kind !== 'media')
|
|
42
|
-
continue;
|
|
43
|
-
const mediaId = typeof source.mediaId === 'string' ? source.mediaId : '';
|
|
44
|
-
const mediaKind = mediaKindById[mediaId];
|
|
45
|
-
// Not probed / not in the pool → not judged. Absence is not evidence.
|
|
46
|
-
if (!mediaKind)
|
|
47
|
-
continue;
|
|
48
|
-
const mediaIsAudio = mediaKind === 'audio';
|
|
49
|
-
const mediaIsVisual = mediaKind === 'video' || mediaKind === 'image';
|
|
50
|
-
if (mediaIsAudio && VISUAL_TRACK_KINDS.has(trackKind)) {
|
|
51
|
-
issues.push({
|
|
52
|
-
clipId,
|
|
53
|
-
message: `clip \`${clipId}\` puts AUDIO media (\`${mediaId}\`) on a \`${trackKind}\` track. ` +
|
|
54
|
-
`Audio belongs on an \`audio\` track — the cloud refuses this as ` +
|
|
55
|
-
`\`media_family_track_mismatch\`, and the local renderer draws nothing for it.`,
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
else if (mediaIsVisual && AUDIO_TRACK_KINDS.has(trackKind)) {
|
|
59
|
-
issues.push({
|
|
60
|
-
clipId,
|
|
61
|
-
message: `clip \`${clipId}\` puts ${mediaKind.toUpperCase()} media (\`${mediaId}\`) on an ` +
|
|
62
|
-
`\`audio\` track. Picture belongs on a \`video\` or \`image\` track — the cloud ` +
|
|
63
|
-
`refuses this as \`media_family_track_mismatch\`.`,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return issues;
|
|
69
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { checkTracks } from "./tracks";
|
|
2
|
-
import { checkSceneMarkerPartition } from "./markers";
|
|
3
|
-
import { checkIdCollisions } from "./ids";
|
|
4
|
-
import { checkKeyframes } from "./keyframes";
|
|
5
|
-
/**
|
|
6
|
-
* Run every structural invariant against a Composition.
|
|
7
|
-
* Returns a flat list of violations; empty array = valid.
|
|
8
|
-
*/
|
|
9
|
-
export function checkComposition(composition) {
|
|
10
|
-
return [
|
|
11
|
-
...checkIdCollisions(composition),
|
|
12
|
-
...checkTracks(composition),
|
|
13
|
-
...checkSceneMarkerPartition(composition),
|
|
14
|
-
...checkKeyframes(composition),
|
|
15
|
-
];
|
|
16
|
-
}
|
|
17
|
-
/** Convenience: duration = max(startTime + duration) across every Track's contents. */
|
|
18
|
-
export function compositionDuration(composition) {
|
|
19
|
-
let max = 0;
|
|
20
|
-
for (const track of composition.tracks) {
|
|
21
|
-
for (const c of track.contents) {
|
|
22
|
-
const e = c.startTime + c.duration;
|
|
23
|
-
if (e > max)
|
|
24
|
-
max = e;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
return max;
|
|
28
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
// Pure-JS SHA-256 (no `node:crypto`) so this module bundles into Convex's V8
|
|
2
|
-
// isolate — importing it transitively (via the invariants barrel) previously
|
|
3
|
-
// broke `npx convex deploy` with "Could not resolve node:crypto". @noble/hashes
|
|
4
|
-
// is sync + dependency-free and its output is byte-identical to node's
|
|
5
|
-
// createHash("sha256").update(utf8).digest("hex"), so every existing etag /
|
|
6
|
-
// If-Match (OCC) value is unchanged. (Pairs with projection.ts's inlined computeEtag.)
|
|
7
|
-
import { sha256 } from "@noble/hashes/sha256";
|
|
8
|
-
import { bytesToHex } from "@noble/hashes/utils";
|
|
9
|
-
/**
|
|
10
|
-
* Canonicalize an object for deterministic hashing:
|
|
11
|
-
* - object keys sorted lexicographically at every depth
|
|
12
|
-
* - arrays preserve order
|
|
13
|
-
* - undefined fields dropped (JSON semantics)
|
|
14
|
-
* - null / number / string / boolean preserved as-is
|
|
15
|
-
*/
|
|
16
|
-
export function canonicalJSON(value) {
|
|
17
|
-
return JSON.stringify(canonicalize(value));
|
|
18
|
-
}
|
|
19
|
-
function canonicalize(value) {
|
|
20
|
-
if (value === null || typeof value !== "object")
|
|
21
|
-
return value;
|
|
22
|
-
if (Array.isArray(value))
|
|
23
|
-
return value.map(canonicalize);
|
|
24
|
-
const out = {};
|
|
25
|
-
const keys = Object.keys(value).sort();
|
|
26
|
-
for (const key of keys) {
|
|
27
|
-
const v = value[key];
|
|
28
|
-
if (v === undefined)
|
|
29
|
-
continue;
|
|
30
|
-
out[key] = canonicalize(v);
|
|
31
|
-
}
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
34
|
-
export function etag(composition) {
|
|
35
|
-
const canonical = canonicalJSON(composition);
|
|
36
|
-
const hash = bytesToHex(sha256(new TextEncoder().encode(canonical)));
|
|
37
|
-
return `"${hash}"`;
|
|
38
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Entity ids share a single namespace within the Composition.
|
|
3
|
-
* TimelineClip.id, Track.id, Gap.id, Marker.id must all be unique.
|
|
4
|
-
*
|
|
5
|
-
* composition_id_collision { existingKind, newKind, id }
|
|
6
|
-
*/
|
|
7
|
-
export function checkIdCollisions(composition) {
|
|
8
|
-
const seen = new Map();
|
|
9
|
-
const out = [];
|
|
10
|
-
const record = (id, kind) => {
|
|
11
|
-
const existing = seen.get(id);
|
|
12
|
-
if (existing) {
|
|
13
|
-
out.push({
|
|
14
|
-
code: "composition_id_collision",
|
|
15
|
-
message: `Id ${id} used by both ${existing} and ${kind}`,
|
|
16
|
-
details: { id, existingKind: existing, newKind: kind },
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
seen.set(id, kind);
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
for (const track of composition.tracks) {
|
|
24
|
-
record(track.id, "track");
|
|
25
|
-
for (const content of track.contents) {
|
|
26
|
-
record(content.id, "source" in content ? "clip" : "gap");
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
for (const marker of composition.markers ?? []) {
|
|
30
|
-
record(marker.id, "marker");
|
|
31
|
-
}
|
|
32
|
-
return out;
|
|
33
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/** Float slack — two keyframes closer than this are the same instant. */
|
|
2
|
-
const TIME_EPSILON = 1e-6;
|
|
3
|
-
export function checkClipKeyframes(clip) {
|
|
4
|
-
const animate = clip.animate;
|
|
5
|
-
if (!animate)
|
|
6
|
-
return [];
|
|
7
|
-
const violations = [];
|
|
8
|
-
for (const [param, channel] of Object.entries(animate)) {
|
|
9
|
-
if (!channel)
|
|
10
|
-
continue;
|
|
11
|
-
const sorted = [...channel].sort((a, b) => a.time - b.time);
|
|
12
|
-
for (const kf of sorted) {
|
|
13
|
-
if (kf.time > clip.duration + TIME_EPSILON) {
|
|
14
|
-
violations.push({
|
|
15
|
-
code: "varying_keyframe_time_out_of_range",
|
|
16
|
-
message: `clip "${clip.id}" animates "${param}" at ${kf.time}s, past its own ` +
|
|
17
|
-
`duration of ${clip.duration}s — that keyframe can never be reached`,
|
|
18
|
-
details: { clipId: clip.id, param, time: kf.time, duration: clip.duration },
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
for (let i = 1; i < sorted.length; i++) {
|
|
23
|
-
if (Math.abs(sorted[i].time - sorted[i - 1].time) < TIME_EPSILON) {
|
|
24
|
-
violations.push({
|
|
25
|
-
code: "varying_keyframe_duplicate_time",
|
|
26
|
-
message: `clip "${clip.id}" has two "${param}" keyframes at ${sorted[i].time}s — ` +
|
|
27
|
-
`the value at that instant is undefined`,
|
|
28
|
-
details: { clipId: clip.id, param, time: sorted[i].time },
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return violations;
|
|
34
|
-
}
|
|
35
|
-
export function checkKeyframes(composition) {
|
|
36
|
-
const violations = [];
|
|
37
|
-
for (const track of composition.tracks) {
|
|
38
|
-
for (const item of track.contents) {
|
|
39
|
-
if (!("source" in item))
|
|
40
|
-
continue;
|
|
41
|
-
violations.push(...checkClipKeyframes(item));
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return violations;
|
|
45
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const end = (m) => m.endTime ?? m.startTime;
|
|
2
|
-
/**
|
|
3
|
-
* Markers with `kind: 'scene'` cannot overlap (single-partition rule).
|
|
4
|
-
* Other kinds (chapter, note, agent, custom) are free to overlap.
|
|
5
|
-
*
|
|
6
|
-
* scene_marker_overlap { markerAId, markerBId, overlapRange }
|
|
7
|
-
*/
|
|
8
|
-
export function checkSceneMarkerPartition(composition) {
|
|
9
|
-
const scenes = (composition.markers ?? [])
|
|
10
|
-
.filter((m) => m.kind === "scene")
|
|
11
|
-
.sort((a, b) => a.startTime - b.startTime);
|
|
12
|
-
const out = [];
|
|
13
|
-
for (let i = 1; i < scenes.length; i++) {
|
|
14
|
-
const prev = scenes[i - 1];
|
|
15
|
-
const cur = scenes[i];
|
|
16
|
-
if (cur.startTime < end(prev)) {
|
|
17
|
-
out.push({
|
|
18
|
-
code: "scene_marker_overlap",
|
|
19
|
-
message: `Scene markers ${prev.id} and ${cur.id} overlap at [${cur.startTime}, ${Math.min(end(prev), end(cur))})`,
|
|
20
|
-
details: {
|
|
21
|
-
markerAId: prev.id,
|
|
22
|
-
markerBId: cur.id,
|
|
23
|
-
overlapRange: [cur.startTime, Math.min(end(prev), end(cur))],
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return out;
|
|
29
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OTIO / native-renderer time quantization rule.
|
|
3
|
-
* See data-model.md §OTIO time export rule and §Native renderer time quantization.
|
|
4
|
-
*/
|
|
5
|
-
export function otioFrames(seconds, fps) {
|
|
6
|
-
return Math.round(seconds * fps);
|
|
7
|
-
}
|
|
8
|
-
export function otioRationalTime(seconds, fps) {
|
|
9
|
-
return { value: Math.round(seconds * fps), rate: fps };
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Per-output-frame source-frame mapping (renderer contract).
|
|
13
|
-
* Matches the OTIO writer's quantization at the boundary.
|
|
14
|
-
*/
|
|
15
|
-
export function sourceFrame(params) {
|
|
16
|
-
const { outputFrame, formatFps, clipStartTime, trimStart, playbackRate, sourceFps } = params;
|
|
17
|
-
const outSeconds = outputFrame / formatFps;
|
|
18
|
-
const sourceSeconds = trimStart + (outSeconds - clipStartTime) * playbackRate;
|
|
19
|
-
return Math.round(sourceSeconds * sourceFps);
|
|
20
|
-
}
|