@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,116 +0,0 @@
|
|
|
1
|
-
export const IMAGE_CONTENT_TYPES = ["image/png", "image/jpeg", "image/webp"];
|
|
2
|
-
/** Closed allowlist — the complete set of accepted content-types (the acceptance
|
|
3
|
-
* gate). mediaKind() routes each: video/audio/still-image do real work;
|
|
4
|
-
* fonts/json/svg/gif route to the opaque path. Unknown bytes (not here)
|
|
5
|
-
* are rejected at the edge. */
|
|
6
|
-
export const ALLOWED_CONTENT_TYPES = [
|
|
7
|
-
"video/mp4", "video/quicktime", "video/x-matroska", "video/webm",
|
|
8
|
-
"audio/mpeg", "audio/wav", "audio/x-wav", "audio/mp4", "audio/aac",
|
|
9
|
-
"image/png", "image/jpeg", "image/webp",
|
|
10
|
-
"image/gif", "image/svg+xml", "application/json",
|
|
11
|
-
"font/ttf", "font/otf", "font/woff", "font/woff2",
|
|
12
|
-
];
|
|
13
|
-
export function mediaKind(contentType) {
|
|
14
|
-
const ct = (contentType || "").toLowerCase();
|
|
15
|
-
if (ct.startsWith("video/"))
|
|
16
|
-
return "video";
|
|
17
|
-
if (ct.startsWith("audio/"))
|
|
18
|
-
return "audio";
|
|
19
|
-
if (IMAGE_CONTENT_TYPES.includes(ct))
|
|
20
|
-
return "image";
|
|
21
|
-
return "opaque";
|
|
22
|
-
}
|
|
23
|
-
const EXT = {
|
|
24
|
-
"video/mp4": "mp4", "audio/mp4": "mp4", "video/quicktime": "mov",
|
|
25
|
-
"video/x-matroska": "mkv", "video/webm": "webm", "video/x-msvideo": "avi",
|
|
26
|
-
"audio/mpeg": "mp3", "audio/wav": "wav", "audio/x-wav": "wav", "audio/aac": "aac",
|
|
27
|
-
"audio/ogg": "ogg", "audio/flac": "flac",
|
|
28
|
-
"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp",
|
|
29
|
-
"font/ttf": "ttf", "font/otf": "otf", "font/woff": "woff", "font/woff2": "woff2",
|
|
30
|
-
"application/json": "json", "image/svg+xml": "svg", "image/gif": "gif",
|
|
31
|
-
};
|
|
32
|
-
export function extensionForContentType(contentType) {
|
|
33
|
-
return EXT[(contentType || "").toLowerCase()] ?? "bin";
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* MIME ALIASES THE PLATFORM EMITS FOR TYPES WE ALREADY ACCEPT.
|
|
37
|
-
*
|
|
38
|
-
* `ALLOWED_CONTENT_TYPES` is a CLOSED gate keyed on an exact string, and the
|
|
39
|
-
* same bytes get different strings depending on who describes them: WebKit says
|
|
40
|
-
* `audio/mp3` where the registry says `audio/mpeg`, Apple says `audio/x-m4a`
|
|
41
|
-
* where the registry says `audio/mp4`. Rejecting those is not the gate doing
|
|
42
|
-
* its job — it is the gate mistaking a spelling for a format, and the user gets
|
|
43
|
-
* "Unsupported file type" for a plain MP3.
|
|
44
|
-
*
|
|
45
|
-
* Only aliases of types ALREADY on the allowlist belong here. This must not
|
|
46
|
-
* become a way to smuggle in a format the pipeline cannot decode.
|
|
47
|
-
*/
|
|
48
|
-
const CONTENT_TYPE_ALIASES = {
|
|
49
|
-
"audio/mp3": "audio/mpeg",
|
|
50
|
-
"audio/x-mp3": "audio/mpeg",
|
|
51
|
-
"audio/x-mpeg": "audio/mpeg",
|
|
52
|
-
"audio/mpeg3": "audio/mpeg",
|
|
53
|
-
"audio/x-mpeg-3": "audio/mpeg",
|
|
54
|
-
"audio/x-m4a": "audio/mp4",
|
|
55
|
-
"audio/m4a": "audio/mp4",
|
|
56
|
-
"audio/wave": "audio/wav",
|
|
57
|
-
"audio/vnd.wave": "audio/wav",
|
|
58
|
-
"audio/x-aac": "audio/aac",
|
|
59
|
-
"image/jpg": "image/jpeg",
|
|
60
|
-
"video/x-quicktime": "video/quicktime",
|
|
61
|
-
"video/mov": "video/quicktime",
|
|
62
|
-
"video/x-m4v": "video/mp4",
|
|
63
|
-
"video/mkv": "video/x-matroska",
|
|
64
|
-
};
|
|
65
|
-
/** Extension → canonical content-type, derived from the EXT map so the two
|
|
66
|
-
* cannot drift. Built once. */
|
|
67
|
-
const TYPE_BY_EXTENSION = Object.entries(EXT).reduce((acc, [contentType, ext]) => {
|
|
68
|
-
// First writer wins, so `audio/mp4` does not steal `mp4` from `video/mp4`.
|
|
69
|
-
if (!(ext in acc))
|
|
70
|
-
acc[ext] = contentType;
|
|
71
|
-
return acc;
|
|
72
|
-
}, {});
|
|
73
|
-
// Spellings EXT cannot carry (it is contentType→ext, one ext per type): the
|
|
74
|
-
// long form of jpg, and m4a — whose canonical type audio/mp4 lost the "mp4"
|
|
75
|
-
// slot to video above.
|
|
76
|
-
TYPE_BY_EXTENSION["jpeg"] = "image/jpeg";
|
|
77
|
-
TYPE_BY_EXTENSION["m4a"] = "audio/mp4";
|
|
78
|
-
/** What a file IS, from nothing but its name — the ONE derivation the import
|
|
79
|
-
* door, the project-file parse gate, and migration 020's SQL all mirror. */
|
|
80
|
-
export function mediaKindForFilename(filename) {
|
|
81
|
-
return mediaKind(contentTypeForUpload(filename, null));
|
|
82
|
-
}
|
|
83
|
-
/** Every extension whose derived kind can occupy time. The import door's
|
|
84
|
-
* accept-list IS this list — derived, so the door and the authority cannot
|
|
85
|
-
* disagree (the disagreement was a thrown import for `.jpeg`/`.m4a`). */
|
|
86
|
-
export const POOL_EXTENSIONS = Object.entries(TYPE_BY_EXTENSION)
|
|
87
|
-
.filter(([, contentType]) => mediaKind(contentType) !== "opaque")
|
|
88
|
-
.map(([ext]) => ext);
|
|
89
|
-
/**
|
|
90
|
-
* The content-type to UPLOAD a file as, given what the platform claimed and
|
|
91
|
-
* what the file is called.
|
|
92
|
-
*
|
|
93
|
-
* WHY THIS EXISTS. The upload client used to send `file.type || "video/mp4"`.
|
|
94
|
-
* Both halves are wrong: the alias case rejects real MP3s (see above), and the
|
|
95
|
-
* fallback silently relabels ANY untyped file as video — so an MP3 dragged in
|
|
96
|
-
* without a MIME is accepted and then routed down the VIDEO transcode path by
|
|
97
|
-
* `mediaKind()`, which is a wrong pipeline rather than an honest refusal.
|
|
98
|
-
*
|
|
99
|
-
* Order: an already-allowed type wins, then a known alias, then the extension.
|
|
100
|
-
* If none of those resolve, the ORIGINAL string is returned unchanged — never a
|
|
101
|
-
* guess. The closed gate then refuses it and names the type the user actually
|
|
102
|
-
* has, which is the error message they need.
|
|
103
|
-
*/
|
|
104
|
-
export function contentTypeForUpload(filename, claimed) {
|
|
105
|
-
const ct = (claimed ?? "").trim().toLowerCase();
|
|
106
|
-
const allowed = ALLOWED_CONTENT_TYPES;
|
|
107
|
-
if (ct && allowed.includes(ct))
|
|
108
|
-
return ct;
|
|
109
|
-
if (ct && CONTENT_TYPE_ALIASES[ct])
|
|
110
|
-
return CONTENT_TYPE_ALIASES[ct];
|
|
111
|
-
const ext = filename.toLowerCase().split(".").pop() ?? "";
|
|
112
|
-
const byExt = TYPE_BY_EXTENSION[ext];
|
|
113
|
-
if (byExt)
|
|
114
|
-
return byExt;
|
|
115
|
-
return ct;
|
|
116
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { runMediaStoreContract } from './mediaStoreContract';
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* THE MEDIA STORE CONTRACT — one executable statement, every store.
|
|
3
|
-
*
|
|
4
|
-
* A pool item is persisted by TWO independent implementations: the desktop's
|
|
5
|
-
* sqlite (`src-tauri/src/database/pool_items.rs`) and the org's Convex
|
|
6
|
-
* documents, reached through an adapter each. A third lives in the test double
|
|
7
|
-
* the app's own tests run against.
|
|
8
|
-
*
|
|
9
|
-
* The surface is three verbs — getPoolItems / savePoolItem / deletePoolItem —
|
|
10
|
-
* and until now it had NO contract, which is the same setup that let
|
|
11
|
-
* `conversations` and `restorePoints` diverge invisibly for weeks.
|
|
12
|
-
*
|
|
13
|
-
* WHY THE RUST LANE IS NOT DRIVEN FROM HERE: it lives behind `cargo test`. The
|
|
14
|
-
* same facts are written as `#[tokio::test]`s in `database/mod.rs`
|
|
15
|
-
* (`media_store_contract_tests`) UNDER THE SAME NAMES — matching names are the
|
|
16
|
-
* seam that makes a one-sided fact one grep away. NOTE: no CI workflow runs
|
|
17
|
-
* `cargo`, so that half executes only when someone runs it by hand. This is
|
|
18
|
-
* not coverage.
|
|
19
|
-
*/
|
|
20
|
-
import { describe, it, expect, beforeEach } from 'vitest';
|
|
21
|
-
const still = (id) => ({
|
|
22
|
-
id,
|
|
23
|
-
name: `${id}.png`,
|
|
24
|
-
kind: 'image',
|
|
25
|
-
metadata: { width: 1920, height: 1080 },
|
|
26
|
-
});
|
|
27
|
-
const clip = (id) => ({
|
|
28
|
-
id,
|
|
29
|
-
name: `${id}.mp4`,
|
|
30
|
-
kind: 'video',
|
|
31
|
-
metadata: { duration: 12.5, width: 1920, height: 1080 },
|
|
32
|
-
});
|
|
33
|
-
export function runMediaStoreContract(name, makeStore) {
|
|
34
|
-
describe(`media store contract: ${name}`, () => {
|
|
35
|
-
let store;
|
|
36
|
-
beforeEach(async () => {
|
|
37
|
-
store = await makeStore();
|
|
38
|
-
});
|
|
39
|
-
it('round-trips kind', async () => {
|
|
40
|
-
await store.savePoolItem(clip('v1'));
|
|
41
|
-
await store.savePoolItem(still('i1'));
|
|
42
|
-
const items = await store.getPoolItems();
|
|
43
|
-
expect(items.find((i) => i.id === 'v1')?.kind).toBe('video');
|
|
44
|
-
expect(items.find((i) => i.id === 'i1')?.kind).toBe('image');
|
|
45
|
-
});
|
|
46
|
-
it('admits only the three placeable kinds', async () => {
|
|
47
|
-
await store.savePoolItem(clip('v2'));
|
|
48
|
-
await store.savePoolItem(still('i2'));
|
|
49
|
-
const kinds = new Set((await store.getPoolItems()).map((i) => i.kind));
|
|
50
|
-
for (const k of kinds)
|
|
51
|
-
expect(['video', 'audio', 'image']).toContain(k);
|
|
52
|
-
});
|
|
53
|
-
// The bug this whole change came from: a still has no source timeline
|
|
54
|
-
// (compositionRender.ts:609). A store that hands back 0 has invented one.
|
|
55
|
-
it('gives a still back with NO duration', async () => {
|
|
56
|
-
await store.savePoolItem(still('i3'));
|
|
57
|
-
const got = (await store.getPoolItems()).find((i) => i.id === 'i3');
|
|
58
|
-
expect(got?.metadata?.duration).toBeUndefined();
|
|
59
|
-
});
|
|
60
|
-
it('keeps a real duration on motion media', async () => {
|
|
61
|
-
await store.savePoolItem(clip('v3'));
|
|
62
|
-
const got = (await store.getPoolItems()).find((i) => i.id === 'v3');
|
|
63
|
-
expect(got?.metadata?.duration).toBe(12.5);
|
|
64
|
-
});
|
|
65
|
-
it('an audio item is never handed back as video', async () => {
|
|
66
|
-
await store.savePoolItem({
|
|
67
|
-
id: 'a1',
|
|
68
|
-
name: 'a1.mp3',
|
|
69
|
-
kind: 'audio',
|
|
70
|
-
metadata: { duration: 30, width: 0, height: 0 },
|
|
71
|
-
});
|
|
72
|
-
const got = (await store.getPoolItems()).find((i) => i.id === 'a1');
|
|
73
|
-
expect(got?.kind).toBe('audio');
|
|
74
|
-
});
|
|
75
|
-
it('deleting removes it from the list', async () => {
|
|
76
|
-
await store.savePoolItem(clip('v4'));
|
|
77
|
-
await store.deletePoolItem('v4');
|
|
78
|
-
const items = await store.getPoolItems();
|
|
79
|
-
expect(items.find((i) => i.id === 'v4')).toBeUndefined();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* WHAT COUNTS AS A SPOKEN-WORD HIT, AND WHAT IT IS WORTH.
|
|
3
|
-
*
|
|
4
|
-
* This rule is implemented TWICE and has to be — the desktop searches its local
|
|
5
|
-
* `transcript_segments` table in Rust (`src-tauri/src/database/transcripts.rs`),
|
|
6
|
-
* and the web searches the utterances in an R2 blob in TypeScript. Neither can
|
|
7
|
-
* call the other: one is a SQL `LIKE` chain inside a Tauri command, the other
|
|
8
|
-
* runs in a browser against a JSON object it just downloaded.
|
|
9
|
-
*
|
|
10
|
-
* SO THE RULE IS DATA, AND BOTH LANES RUN THE SAME DATA. `cases.json` beside
|
|
11
|
-
* this file is the shared table: each row is a query, some spoken lines, and
|
|
12
|
-
* the hits they must produce, in order. This module is the TypeScript runner;
|
|
13
|
-
* `contract_transcript_search_cases` in `database/mod.rs` is the Rust one,
|
|
14
|
-
* reading the same file. A rule change that lands in one lane and not the other
|
|
15
|
-
* fails the table on the side that was missed.
|
|
16
|
-
*
|
|
17
|
-
* WHY A TABLE AND NOT A PARAMETERISED SUITE: this is a pure, stateless
|
|
18
|
-
* operation — inputs in, ranking out, no store to set up — which is exactly the
|
|
19
|
-
* case CLAUDE.md's decision table assigns to fixtures-as-data. A suite is for
|
|
20
|
-
* stateful CRUD behind one interface.
|
|
21
|
-
*
|
|
22
|
-
* WHY THE SCORES MATTER RATHER THAN JUST THE ORDER: `desktopScope`'s library
|
|
23
|
-
* search puts spoken hits above visual ones and says in its own comment that a
|
|
24
|
-
* transcript score and a CLIP cosine are different units that must not be
|
|
25
|
-
* merged by value. That reasoning only holds if a transcript score means one
|
|
26
|
-
* fixed thing, so two lanes scoring the same line differently would quietly
|
|
27
|
-
* make the ordering arbitrary.
|
|
28
|
-
*/
|
|
29
|
-
/**
|
|
30
|
-
* A line containing the whole query as a PHRASE is a stronger answer than one
|
|
31
|
-
* that happens to contain the same words apart. Both outrank nothing.
|
|
32
|
-
*/
|
|
33
|
-
export const PHRASE_SCORE = 1.0;
|
|
34
|
-
export const SCATTERED_SCORE = 0.6;
|
|
35
|
-
/** The query, lowercased and split. Empty query = no terms = no hits. */
|
|
36
|
-
export function searchTerms(query) {
|
|
37
|
-
return query
|
|
38
|
-
.toLowerCase()
|
|
39
|
-
.split(/\s+/)
|
|
40
|
-
.filter((t) => t.length > 0);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Rank the lines that match every term.
|
|
44
|
-
*
|
|
45
|
-
* `limit` is applied LAST, after ranking, so the strongest hits survive a small
|
|
46
|
-
* limit rather than whichever happened to be spoken first.
|
|
47
|
-
*/
|
|
48
|
-
export function rankTranscriptHits(query, lines, limit) {
|
|
49
|
-
const terms = searchTerms(query);
|
|
50
|
-
if (terms.length === 0)
|
|
51
|
-
return [];
|
|
52
|
-
const phrase = terms.join(" ");
|
|
53
|
-
const hits = [];
|
|
54
|
-
for (const line of lines) {
|
|
55
|
-
const lower = line.text.toLowerCase();
|
|
56
|
-
// EVERY term, not any — an `AND` chain, matching the SQL the desktop runs.
|
|
57
|
-
if (!terms.every((t) => lower.includes(t)))
|
|
58
|
-
continue;
|
|
59
|
-
hits.push({
|
|
60
|
-
text: line.text,
|
|
61
|
-
start: line.start,
|
|
62
|
-
end: line.end,
|
|
63
|
-
score: lower.includes(phrase) ? PHRASE_SCORE : SCATTERED_SCORE,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
// Score first, then earliest — stable within a score band, so one media
|
|
67
|
-
// item's hits stay in the order they were spoken.
|
|
68
|
-
hits.sort((a, b) => b.score - a.score || a.start - b.start);
|
|
69
|
-
return limit === undefined ? hits : hits.slice(0, limit);
|
|
70
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$comment": "THE SHARED TABLE. Read by the TypeScript runner (transcriptSearch.test.ts) and by the Rust one (contract_transcript_search_cases in src-tauri/src/database/mod.rs). Adding a row here obliges BOTH lanes. See transcriptSearch.ts for why this rule is data rather than a shared function.",
|
|
3
|
-
"cases": [
|
|
4
|
-
{
|
|
5
|
-
"name": "every term must be present, not just one",
|
|
6
|
-
"query": "pricing model",
|
|
7
|
-
"lines": [
|
|
8
|
-
{ "text": "our pricing model is simple", "start": 1, "end": 3 },
|
|
9
|
-
{ "text": "the pricing is simple", "start": 4, "end": 6 },
|
|
10
|
-
{ "text": "a model of the product", "start": 7, "end": 9 }
|
|
11
|
-
],
|
|
12
|
-
"expected": [{ "text": "our pricing model is simple", "start": 1, "end": 3, "score": 1.0 }]
|
|
13
|
-
},
|
|
14
|
-
{
|
|
15
|
-
"name": "the whole phrase outranks the same words apart",
|
|
16
|
-
"query": "pricing model",
|
|
17
|
-
"lines": [
|
|
18
|
-
{ "text": "the model behind our pricing", "start": 1, "end": 3 },
|
|
19
|
-
{ "text": "our pricing model", "start": 5, "end": 7 }
|
|
20
|
-
],
|
|
21
|
-
"expected": [
|
|
22
|
-
{ "text": "our pricing model", "start": 5, "end": 7, "score": 1.0 },
|
|
23
|
-
{ "text": "the model behind our pricing", "start": 1, "end": 3, "score": 0.6 }
|
|
24
|
-
]
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"name": "within a score band, earliest first",
|
|
28
|
-
"query": "pricing model",
|
|
29
|
-
"lines": [
|
|
30
|
-
{ "text": "model, and then pricing", "start": 9, "end": 10 },
|
|
31
|
-
{ "text": "pricing comes after the model", "start": 2, "end": 3 }
|
|
32
|
-
],
|
|
33
|
-
"expected": [
|
|
34
|
-
{ "text": "pricing comes after the model", "start": 2, "end": 3, "score": 0.6 },
|
|
35
|
-
{ "text": "model, and then pricing", "start": 9, "end": 10, "score": 0.6 }
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"name": "matching ignores case on both sides",
|
|
40
|
-
"query": "PRICING",
|
|
41
|
-
"lines": [{ "text": "Our Pricing Page", "start": 1, "end": 2 }],
|
|
42
|
-
"expected": [{ "text": "Our Pricing Page", "start": 1, "end": 2, "score": 1.0 }]
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"name": "a term matches inside a word",
|
|
46
|
-
"query": "price",
|
|
47
|
-
"lines": [{ "text": "repriced last quarter", "start": 1, "end": 2 }],
|
|
48
|
-
"expected": [{ "text": "repriced last quarter", "start": 1, "end": 2, "score": 1.0 }]
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
"name": "an empty query is no hits, never every hit",
|
|
52
|
-
"query": " ",
|
|
53
|
-
"lines": [{ "text": "anything at all", "start": 1, "end": 2 }],
|
|
54
|
-
"expected": []
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
"name": "extra whitespace in the query does not create an unmatchable term",
|
|
58
|
-
"query": " pricing model ",
|
|
59
|
-
"lines": [{ "text": "our pricing model", "start": 1, "end": 2 }],
|
|
60
|
-
"expected": [{ "text": "our pricing model", "start": 1, "end": 2, "score": 1.0 }]
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"name": "no match is an empty answer",
|
|
64
|
-
"query": "onboarding",
|
|
65
|
-
"lines": [{ "text": "our pricing model", "start": 1, "end": 2 }],
|
|
66
|
-
"expected": []
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
"name": "the limit keeps the strongest, not the earliest",
|
|
70
|
-
"query": "pricing model",
|
|
71
|
-
"limit": 1,
|
|
72
|
-
"lines": [
|
|
73
|
-
{ "text": "model, then pricing", "start": 1, "end": 2 },
|
|
74
|
-
{ "text": "our pricing model", "start": 8, "end": 9 }
|
|
75
|
-
],
|
|
76
|
-
"expected": [{ "text": "our pricing model", "start": 8, "end": 9, "score": 1.0 }]
|
|
77
|
-
}
|
|
78
|
-
]
|
|
79
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
export function compactTimeline(clips, deletedRanges) {
|
|
2
|
-
const byClip = new Map();
|
|
3
|
-
for (const r of deletedRanges) {
|
|
4
|
-
if (!byClip.has(r.clipId))
|
|
5
|
-
byClip.set(r.clipId, []);
|
|
6
|
-
byClip.get(r.clipId).push(r);
|
|
7
|
-
}
|
|
8
|
-
const survivors = [];
|
|
9
|
-
const sortedClips = [...clips].sort((a, b) => a.timelineStart - b.timelineStart);
|
|
10
|
-
for (const clip of sortedClips) {
|
|
11
|
-
const clipDuration = clip.sourceOut - clip.sourceIn;
|
|
12
|
-
const ranges = (byClip.get(clip.id) ?? [])
|
|
13
|
-
.map(r => ({
|
|
14
|
-
start: Math.max(0, Math.min(r.startSec, clipDuration)),
|
|
15
|
-
end: Math.max(0, Math.min(r.endSec, clipDuration)),
|
|
16
|
-
}))
|
|
17
|
-
.filter(r => r.end > r.start)
|
|
18
|
-
.sort((a, b) => a.start - b.start);
|
|
19
|
-
const merged = [];
|
|
20
|
-
for (const r of ranges) {
|
|
21
|
-
const last = merged[merged.length - 1];
|
|
22
|
-
if (last && r.start <= last.end)
|
|
23
|
-
last.end = Math.max(last.end, r.end);
|
|
24
|
-
else
|
|
25
|
-
merged.push({ ...r });
|
|
26
|
-
}
|
|
27
|
-
const keep = [];
|
|
28
|
-
let cursor = 0;
|
|
29
|
-
for (const r of merged) {
|
|
30
|
-
if (r.start > cursor)
|
|
31
|
-
keep.push({ start: cursor, end: r.start });
|
|
32
|
-
cursor = r.end;
|
|
33
|
-
}
|
|
34
|
-
if (cursor < clipDuration)
|
|
35
|
-
keep.push({ start: cursor, end: clipDuration });
|
|
36
|
-
const anySplit = merged.length > 0;
|
|
37
|
-
keep.forEach((seg, idx) => {
|
|
38
|
-
survivors.push({
|
|
39
|
-
id: anySplit ? `${clip.id}__${idx}` : clip.id,
|
|
40
|
-
originalClipId: anySplit ? clip.id : undefined,
|
|
41
|
-
poolItemId: clip.poolItemId,
|
|
42
|
-
sourceIn: clip.sourceIn + seg.start,
|
|
43
|
-
sourceOut: clip.sourceIn + seg.end,
|
|
44
|
-
transitionIn: clip.transitionIn,
|
|
45
|
-
transitionDuration: clip.transitionDuration,
|
|
46
|
-
durationSec: seg.end - seg.start,
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
let tlCursor = 0;
|
|
51
|
-
return survivors.map(s => {
|
|
52
|
-
const timelineStart = tlCursor;
|
|
53
|
-
const timelineEnd = tlCursor + s.durationSec;
|
|
54
|
-
tlCursor = timelineEnd;
|
|
55
|
-
const { durationSec: _d, ...rest } = s;
|
|
56
|
-
const result = {
|
|
57
|
-
id: rest.id,
|
|
58
|
-
poolItemId: rest.poolItemId,
|
|
59
|
-
sourceIn: rest.sourceIn,
|
|
60
|
-
sourceOut: rest.sourceOut,
|
|
61
|
-
timelineStart,
|
|
62
|
-
timelineEnd,
|
|
63
|
-
};
|
|
64
|
-
if (rest.originalClipId !== undefined)
|
|
65
|
-
result.originalClipId = rest.originalClipId;
|
|
66
|
-
if (rest.transitionIn !== undefined)
|
|
67
|
-
result.transitionIn = rest.transitionIn;
|
|
68
|
-
if (rest.transitionDuration !== undefined)
|
|
69
|
-
result.transitionDuration = rest.transitionDuration;
|
|
70
|
-
return result;
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
//# sourceMappingURL=compact-timeline.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"compact-timeline.js","sourceRoot":"","sources":["../src/compact-timeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import { compactTimeline } from "./compact-timeline";
|
|
2
|
-
import { CompositionValidationError } from "./types";
|
|
3
|
-
import { getPrimitiveText } from "@cueframe/compose";
|
|
4
|
-
const EPSILON = 1e-6;
|
|
5
|
-
function sequenceRational(fps) {
|
|
6
|
-
if (Math.abs(fps - 29.97) < 0.01)
|
|
7
|
-
return { fpsNum: 30000, fpsDen: 1001 };
|
|
8
|
-
if (Math.abs(fps - 23.976) < 0.01)
|
|
9
|
-
return { fpsNum: 24000, fpsDen: 1001 };
|
|
10
|
-
if (Math.abs(fps - 59.94) < 0.01)
|
|
11
|
-
return { fpsNum: 60000, fpsDen: 1001 };
|
|
12
|
-
return { fpsNum: Math.round(fps), fpsDen: 1 };
|
|
13
|
-
}
|
|
14
|
-
export function compositionToClipExportInput(composition, trimmedRefs) {
|
|
15
|
-
// Validate overlaps/gaps against the ORIGINAL composition clips (compactTimeline
|
|
16
|
-
// re-lays-out clips contiguously by cursor, so it would hide these defects).
|
|
17
|
-
const originalSorted = [...composition.clips].sort((a, b) => a.timelineStart - b.timelineStart);
|
|
18
|
-
for (let i = 0; i < originalSorted.length - 1; i++) {
|
|
19
|
-
const cur = originalSorted[i], next = originalSorted[i + 1];
|
|
20
|
-
if (next.timelineStart < cur.timelineEnd - EPSILON) {
|
|
21
|
-
throw new CompositionValidationError("Composition spine overlaps — clips must not share timeline time in v1", { kind: "overlap", detail: `${cur.id} overlaps ${next.id}` });
|
|
22
|
-
}
|
|
23
|
-
if (next.timelineStart > cur.timelineEnd + EPSILON) {
|
|
24
|
-
throw new CompositionValidationError("Composition spine has a gap — clips must be contiguous in v1", { kind: "gap", detail: `${cur.id} ends at ${cur.timelineEnd}, ${next.id} starts at ${next.timelineStart}` });
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
const compacted = compactTimeline(composition.clips, composition.deletedRanges);
|
|
28
|
-
const sorted = [...compacted].sort((a, b) => a.timelineStart - b.timelineStart);
|
|
29
|
-
function findRef(clip) {
|
|
30
|
-
// Match by exact integer triple. Trim activity computed
|
|
31
|
-
// inFramesAtSourceRate via `round(sourceIn * mediaItemFps)` — we use
|
|
32
|
-
// the same formula here so the round-trip is deterministic regardless
|
|
33
|
-
// of whether mediaItem.frameRate is stored as 29.97 (decimal) while
|
|
34
|
-
// ffprobe reports 30000/1001 (rational).
|
|
35
|
-
const match = trimmedRefs.find(r => {
|
|
36
|
-
if (r.sourceId !== clip.poolItemId)
|
|
37
|
-
return false;
|
|
38
|
-
const expectedIn = Math.round(clip.sourceIn * r.mediaItemFps);
|
|
39
|
-
const expectedOut = Math.round(clip.sourceOut * r.mediaItemFps);
|
|
40
|
-
return (r.inFramesAtSourceRate === expectedIn &&
|
|
41
|
-
r.outFramesAtSourceRate === expectedOut);
|
|
42
|
-
});
|
|
43
|
-
if (!match) {
|
|
44
|
-
throw new CompositionValidationError("Missing trimmedRef for clip", { kind: "missing-trim", detail: `clip ${clip.id} (${clip.poolItemId} ${clip.sourceIn}-${clip.sourceOut}s)` });
|
|
45
|
-
}
|
|
46
|
-
return match;
|
|
47
|
-
}
|
|
48
|
-
const assetOrder = [];
|
|
49
|
-
const refForClip = new Map();
|
|
50
|
-
for (const clip of sorted) {
|
|
51
|
-
const ref = findRef(clip);
|
|
52
|
-
refForClip.set(clip.id, ref);
|
|
53
|
-
const key = `${ref.sourceId}::${ref.inFramesAtSourceRate}::${ref.outFramesAtSourceRate}`;
|
|
54
|
-
if (!assetOrder.includes(key))
|
|
55
|
-
assetOrder.push(key);
|
|
56
|
-
}
|
|
57
|
-
const assetIdByKey = new Map();
|
|
58
|
-
const refByKey = new Map();
|
|
59
|
-
for (const clip of sorted) {
|
|
60
|
-
const ref = refForClip.get(clip.id);
|
|
61
|
-
const key = `${ref.sourceId}::${ref.inFramesAtSourceRate}::${ref.outFramesAtSourceRate}`;
|
|
62
|
-
if (!refByKey.has(key))
|
|
63
|
-
refByKey.set(key, ref);
|
|
64
|
-
}
|
|
65
|
-
const assets = assetOrder.map((key, i) => {
|
|
66
|
-
const id = `a${i + 1}`;
|
|
67
|
-
assetIdByKey.set(key, id);
|
|
68
|
-
const ref = refByKey.get(key);
|
|
69
|
-
return {
|
|
70
|
-
id,
|
|
71
|
-
relPath: `media/${id}.mp4`,
|
|
72
|
-
displayName: ref.displayName,
|
|
73
|
-
sourceId: ref.sourceId,
|
|
74
|
-
originInFrames: ref.inFramesAtSourceRate,
|
|
75
|
-
originOutFrames: ref.outFramesAtSourceRate,
|
|
76
|
-
fpsNum: ref.sourceFpsNum,
|
|
77
|
-
fpsDen: ref.sourceFpsDen,
|
|
78
|
-
width: composition.width,
|
|
79
|
-
height: composition.height,
|
|
80
|
-
durationSec: ref.durationSec,
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
const { fpsNum, fpsDen } = sequenceRational(composition.fps);
|
|
84
|
-
const seqFps = fpsNum / fpsDen;
|
|
85
|
-
// Map: original (pre-split) TimelineClip id → spine item id (first segment)
|
|
86
|
-
const spineIdByOriginalClipId = new Map();
|
|
87
|
-
const spine = sorted.map((clip, idx) => {
|
|
88
|
-
const ref = refForClip.get(clip.id);
|
|
89
|
-
const sourceFps = ref.sourceFpsNum / ref.sourceFpsDen;
|
|
90
|
-
const key = `${ref.sourceId}::${ref.inFramesAtSourceRate}::${ref.outFramesAtSourceRate}`;
|
|
91
|
-
const spineId = `s${idx + 1}`;
|
|
92
|
-
const originalId = clip.originalClipId ?? clip.id;
|
|
93
|
-
if (!spineIdByOriginalClipId.has(originalId)) {
|
|
94
|
-
spineIdByOriginalClipId.set(originalId, spineId);
|
|
95
|
-
}
|
|
96
|
-
const inFrames = Math.round(ref.handleBeforeSec * sourceFps);
|
|
97
|
-
const clipLen = Math.round((clip.sourceOut - clip.sourceIn) * sourceFps);
|
|
98
|
-
return {
|
|
99
|
-
id: spineId,
|
|
100
|
-
assetId: assetIdByKey.get(key),
|
|
101
|
-
inFrames,
|
|
102
|
-
outFrames: inFrames + clipLen,
|
|
103
|
-
timelineStartFrames: Math.round(clip.timelineStart * seqFps),
|
|
104
|
-
timelineDurationFrames: Math.round((clip.timelineEnd - clip.timelineStart) * seqFps),
|
|
105
|
-
};
|
|
106
|
-
});
|
|
107
|
-
const markers = [];
|
|
108
|
-
if (composition.metadata?.cueframe?.hook) {
|
|
109
|
-
markers.push({
|
|
110
|
-
startFrames: 0,
|
|
111
|
-
durationFrames: 1,
|
|
112
|
-
name: composition.metadata.cueframe.hook,
|
|
113
|
-
kind: "hook",
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
for (const label of composition.sceneLabels) {
|
|
117
|
-
const spineItemId = spineIdByOriginalClipId.get(label.clipId);
|
|
118
|
-
if (!spineItemId)
|
|
119
|
-
continue;
|
|
120
|
-
const spineItem = spine.find(s => s.id === spineItemId);
|
|
121
|
-
const timelineSec = (spineItem.timelineStartFrames / seqFps) + label.startSec;
|
|
122
|
-
markers.push({
|
|
123
|
-
startFrames: Math.round(timelineSec * seqFps),
|
|
124
|
-
durationFrames: 1,
|
|
125
|
-
name: label.text,
|
|
126
|
-
kind: "scene",
|
|
127
|
-
spineItemId,
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
const textOverlays = composition.overlays.map(o => ({
|
|
131
|
-
text: getPrimitiveText({ template: o.template, params: o.params ?? {} }) ?? "",
|
|
132
|
-
startFrames: o.startFrame,
|
|
133
|
-
durationFrames: o.durationInFrames,
|
|
134
|
-
}));
|
|
135
|
-
const durationFrames = spine.reduce((sum, s) => Math.max(sum, s.timelineStartFrames + s.timelineDurationFrames), 0);
|
|
136
|
-
return {
|
|
137
|
-
title: composition.metadata?.cueframe?.hook ?? "Clip Export",
|
|
138
|
-
hook: composition.metadata?.cueframe?.hook,
|
|
139
|
-
sequence: { fpsNum, fpsDen, width: composition.width, height: composition.height, durationFrames },
|
|
140
|
-
assets,
|
|
141
|
-
spine,
|
|
142
|
-
markers,
|
|
143
|
-
textOverlays,
|
|
144
|
-
audioTracks: [],
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
//# sourceMappingURL=composition-to-input.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"composition-to-input.js","sourceRoot":"","sources":["../src/composition-to-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAMrD,OAAO,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,OAAO,GAAG,IAAI,CAAC;AAErB,SAAS,gBAAgB,CAAC,GAAW;IACnC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACzE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1E,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI;QAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACzE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,4BAA4B,CAC1C,WAA8B,EAC9B,WAAyB;IAEzB,iFAAiF;IACjF,6EAA6E;IAC7E,MAAM,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAChG,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACnD,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5D,IAAI,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,WAAW,GAAG,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,0BAA0B,CAClC,uEAAuE,EACvE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,aAAa,IAAI,CAAC,EAAE,EAAE,EAAE,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,WAAW,GAAG,OAAO,EAAE,CAAC;YACnD,MAAM,IAAI,0BAA0B,CAClC,8DAA8D,EAC9D,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,YAAY,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,EAAE,cAAc,IAAI,CAAC,aAAa,EAAE,EAAE,CAC5G,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,eAAe,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;IAChF,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC;IAEhF,SAAS,OAAO,CAAC,IAAkB;QACjC,wDAAwD;QACxD,qEAAqE;QACrE,sEAAsE;QACtE,oEAAoE;QACpE,yCAAyC;QACzC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,UAAU;gBAAE,OAAO,KAAK,CAAC;YACjD,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;YAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC;YAChE,OAAO,CACL,CAAC,CAAC,oBAAoB,KAAK,UAAU;gBACrC,CAAC,CAAC,qBAAqB,KAAK,WAAW,CACxC,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,0BAA0B,CAClC,6BAA6B,EAC7B,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,EAAE,QAAQ,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,CAC7G,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IACjD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACzF,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAC;QACrC,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACzF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IAED,MAAM,MAAM,GAAsB,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QAC1D,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC/B,OAAO;YACL,EAAE;YACF,OAAO,EAAE,SAAS,EAAE,MAAM;YAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;YAC5B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,cAAc,EAAE,GAAG,CAAC,oBAAoB;YACxC,eAAe,EAAE,GAAG,CAAC,qBAAqB;YAC1C,MAAM,EAAE,GAAG,CAAC,YAAY;YACxB,MAAM,EAAE,GAAG,CAAC,YAAY;YACxB,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,WAAW,EAAE,GAAG,CAAC,WAAW;SAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;IAE/B,4EAA4E;IAC5E,MAAM,uBAAuB,GAAG,IAAI,GAAG,EAAkB,CAAC;IAE1D,MAAM,KAAK,GAAgB,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAClD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAE,CAAC;QACrC,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,GAAG,GAAG,CAAC,YAAY,CAAC;QACtD,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACzF,MAAM,OAAO,GAAG,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC;QAE9B,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,IAAI,IAAI,CAAC,EAAE,CAAC;QAClD,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;YAC7C,uBAAuB,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,CAAC;QACzE,OAAO;YACL,EAAE,EAAE,OAAO;YACX,OAAO,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAE;YAC/B,QAAQ;YACR,SAAS,EAAE,QAAQ,GAAG,OAAO;YAC7B,mBAAmB,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC;YAC5D,sBAAsB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;SACrF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACzC,OAAO,CAAC,IAAI,CAAC;YACX,WAAW,EAAE,CAAC;YACd,cAAc,EAAE,CAAC;YACjB,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI;YACxC,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;IACL,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,WAAW,GAAG,uBAAuB,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW;YAAE,SAAS;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAE,CAAC;QACzD,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,mBAAmB,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC9E,OAAO,CAAC,IAAI,CAAC;YACX,WAAW,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;YAC7C,cAAc,EAAE,CAAC;YACjB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,IAAI,EAAE,OAAO;YACb,WAAW;SACZ,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAwB,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACvE,IAAI,EAAE,gBAAgB,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;QAC9E,WAAW,EAAE,CAAC,CAAC,UAAU;QACzB,cAAc,EAAE,CAAC,CAAC,gBAAgB;KACnC,CAAC,CAAC,CAAC;IAEJ,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CACjC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,mBAAmB,GAAG,CAAC,CAAC,sBAAsB,CAAC,EAC3E,CAAC,CACF,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,IAAI,aAAa;QAC5D,IAAI,EAAE,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI;QAC1C,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,cAAc,EAAE;QAClG,MAAM;QACN,KAAK;QACL,OAAO;QACP,YAAY;QACZ,WAAW,EAAE,EAAE;KAChB,CAAC;AACJ,CAAC"}
|