@nodaro/shared 1.4.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 +202 -0
- package/README.md +32 -0
- package/dist/index.cjs +12506 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12269 -0
- package/dist/index.d.ts +12269 -0
- package/dist/index.js +11831 -0
- package/dist/index.js.map +1 -0
- package/package.json +54 -0
- package/src/__tests__/__snapshots__/prompt-builder-segments.test.ts.snap +65 -0
- package/src/__tests__/ai-avatar-pricing.test.ts +321 -0
- package/src/__tests__/apply-video-negative-prompt.test.ts +76 -0
- package/src/__tests__/attach-columns.test.ts +28 -0
- package/src/__tests__/audio-crossfade-curves.test.ts +33 -0
- package/src/__tests__/build-model-menu.test.ts +58 -0
- package/src/__tests__/character-aspect-defaults.test.ts +142 -0
- package/src/__tests__/character-mention-slug.test.ts +199 -0
- package/src/__tests__/character-reference-photo-kinds.test.ts +32 -0
- package/src/__tests__/character-usage-mode.test.ts +147 -0
- package/src/__tests__/character-variant-assets.test.ts +142 -0
- package/src/__tests__/character-voice.test.ts +130 -0
- package/src/__tests__/cinematic-avatar-pricing.test.ts +119 -0
- package/src/__tests__/combine-transitions.test.ts +137 -0
- package/src/__tests__/component-types.test.ts +87 -0
- package/src/__tests__/condition-variables.test.ts +98 -0
- package/src/__tests__/credit-identifiers.test.ts +811 -0
- package/src/__tests__/default-video-provider.test.ts +63 -0
- package/src/__tests__/entity-image-handle.test.ts +43 -0
- package/src/__tests__/entity-variants.test.ts +33 -0
- package/src/__tests__/fal-lip-sync-sets.test.ts +31 -0
- package/src/__tests__/featured-entities.test.ts +33 -0
- package/src/__tests__/film-pricing.test.ts +64 -0
- package/src/__tests__/filter-condition.test.ts +285 -0
- package/src/__tests__/freecut-protocol.test.ts +35 -0
- package/src/__tests__/generate-text-items.test.ts +19 -0
- package/src/__tests__/generated-results.test.ts +50 -0
- package/src/__tests__/graph-utils.test.ts +618 -0
- package/src/__tests__/group-aggregation.test.ts +83 -0
- package/src/__tests__/i18n-locale-completeness.test.ts +156 -0
- package/src/__tests__/image-critic-node.test.ts +86 -0
- package/src/__tests__/image-mask-mode.test.ts +16 -0
- package/src/__tests__/image-ref-limit.test.ts +78 -0
- package/src/__tests__/inpaint-region.test.ts +24 -0
- package/src/__tests__/input-field-map-parity.test.ts +30 -0
- package/src/__tests__/json-evaluator.test.ts +289 -0
- package/src/__tests__/json-path.test.ts +64 -0
- package/src/__tests__/lip-sync-pricing.test.ts +142 -0
- package/src/__tests__/list-merge.test.ts +96 -0
- package/src/__tests__/list-sort.test.ts +134 -0
- package/src/__tests__/llm-models.test.ts +445 -0
- package/src/__tests__/location-mention-slug.test.ts +246 -0
- package/src/__tests__/locations-coverage-critic-schema.test.ts +92 -0
- package/src/__tests__/loop-delimiter.test.ts +39 -0
- package/src/__tests__/lottie-slots.test.ts +245 -0
- package/src/__tests__/model-catalog-flux2-resolutions.test.ts +21 -0
- package/src/__tests__/model-constants-location.test.ts +20 -0
- package/src/__tests__/model-constants.test.ts +122 -0
- package/src/__tests__/model-tree.test.ts +86 -0
- package/src/__tests__/no-internal-imports.test.ts +25 -0
- package/src/__tests__/node-default-mappings.test.ts +175 -0
- package/src/__tests__/node-mappable-fields.test.ts +7 -0
- package/src/__tests__/node-preset-export.test.ts +46 -0
- package/src/__tests__/node-preset-extract.test.ts +166 -0
- package/src/__tests__/node-refs-canonical.test.ts +54 -0
- package/src/__tests__/node-refs-combine.test.ts +54 -0
- package/src/__tests__/node-refs.test.ts +187 -0
- package/src/__tests__/node-runtime-keys.test.ts +99 -0
- package/src/__tests__/object-aspect-defaults.test.ts +59 -0
- package/src/__tests__/parameter-node-value.test.ts +137 -0
- package/src/__tests__/pinterest-url.test.ts +35 -0
- package/src/__tests__/pipeline-chat.test.ts +110 -0
- package/src/__tests__/pipeline-validation.test.ts +98 -0
- package/src/__tests__/presentation-utils.test.ts +1137 -0
- package/src/__tests__/producer-types.test.ts +47 -0
- package/src/__tests__/prompt-length-limits.test.ts +156 -0
- package/src/__tests__/provider-directive-defaults.test.ts +46 -0
- package/src/__tests__/reduce-strategy-registry.test.ts +43 -0
- package/src/__tests__/reference-board-templates.test.ts +33 -0
- package/src/__tests__/reference-roles.test.ts +36 -0
- package/src/__tests__/resolve-field-mappings.test.ts +110 -0
- package/src/__tests__/resolve-pipeline-model.test.ts +76 -0
- package/src/__tests__/scene-node-types.test.ts +80 -0
- package/src/__tests__/scraper-actors.test.ts +67 -0
- package/src/__tests__/seedance-2-catalog.test.ts +18 -0
- package/src/__tests__/seedance-2-credit-id.test.ts +23 -0
- package/src/__tests__/seedance-aspects.test.ts +52 -0
- package/src/__tests__/selector.test.ts +1151 -0
- package/src/__tests__/settled-with-limit.test.ts +214 -0
- package/src/__tests__/social-media-specs.test.ts +129 -0
- package/src/__tests__/sub-workflow-validation.test.ts +88 -0
- package/src/__tests__/switchx-pricing.test.ts +28 -0
- package/src/__tests__/to-connected-references.test.ts +153 -0
- package/src/__tests__/utilities.test.ts +541 -0
- package/src/__tests__/video-analysis-pricing.test.ts +58 -0
- package/src/__tests__/video-analysis.test.ts +63 -0
- package/src/__tests__/video-audio-capability.test.ts +204 -0
- package/src/__tests__/video-gen-providers.test.ts +28 -0
- package/src/__tests__/video-mode-aliases.test.ts +150 -0
- package/src/__tests__/video-ref-limits.test.ts +72 -0
- package/src/__tests__/video-utils.test.ts +303 -0
- package/src/__tests__/voice-changer-models.test.ts +33 -0
- package/src/__tests__/workflow-export-strip.test.ts +46 -0
- package/src/ai-avatar-pricing.ts +213 -0
- package/src/ancestor-refs.ts +48 -0
- package/src/animals.ts +231 -0
- package/src/audio-crossfade-curves.ts +73 -0
- package/src/audio-fx-presets.ts +64 -0
- package/src/avatar-payload-validators.ts +214 -0
- package/src/caption-styles.ts +31 -0
- package/src/character-aspect-defaults.ts +102 -0
- package/src/character-facets.ts +37 -0
- package/src/character-mention-slug.ts +166 -0
- package/src/character-usage-mode.ts +109 -0
- package/src/character-variant-assets.ts +121 -0
- package/src/character-voice.ts +151 -0
- package/src/cinematic-avatar-pricing.ts +111 -0
- package/src/clone-utils.ts +46 -0
- package/src/combine-transitions.ts +482 -0
- package/src/community.ts +112 -0
- package/src/component-types.ts +127 -0
- package/src/condition-variables.ts +65 -0
- package/src/credit-estimators/index.ts +15 -0
- package/src/credit-estimators/video-utils.ts +165 -0
- package/src/credit-identifiers.ts +304 -0
- package/src/entity-approval-types.ts +31 -0
- package/src/entity-aspect-defaults.ts +82 -0
- package/src/entity-asset-types.ts +296 -0
- package/src/entity-image-handle.ts +36 -0
- package/src/extra-refs.ts +139 -0
- package/src/featured-entities.ts +136 -0
- package/src/film-pricing.ts +117 -0
- package/src/filter-condition.ts +250 -0
- package/src/flux2-pricing.ts +18 -0
- package/src/freecut-protocol.ts +52 -0
- package/src/furniture.ts +167 -0
- package/src/generate-text-items.ts +15 -0
- package/src/generated-results.ts +63 -0
- package/src/group-aggregation.ts +75 -0
- package/src/hint-graph-types.ts +18 -0
- package/src/i18n/action-fx.ar.ts +89 -0
- package/src/i18n/action-fx.de.ts +89 -0
- package/src/i18n/action-fx.es.ts +89 -0
- package/src/i18n/action-fx.fr.ts +89 -0
- package/src/i18n/action-fx.he.ts +89 -0
- package/src/i18n/action-fx.hi.ts +89 -0
- package/src/i18n/action-fx.ja.ts +89 -0
- package/src/i18n/action-fx.ko.ts +89 -0
- package/src/i18n/action-fx.pt-BR.ts +89 -0
- package/src/i18n/action-fx.ru.ts +89 -0
- package/src/i18n/action-fx.zh-CN.ts +89 -0
- package/src/i18n/aesthetic.ar.ts +170 -0
- package/src/i18n/aesthetic.de.ts +48 -0
- package/src/i18n/aesthetic.es.ts +169 -0
- package/src/i18n/aesthetic.fr.ts +52 -0
- package/src/i18n/aesthetic.he.ts +169 -0
- package/src/i18n/aesthetic.hi.ts +55 -0
- package/src/i18n/aesthetic.ja.ts +165 -0
- package/src/i18n/aesthetic.ko.ts +169 -0
- package/src/i18n/aesthetic.pt-BR.ts +148 -0
- package/src/i18n/aesthetic.ru.ts +155 -0
- package/src/i18n/aesthetic.zh-CN.ts +172 -0
- package/src/i18n/animals.ar.ts +145 -0
- package/src/i18n/animals.de.ts +144 -0
- package/src/i18n/animals.es.ts +158 -0
- package/src/i18n/animals.fr.ts +144 -0
- package/src/i18n/animals.he.ts +155 -0
- package/src/i18n/animals.hi.ts +157 -0
- package/src/i18n/animals.ja.ts +159 -0
- package/src/i18n/animals.ko.ts +159 -0
- package/src/i18n/animals.pt-BR.ts +157 -0
- package/src/i18n/animals.ru.ts +155 -0
- package/src/i18n/animals.zh-CN.ts +155 -0
- package/src/i18n/atmosphere.ar.ts +49 -0
- package/src/i18n/atmosphere.de.ts +47 -0
- package/src/i18n/atmosphere.es.ts +50 -0
- package/src/i18n/atmosphere.fr.ts +47 -0
- package/src/i18n/atmosphere.he.ts +47 -0
- package/src/i18n/atmosphere.hi.ts +49 -0
- package/src/i18n/atmosphere.ja.ts +49 -0
- package/src/i18n/atmosphere.ko.ts +49 -0
- package/src/i18n/atmosphere.pt-BR.ts +49 -0
- package/src/i18n/atmosphere.ru.ts +47 -0
- package/src/i18n/atmosphere.zh-CN.ts +152 -0
- package/src/i18n/backdrop.ar.ts +53 -0
- package/src/i18n/backdrop.de.ts +46 -0
- package/src/i18n/backdrop.es.ts +54 -0
- package/src/i18n/backdrop.fr.ts +52 -0
- package/src/i18n/backdrop.he.ts +51 -0
- package/src/i18n/backdrop.hi.ts +59 -0
- package/src/i18n/backdrop.ja.ts +61 -0
- package/src/i18n/backdrop.ko.ts +59 -0
- package/src/i18n/backdrop.pt-BR.ts +59 -0
- package/src/i18n/backdrop.ru.ts +57 -0
- package/src/i18n/backdrop.zh-CN.ts +57 -0
- package/src/i18n/camera-format.ar.ts +40 -0
- package/src/i18n/camera-format.de.ts +37 -0
- package/src/i18n/camera-format.es.ts +41 -0
- package/src/i18n/camera-format.fr.ts +37 -0
- package/src/i18n/camera-format.he.ts +37 -0
- package/src/i18n/camera-format.hi.ts +42 -0
- package/src/i18n/camera-format.ja.ts +37 -0
- package/src/i18n/camera-format.ko.ts +37 -0
- package/src/i18n/camera-format.pt-BR.ts +46 -0
- package/src/i18n/camera-format.ru.ts +42 -0
- package/src/i18n/camera-format.zh-CN.ts +42 -0
- package/src/i18n/camera-motions.ar.ts +86 -0
- package/src/i18n/camera-motions.de.ts +74 -0
- package/src/i18n/camera-motions.es.ts +86 -0
- package/src/i18n/camera-motions.fr.ts +86 -0
- package/src/i18n/camera-motions.he.ts +86 -0
- package/src/i18n/camera-motions.hi.ts +99 -0
- package/src/i18n/camera-motions.ja.ts +99 -0
- package/src/i18n/camera-motions.ko.ts +99 -0
- package/src/i18n/camera-motions.pt-BR.ts +99 -0
- package/src/i18n/camera-motions.ru.ts +99 -0
- package/src/i18n/camera-motions.zh-CN.ts +99 -0
- package/src/i18n/character-fx.ar.ts +72 -0
- package/src/i18n/character-fx.de.ts +72 -0
- package/src/i18n/character-fx.es.ts +72 -0
- package/src/i18n/character-fx.fr.ts +72 -0
- package/src/i18n/character-fx.he.ts +72 -0
- package/src/i18n/character-fx.hi.ts +72 -0
- package/src/i18n/character-fx.ja.ts +72 -0
- package/src/i18n/character-fx.ko.ts +72 -0
- package/src/i18n/character-fx.pt-BR.ts +72 -0
- package/src/i18n/character-fx.ru.ts +72 -0
- package/src/i18n/character-fx.zh-CN.ts +72 -0
- package/src/i18n/color-look.ar.ts +50 -0
- package/src/i18n/color-look.de.ts +47 -0
- package/src/i18n/color-look.es.ts +50 -0
- package/src/i18n/color-look.fr.ts +50 -0
- package/src/i18n/color-look.he.ts +49 -0
- package/src/i18n/color-look.hi.ts +52 -0
- package/src/i18n/color-look.ja.ts +54 -0
- package/src/i18n/color-look.ko.ts +54 -0
- package/src/i18n/color-look.pt-BR.ts +54 -0
- package/src/i18n/color-look.ru.ts +52 -0
- package/src/i18n/color-look.zh-CN.ts +53 -0
- package/src/i18n/composition-effects.ar.ts +26 -0
- package/src/i18n/composition-effects.de.ts +25 -0
- package/src/i18n/composition-effects.es.ts +27 -0
- package/src/i18n/composition-effects.fr.ts +25 -0
- package/src/i18n/composition-effects.he.ts +25 -0
- package/src/i18n/composition-effects.hi.ts +27 -0
- package/src/i18n/composition-effects.ja.ts +27 -0
- package/src/i18n/composition-effects.ko.ts +27 -0
- package/src/i18n/composition-effects.pt-BR.ts +25 -0
- package/src/i18n/composition-effects.ru.ts +82 -0
- package/src/i18n/composition-effects.zh-CN.ts +25 -0
- package/src/i18n/era.ar.ts +37 -0
- package/src/i18n/era.de.ts +34 -0
- package/src/i18n/era.es.ts +37 -0
- package/src/i18n/era.fr.ts +37 -0
- package/src/i18n/era.he.ts +36 -0
- package/src/i18n/era.hi.ts +39 -0
- package/src/i18n/era.ja.ts +41 -0
- package/src/i18n/era.ko.ts +39 -0
- package/src/i18n/era.pt-BR.ts +41 -0
- package/src/i18n/era.ru.ts +121 -0
- package/src/i18n/era.zh-CN.ts +39 -0
- package/src/i18n/exposure-settings.ar.ts +28 -0
- package/src/i18n/exposure-settings.de.ts +26 -0
- package/src/i18n/exposure-settings.es.ts +28 -0
- package/src/i18n/exposure-settings.fr.ts +29 -0
- package/src/i18n/exposure-settings.he.ts +28 -0
- package/src/i18n/exposure-settings.hi.ts +31 -0
- package/src/i18n/exposure-settings.ja.ts +31 -0
- package/src/i18n/exposure-settings.ko.ts +31 -0
- package/src/i18n/exposure-settings.pt-BR.ts +31 -0
- package/src/i18n/exposure-settings.ru.ts +31 -0
- package/src/i18n/exposure-settings.zh-CN.ts +31 -0
- package/src/i18n/framing.ar.ts +78 -0
- package/src/i18n/framing.de.ts +73 -0
- package/src/i18n/framing.es.ts +78 -0
- package/src/i18n/framing.fr.ts +78 -0
- package/src/i18n/framing.he.ts +77 -0
- package/src/i18n/framing.hi.ts +82 -0
- package/src/i18n/framing.ja.ts +84 -0
- package/src/i18n/framing.ko.ts +82 -0
- package/src/i18n/framing.pt-BR.ts +84 -0
- package/src/i18n/framing.ru.ts +82 -0
- package/src/i18n/framing.zh-CN.ts +82 -0
- package/src/i18n/furniture.ar.ts +92 -0
- package/src/i18n/furniture.de.ts +93 -0
- package/src/i18n/furniture.es.ts +101 -0
- package/src/i18n/furniture.fr.ts +93 -0
- package/src/i18n/furniture.he.ts +101 -0
- package/src/i18n/furniture.hi.ts +101 -0
- package/src/i18n/furniture.ja.ts +101 -0
- package/src/i18n/furniture.ko.ts +101 -0
- package/src/i18n/furniture.pt-BR.ts +101 -0
- package/src/i18n/furniture.ru.ts +101 -0
- package/src/i18n/furniture.zh-CN.ts +101 -0
- package/src/i18n/held-prop.ar.ts +74 -0
- package/src/i18n/held-prop.de.ts +65 -0
- package/src/i18n/held-prop.es.ts +83 -0
- package/src/i18n/held-prop.fr.ts +74 -0
- package/src/i18n/held-prop.he.ts +73 -0
- package/src/i18n/held-prop.hi.ts +82 -0
- package/src/i18n/held-prop.ja.ts +84 -0
- package/src/i18n/held-prop.ko.ts +84 -0
- package/src/i18n/held-prop.pt-BR.ts +84 -0
- package/src/i18n/held-prop.ru.ts +82 -0
- package/src/i18n/held-prop.zh-CN.ts +82 -0
- package/src/i18n/index.ts +208 -0
- package/src/i18n/instrumentation.ar.ts +195 -0
- package/src/i18n/instrumentation.de.ts +195 -0
- package/src/i18n/instrumentation.es.ts +195 -0
- package/src/i18n/instrumentation.fr.ts +195 -0
- package/src/i18n/instrumentation.he.ts +195 -0
- package/src/i18n/instrumentation.hi.ts +195 -0
- package/src/i18n/instrumentation.ja.ts +195 -0
- package/src/i18n/instrumentation.ko.ts +195 -0
- package/src/i18n/instrumentation.pt-BR.ts +195 -0
- package/src/i18n/instrumentation.ru.ts +195 -0
- package/src/i18n/instrumentation.zh-CN.ts +195 -0
- package/src/i18n/lens.ar.ts +24 -0
- package/src/i18n/lens.de.ts +24 -0
- package/src/i18n/lens.es.ts +24 -0
- package/src/i18n/lens.fr.ts +24 -0
- package/src/i18n/lens.he.ts +24 -0
- package/src/i18n/lens.hi.ts +24 -0
- package/src/i18n/lens.ja.ts +24 -0
- package/src/i18n/lens.ko.ts +24 -0
- package/src/i18n/lens.pt-BR.ts +24 -0
- package/src/i18n/lens.ru.ts +25 -0
- package/src/i18n/lens.zh-CN.ts +24 -0
- package/src/i18n/lighting.ar.ts +86 -0
- package/src/i18n/lighting.de.ts +84 -0
- package/src/i18n/lighting.es.ts +89 -0
- package/src/i18n/lighting.fr.ts +84 -0
- package/src/i18n/lighting.he.ts +88 -0
- package/src/i18n/lighting.hi.ts +90 -0
- package/src/i18n/lighting.ja.ts +90 -0
- package/src/i18n/lighting.ko.ts +90 -0
- package/src/i18n/lighting.pt-BR.ts +90 -0
- package/src/i18n/lighting.ru.ts +88 -0
- package/src/i18n/lighting.zh-CN.ts +92 -0
- package/src/i18n/loop-subject.ar.ts +39 -0
- package/src/i18n/loop-subject.de.ts +39 -0
- package/src/i18n/loop-subject.es.ts +39 -0
- package/src/i18n/loop-subject.fr.ts +39 -0
- package/src/i18n/loop-subject.he.ts +39 -0
- package/src/i18n/loop-subject.hi.ts +39 -0
- package/src/i18n/loop-subject.ja.ts +39 -0
- package/src/i18n/loop-subject.ko.ts +39 -0
- package/src/i18n/loop-subject.pt-BR.ts +39 -0
- package/src/i18n/loop-subject.ru.ts +39 -0
- package/src/i18n/loop-subject.zh-CN.ts +39 -0
- package/src/i18n/materials.ar.ts +80 -0
- package/src/i18n/materials.de.ts +80 -0
- package/src/i18n/materials.es.ts +87 -0
- package/src/i18n/materials.fr.ts +80 -0
- package/src/i18n/materials.he.ts +86 -0
- package/src/i18n/materials.hi.ts +86 -0
- package/src/i18n/materials.ja.ts +88 -0
- package/src/i18n/materials.ko.ts +88 -0
- package/src/i18n/materials.pt-BR.ts +88 -0
- package/src/i18n/materials.ru.ts +86 -0
- package/src/i18n/materials.zh-CN.ts +86 -0
- package/src/i18n/mood.ar.ts +61 -0
- package/src/i18n/mood.de.ts +61 -0
- package/src/i18n/mood.es.ts +66 -0
- package/src/i18n/mood.fr.ts +61 -0
- package/src/i18n/mood.he.ts +64 -0
- package/src/i18n/mood.hi.ts +66 -0
- package/src/i18n/mood.ja.ts +66 -0
- package/src/i18n/mood.ko.ts +66 -0
- package/src/i18n/mood.pt-BR.ts +64 -0
- package/src/i18n/mood.ru.ts +64 -0
- package/src/i18n/mood.zh-CN.ts +64 -0
- package/src/i18n/music-genre.ar.ts +302 -0
- package/src/i18n/music-genre.de.ts +302 -0
- package/src/i18n/music-genre.es.ts +302 -0
- package/src/i18n/music-genre.fr.ts +302 -0
- package/src/i18n/music-genre.he.ts +302 -0
- package/src/i18n/music-genre.hi.ts +302 -0
- package/src/i18n/music-genre.ja.ts +302 -0
- package/src/i18n/music-genre.ko.ts +302 -0
- package/src/i18n/music-genre.pt-BR.ts +302 -0
- package/src/i18n/music-genre.ru.ts +302 -0
- package/src/i18n/music-genre.zh-CN.ts +302 -0
- package/src/i18n/music-mood.ar.ts +75 -0
- package/src/i18n/music-mood.de.ts +75 -0
- package/src/i18n/music-mood.es.ts +75 -0
- package/src/i18n/music-mood.fr.ts +75 -0
- package/src/i18n/music-mood.he.ts +75 -0
- package/src/i18n/music-mood.hi.ts +75 -0
- package/src/i18n/music-mood.ja.ts +75 -0
- package/src/i18n/music-mood.ko.ts +75 -0
- package/src/i18n/music-mood.pt-BR.ts +75 -0
- package/src/i18n/music-mood.ru.ts +75 -0
- package/src/i18n/music-mood.zh-CN.ts +75 -0
- package/src/i18n/person.ar.ts +638 -0
- package/src/i18n/person.de.ts +629 -0
- package/src/i18n/person.es.ts +645 -0
- package/src/i18n/person.fr.ts +621 -0
- package/src/i18n/person.he.ts +656 -0
- package/src/i18n/person.hi.ts +654 -0
- package/src/i18n/person.ja.ts +662 -0
- package/src/i18n/person.ko.ts +662 -0
- package/src/i18n/person.pt-BR.ts +656 -0
- package/src/i18n/person.ru.ts +656 -0
- package/src/i18n/person.zh-CN.ts +656 -0
- package/src/i18n/photo-genre.ar.ts +58 -0
- package/src/i18n/photo-genre.de.ts +52 -0
- package/src/i18n/photo-genre.es.ts +64 -0
- package/src/i18n/photo-genre.fr.ts +58 -0
- package/src/i18n/photo-genre.he.ts +62 -0
- package/src/i18n/photo-genre.hi.ts +63 -0
- package/src/i18n/photo-genre.ja.ts +65 -0
- package/src/i18n/photo-genre.ko.ts +63 -0
- package/src/i18n/photo-genre.pt-BR.ts +65 -0
- package/src/i18n/photo-genre.ru.ts +63 -0
- package/src/i18n/photo-genre.zh-CN.ts +63 -0
- package/src/i18n/photographer.ar.ts +75 -0
- package/src/i18n/photographer.de.ts +74 -0
- package/src/i18n/photographer.es.ts +77 -0
- package/src/i18n/photographer.fr.ts +77 -0
- package/src/i18n/photographer.he.ts +78 -0
- package/src/i18n/photographer.hi.ts +80 -0
- package/src/i18n/photographer.ja.ts +84 -0
- package/src/i18n/photographer.ko.ts +84 -0
- package/src/i18n/photographer.pt-BR.ts +83 -0
- package/src/i18n/photographer.ru.ts +78 -0
- package/src/i18n/photographer.zh-CN.ts +78 -0
- package/src/i18n/pose.ar.ts +95 -0
- package/src/i18n/pose.de.ts +96 -0
- package/src/i18n/pose.es.ts +104 -0
- package/src/i18n/pose.fr.ts +96 -0
- package/src/i18n/pose.he.ts +104 -0
- package/src/i18n/pose.hi.ts +104 -0
- package/src/i18n/pose.ja.ts +104 -0
- package/src/i18n/pose.ko.ts +104 -0
- package/src/i18n/pose.pt-BR.ts +104 -0
- package/src/i18n/pose.ru.ts +104 -0
- package/src/i18n/pose.zh-CN.ts +104 -0
- package/src/i18n/post-process-effects.ar.ts +25 -0
- package/src/i18n/post-process-effects.de.ts +24 -0
- package/src/i18n/post-process-effects.es.ts +26 -0
- package/src/i18n/post-process-effects.fr.ts +24 -0
- package/src/i18n/post-process-effects.he.ts +24 -0
- package/src/i18n/post-process-effects.hi.ts +26 -0
- package/src/i18n/post-process-effects.ja.ts +26 -0
- package/src/i18n/post-process-effects.ko.ts +26 -0
- package/src/i18n/post-process-effects.pt-BR.ts +24 -0
- package/src/i18n/post-process-effects.ru.ts +24 -0
- package/src/i18n/post-process-effects.zh-CN.ts +24 -0
- package/src/i18n/render-quality.ar.ts +34 -0
- package/src/i18n/render-quality.de.ts +30 -0
- package/src/i18n/render-quality.es.ts +35 -0
- package/src/i18n/render-quality.fr.ts +34 -0
- package/src/i18n/render-quality.he.ts +33 -0
- package/src/i18n/render-quality.hi.ts +39 -0
- package/src/i18n/render-quality.ja.ts +39 -0
- package/src/i18n/render-quality.ko.ts +39 -0
- package/src/i18n/render-quality.pt-BR.ts +37 -0
- package/src/i18n/render-quality.ru.ts +37 -0
- package/src/i18n/render-quality.zh-CN.ts +37 -0
- package/src/i18n/seasons.ar.ts +10 -0
- package/src/i18n/seasons.de.ts +10 -0
- package/src/i18n/seasons.es.ts +10 -0
- package/src/i18n/seasons.fr.ts +10 -0
- package/src/i18n/seasons.he.ts +10 -0
- package/src/i18n/seasons.hi.ts +10 -0
- package/src/i18n/seasons.ja.ts +10 -0
- package/src/i18n/seasons.ko.ts +10 -0
- package/src/i18n/seasons.pt-BR.ts +10 -0
- package/src/i18n/seasons.ru.ts +10 -0
- package/src/i18n/seasons.zh-CN.ts +10 -0
- package/src/i18n/setting.ar.ts +73 -0
- package/src/i18n/setting.de.ts +73 -0
- package/src/i18n/setting.es.ts +77 -0
- package/src/i18n/setting.fr.ts +73 -0
- package/src/i18n/setting.he.ts +76 -0
- package/src/i18n/setting.hi.ts +76 -0
- package/src/i18n/setting.ja.ts +78 -0
- package/src/i18n/setting.ko.ts +76 -0
- package/src/i18n/setting.pt-BR.ts +78 -0
- package/src/i18n/setting.ru.ts +76 -0
- package/src/i18n/setting.zh-CN.ts +76 -0
- package/src/i18n/style.ar.ts +55 -0
- package/src/i18n/style.de.ts +54 -0
- package/src/i18n/style.es.ts +54 -0
- package/src/i18n/style.fr.ts +54 -0
- package/src/i18n/style.he.ts +54 -0
- package/src/i18n/style.hi.ts +54 -0
- package/src/i18n/style.ja.ts +54 -0
- package/src/i18n/style.ko.ts +54 -0
- package/src/i18n/style.pt-BR.ts +56 -0
- package/src/i18n/style.ru.ts +54 -0
- package/src/i18n/style.zh-CN.ts +54 -0
- package/src/i18n/styling.ar.ts +295 -0
- package/src/i18n/styling.de.ts +285 -0
- package/src/i18n/styling.es.ts +317 -0
- package/src/i18n/styling.fr.ts +285 -0
- package/src/i18n/styling.he.ts +307 -0
- package/src/i18n/styling.hi.ts +323 -0
- package/src/i18n/styling.ja.ts +317 -0
- package/src/i18n/styling.ko.ts +311 -0
- package/src/i18n/styling.pt-BR.ts +301 -0
- package/src/i18n/styling.ru.ts +301 -0
- package/src/i18n/styling.zh-CN.ts +307 -0
- package/src/i18n/temporal.ar.ts +31 -0
- package/src/i18n/temporal.de.ts +24 -0
- package/src/i18n/temporal.es.ts +27 -0
- package/src/i18n/temporal.fr.ts +28 -0
- package/src/i18n/temporal.he.ts +31 -0
- package/src/i18n/temporal.hi.ts +31 -0
- package/src/i18n/temporal.ja.ts +31 -0
- package/src/i18n/temporal.ko.ts +31 -0
- package/src/i18n/temporal.pt-BR.ts +31 -0
- package/src/i18n/temporal.ru.ts +31 -0
- package/src/i18n/temporal.zh-CN.ts +31 -0
- package/src/i18n/transitions.ar.ts +97 -0
- package/src/i18n/transitions.de.ts +97 -0
- package/src/i18n/transitions.es.ts +97 -0
- package/src/i18n/transitions.fr.ts +97 -0
- package/src/i18n/transitions.he.ts +97 -0
- package/src/i18n/transitions.hi.ts +97 -0
- package/src/i18n/transitions.ja.ts +97 -0
- package/src/i18n/transitions.ko.ts +97 -0
- package/src/i18n/transitions.pt-BR.ts +97 -0
- package/src/i18n/transitions.ru.ts +97 -0
- package/src/i18n/transitions.zh-CN.ts +97 -0
- package/src/i18n/types.ts +158 -0
- package/src/i18n/vehicles.ar.ts +137 -0
- package/src/i18n/vehicles.de.ts +125 -0
- package/src/i18n/vehicles.es.ts +138 -0
- package/src/i18n/vehicles.fr.ts +125 -0
- package/src/i18n/vehicles.he.ts +136 -0
- package/src/i18n/vehicles.hi.ts +138 -0
- package/src/i18n/vehicles.ja.ts +138 -0
- package/src/i18n/vehicles.ko.ts +138 -0
- package/src/i18n/vehicles.pt-BR.ts +136 -0
- package/src/i18n/vehicles.ru.ts +136 -0
- package/src/i18n/vehicles.zh-CN.ts +136 -0
- package/src/i18n/voice-character.ar.ts +126 -0
- package/src/i18n/voice-character.de.ts +126 -0
- package/src/i18n/voice-character.es.ts +126 -0
- package/src/i18n/voice-character.fr.ts +126 -0
- package/src/i18n/voice-character.he.ts +126 -0
- package/src/i18n/voice-character.hi.ts +126 -0
- package/src/i18n/voice-character.ja.ts +126 -0
- package/src/i18n/voice-character.ko.ts +126 -0
- package/src/i18n/voice-character.pt-BR.ts +126 -0
- package/src/i18n/voice-character.ru.ts +126 -0
- package/src/i18n/voice-character.zh-CN.ts +126 -0
- package/src/i18n/voice-delivery.ar.ts +77 -0
- package/src/i18n/voice-delivery.de.ts +77 -0
- package/src/i18n/voice-delivery.es.ts +77 -0
- package/src/i18n/voice-delivery.fr.ts +77 -0
- package/src/i18n/voice-delivery.he.ts +77 -0
- package/src/i18n/voice-delivery.hi.ts +77 -0
- package/src/i18n/voice-delivery.ja.ts +77 -0
- package/src/i18n/voice-delivery.ko.ts +77 -0
- package/src/i18n/voice-delivery.pt-BR.ts +77 -0
- package/src/i18n/voice-delivery.ru.ts +77 -0
- package/src/i18n/voice-delivery.zh-CN.ts +77 -0
- package/src/i18n/weapons.ar.ts +115 -0
- package/src/i18n/weapons.de.ts +114 -0
- package/src/i18n/weapons.es.ts +116 -0
- package/src/i18n/weapons.fr.ts +103 -0
- package/src/i18n/weapons.he.ts +114 -0
- package/src/i18n/weapons.hi.ts +116 -0
- package/src/i18n/weapons.ja.ts +116 -0
- package/src/i18n/weapons.ko.ts +116 -0
- package/src/i18n/weapons.pt-BR.ts +114 -0
- package/src/i18n/weapons.ru.ts +114 -0
- package/src/i18n/weapons.zh-CN.ts +114 -0
- package/src/image-critic-node.ts +61 -0
- package/src/image-critic-types.ts +40 -0
- package/src/index.ts +866 -0
- package/src/inject-upstream.ts +15 -0
- package/src/inpaint-region.ts +51 -0
- package/src/json-evaluator.ts +732 -0
- package/src/json-path.ts +52 -0
- package/src/lip-sync-pricing.ts +90 -0
- package/src/list-merge.ts +40 -0
- package/src/list-sort.ts +122 -0
- package/src/list-source-resolver.ts +50 -0
- package/src/llm-models.ts +245 -0
- package/src/location-mention-slug.ts +291 -0
- package/src/location-preset-catalog-map.ts +128 -0
- package/src/loop-delimiter.ts +73 -0
- package/src/lora-routing.ts +95 -0
- package/src/lottie-overlay-catalog.ts +175 -0
- package/src/lottie-slots.ts +309 -0
- package/src/model-catalog.ts +2386 -0
- package/src/model-constants.ts +1910 -0
- package/src/model-tree.ts +120 -0
- package/src/monetization.ts +15 -0
- package/src/multi-pick.ts +42 -0
- package/src/node-default-mappings.ts +262 -0
- package/src/node-mappable-fields.ts +70 -0
- package/src/node-preset-export.ts +56 -0
- package/src/node-preset-extract.ts +147 -0
- package/src/node-refs.ts +253 -0
- package/src/node-runtime-keys.ts +117 -0
- package/src/object-aspect-defaults.ts +72 -0
- package/src/object-picker-types.ts +22 -0
- package/src/parameter-node-value.ts +284 -0
- package/src/pinterest-url.ts +28 -0
- package/src/pipeline-chat.ts +72 -0
- package/src/pipeline-defaults.ts +318 -0
- package/src/pipeline-events.ts +162 -0
- package/src/pipeline-state-types.ts +196 -0
- package/src/pipeline-types.ts +647 -0
- package/src/pipeline-validation.ts +87 -0
- package/src/presentation-types.ts +23 -0
- package/src/presentation-utils.ts +397 -0
- package/src/producer-types.ts +188 -0
- package/src/progress-curve.ts +99 -0
- package/src/provider-directive-defaults.ts +69 -0
- package/src/reduce-strategy-registry.ts +121 -0
- package/src/reference-board-templates.ts +81 -0
- package/src/reference-roles.ts +153 -0
- package/src/reference-sheet/__tests__/board-to-column.test.ts +20 -0
- package/src/reference-sheet/__tests__/catalog.test.ts +50 -0
- package/src/reference-sheet/__tests__/cost.test.ts +38 -0
- package/src/reference-sheet/__tests__/no-drift.test.ts +28 -0
- package/src/reference-sheet/__tests__/panel-plan.test.ts +61 -0
- package/src/reference-sheet/__tests__/panel-prompts.test.ts +17 -0
- package/src/reference-sheet/__tests__/plan-generation.test.ts +72 -0
- package/src/reference-sheet/__tests__/presets.test.ts +54 -0
- package/src/reference-sheet/__tests__/types.test.ts +24 -0
- package/src/reference-sheet/catalog.ts +144 -0
- package/src/reference-sheet/cost.ts +37 -0
- package/src/reference-sheet/credit-id.ts +7 -0
- package/src/reference-sheet/index.ts +8 -0
- package/src/reference-sheet/panel-plan.ts +65 -0
- package/src/reference-sheet/panel-prompts.ts +14 -0
- package/src/reference-sheet/plan-generation.ts +79 -0
- package/src/reference-sheet/presets.ts +77 -0
- package/src/reference-sheet/types.ts +92 -0
- package/src/repeat-types.ts +97 -0
- package/src/resolve-field-mappings.ts +119 -0
- package/src/route-filter.ts +80 -0
- package/src/scene-helper-types.ts +249 -0
- package/src/scene-node-types.ts +281 -0
- package/src/scraper-actors.ts +57 -0
- package/src/scraper-output-schemas.ts +25 -0
- package/src/seasons.ts +45 -0
- package/src/selector.ts +864 -0
- package/src/settled-with-limit.ts +42 -0
- package/src/shot-element.ts +43 -0
- package/src/social-media-specs.ts +121 -0
- package/src/social-post.ts +24 -0
- package/src/sub-workflow-validation.ts +78 -0
- package/src/supported-fonts.ts +40 -0
- package/src/surround.ts +113 -0
- package/src/switchx-pricing.ts +33 -0
- package/src/text-separators.ts +59 -0
- package/src/to-connected-references.ts +77 -0
- package/src/types.ts +272 -0
- package/src/variant-job-id.ts +17 -0
- package/src/vehicles.ts +213 -0
- package/src/video-analysis-pricing.ts +74 -0
- package/src/video-analysis.ts +127 -0
- package/src/video-duration.ts +25 -0
- package/src/voice-changer-models.ts +36 -0
- package/src/voice-matcher-types.ts +37 -0
- package/src/voices.ts +92 -0
- package/src/weapons.ts +190 -0
- package/src/workflow-export.ts +153 -0
package/src/animals.ts
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical catalog of animal presets for the Object entity node.
|
|
3
|
+
*
|
|
4
|
+
* When the Object category is "animal", users pick a specific animal from this
|
|
5
|
+
* catalog. The picker auto-fills the object's `objectName` and `description`
|
|
6
|
+
* so the existing `buildObjectPrompt` pipeline just works — no backend prompt
|
|
7
|
+
* changes needed.
|
|
8
|
+
*
|
|
9
|
+
* Organized into everyday sub-categories: cats, dogs, transport animals (the
|
|
10
|
+
* rideable / working ones like horse + camel + donkey), farm, wild, birds,
|
|
11
|
+
* sea, small pets, reptiles, and mythical.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export type AnimalSubcategory =
|
|
15
|
+
| "cats"
|
|
16
|
+
| "dogs"
|
|
17
|
+
| "transport"
|
|
18
|
+
| "farm"
|
|
19
|
+
| "wild"
|
|
20
|
+
| "birds"
|
|
21
|
+
| "sea"
|
|
22
|
+
| "small-pets"
|
|
23
|
+
| "reptiles"
|
|
24
|
+
| "insects"
|
|
25
|
+
| "dinosaurs"
|
|
26
|
+
| "mythical"
|
|
27
|
+
|
|
28
|
+
export interface Animal {
|
|
29
|
+
readonly id: string
|
|
30
|
+
readonly label: string
|
|
31
|
+
readonly subcategory: AnimalSubcategory
|
|
32
|
+
readonly description: string
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const ANIMALS: ReadonlyArray<Animal> = [
|
|
36
|
+
// -------------------- Cats --------------------
|
|
37
|
+
{ id: "cat-persian", label: "Persian Cat", subcategory: "cats", description: "Long-haired cat with a flat face, stocky build and luxurious fluffy coat" },
|
|
38
|
+
{ id: "cat-siamese", label: "Siamese Cat", subcategory: "cats", description: "Sleek short-haired cat with a cream body, dark points on face, ears, paws and tail, and piercing blue almond-shaped eyes" },
|
|
39
|
+
{ id: "cat-maine-coon", label: "Maine Coon", subcategory: "cats", description: "Very large long-haired cat with a shaggy ruff, tufted ears and a bushy ringed tail" },
|
|
40
|
+
{ id: "cat-bengal", label: "Bengal Cat", subcategory: "cats", description: "Muscular athletic cat with a sleek leopard-like rosetted coat in gold and brown" },
|
|
41
|
+
{ id: "cat-sphynx", label: "Sphynx Cat", subcategory: "cats", description: "Hairless wrinkled cat with large bat-like ears, prominent cheekbones and an elegant muscular frame" },
|
|
42
|
+
{ id: "cat-ragdoll", label: "Ragdoll Cat", subcategory: "cats", description: "Large semi-long-haired cat with a soft silky coat, color points and vivid blue eyes" },
|
|
43
|
+
{ id: "cat-british-shorthair",label: "British Shorthair", subcategory: "cats", description: "Plush round-faced cat with a dense blue-grey coat, chubby cheeks and copper eyes" },
|
|
44
|
+
{ id: "cat-scottish-fold", label: "Scottish Fold", subcategory: "cats", description: "Round-faced cat with small folded ears, a stocky body and big round owl-like eyes" },
|
|
45
|
+
{ id: "cat-tabby", label: "Tabby Cat", subcategory: "cats", description: "Classic striped short-haired cat with an M mark on the forehead and alert green eyes" },
|
|
46
|
+
{ id: "cat-black", label: "Black Cat", subcategory: "cats", description: "Sleek all-black short-haired cat with bright yellow-green eyes and a glossy coat" },
|
|
47
|
+
|
|
48
|
+
// -------------------- Dogs --------------------
|
|
49
|
+
{ id: "dog-labrador", label: "Labrador Retriever", subcategory: "dogs", description: "Friendly medium-large sporting dog with a short dense coat in yellow, black or chocolate and a thick otter tail" },
|
|
50
|
+
{ id: "dog-golden-retriever", label: "Golden Retriever", subcategory: "dogs", description: "Medium-large dog with a luxurious wavy golden coat, feathered tail and a warm friendly face" },
|
|
51
|
+
{ id: "dog-german-shepherd", label: "German Shepherd", subcategory: "dogs", description: "Strong alert working dog with a tan and black saddle coat, erect ears and a bushy tail" },
|
|
52
|
+
{ id: "dog-bulldog", label: "Bulldog", subcategory: "dogs", description: "Stocky muscular short-haired dog with a wrinkled flat face, wide jaw and loose jowls" },
|
|
53
|
+
{ id: "dog-poodle", label: "Poodle", subcategory: "dogs", description: "Elegant curly-coated dog with a proud posture and a classic groomed silhouette" },
|
|
54
|
+
{ id: "dog-husky", label: "Siberian Husky", subcategory: "dogs", description: "Thick double-coated dog with black and white markings, piercing blue or bi-colored eyes and erect triangular ears" },
|
|
55
|
+
{ id: "dog-beagle", label: "Beagle", subcategory: "dogs", description: "Small tri-color hound with long floppy ears, a short coat and a white-tipped tail" },
|
|
56
|
+
{ id: "dog-dachshund", label: "Dachshund", subcategory: "dogs", description: "Long low-slung dog with short legs, a deep chest and long drooping ears" },
|
|
57
|
+
{ id: "dog-chihuahua", label: "Chihuahua", subcategory: "dogs", description: "Tiny toy dog with an apple-shaped head, huge upright ears and big alert eyes" },
|
|
58
|
+
{ id: "dog-corgi", label: "Corgi", subcategory: "dogs", description: "Short-legged herding dog with a fox-like face, huge upright ears and a plush double coat in red and white" },
|
|
59
|
+
{ id: "dog-pug", label: "Pug", subcategory: "dogs", description: "Small stocky dog with a deeply wrinkled flat face, curly tail and a fawn coat with a black mask" },
|
|
60
|
+
{ id: "dog-border-collie", label: "Border Collie", subcategory: "dogs", description: "Agile medium-sized herding dog with a black and white coat, intense stare and feathered tail" },
|
|
61
|
+
{ id: "dog-rottweiler", label: "Rottweiler", subcategory: "dogs", description: "Powerful muscular dog with a short glossy black coat and distinctive mahogany markings on face, chest and legs" },
|
|
62
|
+
{ id: "dog-shiba-inu", label: "Shiba Inu", subcategory: "dogs", description: "Compact spitz-type dog with a red-orange coat, curled tail, erect triangular ears and a fox-like face" },
|
|
63
|
+
|
|
64
|
+
// -------------------- Transport / Working --------------------
|
|
65
|
+
{ id: "horse", label: "Horse", subcategory: "transport", description: "Strong graceful horse with flowing mane and tail, sturdy hooves and a muscular frame" },
|
|
66
|
+
{ id: "camel", label: "Camel", subcategory: "transport", description: "Desert camel with a tall humped back, long legs, wide padded feet and a serene face" },
|
|
67
|
+
{ id: "donkey", label: "Donkey", subcategory: "transport", description: "Small sturdy donkey with long ears, a short upright mane and a gentle face" },
|
|
68
|
+
{ id: "mule", label: "Mule", subcategory: "transport", description: "Hardy pack mule with long ears, a short dark mane and a compact muscular frame" },
|
|
69
|
+
{ id: "ox", label: "Ox", subcategory: "transport", description: "Massive working ox with broad shoulders, curved horns and a patient stoic face" },
|
|
70
|
+
|
|
71
|
+
// -------------------- Farm --------------------
|
|
72
|
+
{ id: "cow", label: "Cow", subcategory: "farm", description: "Dairy cow with a white and black patched hide, large udder and gentle brown eyes" },
|
|
73
|
+
{ id: "pig", label: "Pig", subcategory: "farm", description: "Stout pink farm pig with a curled tail, round snout and upright ears" },
|
|
74
|
+
{ id: "sheep", label: "Sheep", subcategory: "farm", description: "Fluffy woolly sheep with a thick cream fleece, dark face and short legs" },
|
|
75
|
+
{ id: "goat", label: "Goat", subcategory: "farm", description: "Nimble goat with a shaggy coat, curved horns, a tuft of beard and rectangular pupils" },
|
|
76
|
+
{ id: "chicken", label: "Chicken", subcategory: "farm", description: "Classic farm chicken with a red comb and wattles, feathered body and alert side-tilted head" },
|
|
77
|
+
{ id: "rooster", label: "Rooster", subcategory: "farm", description: "Proud rooster with a tall red comb, iridescent green-and-copper feathers and long arched tail plumes" },
|
|
78
|
+
{ id: "duck", label: "Duck", subcategory: "farm", description: "White-and-brown farm duck with an orange bill, webbed feet and a rounded rump" },
|
|
79
|
+
{ id: "rabbit", label: "Rabbit", subcategory: "farm", description: "Fluffy rabbit with long upright ears, a twitching nose and a cotton-ball tail" },
|
|
80
|
+
{ id: "turkey", label: "Turkey", subcategory: "farm", description: "Large turkey with a fan of dark iridescent tail feathers, a bare red head and a dangling snood" },
|
|
81
|
+
|
|
82
|
+
// -------------------- Wild --------------------
|
|
83
|
+
{ id: "lion", label: "Lion", subcategory: "wild", description: "Powerful male lion with a thick golden mane framing a wide tawny face and a muscular frame" },
|
|
84
|
+
{ id: "tiger", label: "Tiger", subcategory: "wild", description: "Massive tiger with striking orange fur, bold black stripes and intense amber eyes" },
|
|
85
|
+
{ id: "bear", label: "Bear", subcategory: "wild", description: "Large brown bear with thick shaggy fur, a broad head, round ears and powerful clawed paws" },
|
|
86
|
+
{ id: "polar-bear", label: "Polar Bear", subcategory: "wild", description: "Massive arctic bear with thick cream-white fur, a long neck, black nose and huge padded paws" },
|
|
87
|
+
{ id: "wolf", label: "Wolf", subcategory: "wild", description: "Lean grey wolf with a thick double coat, upright ears, piercing yellow eyes and a bushy tail" },
|
|
88
|
+
{ id: "fox", label: "Fox", subcategory: "wild", description: "Slender red fox with a sharp pointed muzzle, upright ears and a long white-tipped bushy tail" },
|
|
89
|
+
{ id: "elephant", label: "Elephant", subcategory: "wild", description: "Massive elephant with a wrinkled grey hide, long trunk, wide flapping ears and curved ivory tusks" },
|
|
90
|
+
{ id: "zebra", label: "Zebra", subcategory: "wild", description: "Sturdy horse-like zebra with bold black and white stripes, a short upright mane and large dark eyes" },
|
|
91
|
+
{ id: "giraffe", label: "Giraffe", subcategory: "wild", description: "Tall graceful giraffe with an impossibly long neck, a golden patchwork coat and small ossicone horns" },
|
|
92
|
+
{ id: "panda", label: "Giant Panda", subcategory: "wild", description: "Roly-poly panda with a black-and-white coat, round ears, distinctive black eye patches and a gentle face" },
|
|
93
|
+
{ id: "leopard", label: "Leopard", subcategory: "wild", description: "Sleek spotted leopard with a tawny coat covered in rosettes, muscular shoulders and piercing pale eyes" },
|
|
94
|
+
{ id: "cheetah", label: "Cheetah", subcategory: "wild", description: "Slim fast-running cheetah with a golden coat of solid black spots and tear-track lines down the face" },
|
|
95
|
+
{ id: "monkey", label: "Monkey", subcategory: "wild", description: "Agile long-tailed monkey with expressive brown eyes, slender limbs and a soft brown-and-cream coat" },
|
|
96
|
+
{ id: "gorilla", label: "Gorilla", subcategory: "wild", description: "Massive silverback gorilla with broad shoulders, a prominent brow ridge and thick black fur" },
|
|
97
|
+
{ id: "kangaroo", label: "Kangaroo", subcategory: "wild", description: "Tall kangaroo with powerful hind legs, a thick muscular tail, small front paws and upright alert ears" },
|
|
98
|
+
{ id: "koala", label: "Koala", subcategory: "wild", description: "Fluffy grey marsupial with a round head, large fuzzy ears, a big black nose and a soft fluffy chest" },
|
|
99
|
+
{ id: "deer", label: "Deer", subcategory: "wild", description: "Graceful deer with a reddish-brown coat, slender legs, white throat patch and — on a stag — branched antlers" },
|
|
100
|
+
{ id: "raccoon", label: "Raccoon", subcategory: "wild", description: "Masked raccoon with a grey coat, a dark bandit mask across the eyes and a bushy ringed tail" },
|
|
101
|
+
{ id: "capybara", label: "Capybara", subcategory: "wild", description: "Large peaceful South American rodent with a barrel-shaped body, blunt muzzle and calm expression, often photographed soaking in a hot spring with citrus floating around it" },
|
|
102
|
+
{ id: "sloth", label: "Sloth", subcategory: "wild", description: "Slow-moving tree-dwelling mammal with shaggy fur, long curved claws and a permanent gentle smile, often hanging upside-down from a branch" },
|
|
103
|
+
{ id: "red-panda", label: "Red Panda", subcategory: "wild", description: "Small fox-faced bamboo eater with rich reddish-brown fur, white facial markings, ringed tail and tufted upright ears, distinct from the giant panda" },
|
|
104
|
+
{ id: "pangolin", label: "Pangolin", subcategory: "wild", description: "Scaly armored anteater, distinctive overlapping plates" },
|
|
105
|
+
{ id: "okapi", label: "Okapi", subcategory: "wild", description: "Forest giraffe with zebra-striped legs" },
|
|
106
|
+
{ id: "quokka", label: "Quokka", subcategory: "wild", description: "Smiling Australian marsupial, internet-famous selfie animal" },
|
|
107
|
+
{ id: "meerkat", label: "Meerkat", subcategory: "wild", description: "Standing African mongoose, sentinel posture" },
|
|
108
|
+
|
|
109
|
+
// -------------------- Birds --------------------
|
|
110
|
+
{ id: "eagle", label: "Eagle", subcategory: "birds", description: "Majestic eagle with a dark brown body, white head and tail, curved yellow beak and sharp talons" },
|
|
111
|
+
{ id: "owl", label: "Owl", subcategory: "birds", description: "Round-faced owl with a mottled brown-and-white plumage, huge forward-facing yellow eyes and feathered ear tufts" },
|
|
112
|
+
{ id: "parrot", label: "Parrot", subcategory: "birds", description: "Vibrant tropical parrot with saturated red, green, yellow and blue plumage and a hooked beak" },
|
|
113
|
+
{ id: "peacock", label: "Peacock", subcategory: "birds", description: "Iridescent blue peacock with an enormous fanned tail of shimmering eye-patterned feathers" },
|
|
114
|
+
{ id: "flamingo", label: "Flamingo", subcategory: "birds", description: "Tall slender flamingo with bright pink plumage, a long curved neck and a bent beak dipping toward the water" },
|
|
115
|
+
{ id: "penguin", label: "Penguin", subcategory: "birds", description: "Upright tuxedoed penguin with a black back, white belly and small flipper-like wings" },
|
|
116
|
+
{ id: "swan", label: "Swan", subcategory: "birds", description: "Elegant white swan with a long curved neck, orange beak and delicately folded wings" },
|
|
117
|
+
{ id: "sparrow", label: "Sparrow", subcategory: "birds", description: "Small brown-and-grey sparrow with a streaked back, tidy round body and alert black eye" },
|
|
118
|
+
{ id: "crow", label: "Crow", subcategory: "birds", description: "Glossy all-black crow with a thick straight beak, intelligent dark eyes and sleek iridescent feathers" },
|
|
119
|
+
{ id: "hummingbird", label: "Hummingbird", subcategory: "birds", description: "Tiny jewel-toned hummingbird with iridescent emerald and ruby plumage and a long needle-like beak" },
|
|
120
|
+
{ id: "raven", label: "Raven", subcategory: "birds", description: "Large glossy all-black raven with a heavy wedge-shaped beak, shaggy throat hackles and an intelligent piercing gaze, often perched in a cinematic mysterious mood" },
|
|
121
|
+
{ id: "emu", label: "Emu", subcategory: "birds", description: "Large flightless Australian ratite bird" },
|
|
122
|
+
|
|
123
|
+
// -------------------- Sea --------------------
|
|
124
|
+
{ id: "dolphin", label: "Dolphin", subcategory: "sea", description: "Sleek grey dolphin with a playful smiling face, curved dorsal fin and powerful tail flukes" },
|
|
125
|
+
{ id: "whale", label: "Whale", subcategory: "sea", description: "Massive humpback whale with a dark blue-grey body, long pectoral fins and barnacled knobby head" },
|
|
126
|
+
{ id: "shark", label: "Shark", subcategory: "sea", description: "Powerful great white shark with a torpedo-shaped grey body, white underside and rows of sharp teeth" },
|
|
127
|
+
{ id: "octopus", label: "Octopus", subcategory: "sea", description: "Curious octopus with a bulbous head, large intelligent eyes and eight long suckered arms" },
|
|
128
|
+
{ id: "sea-turtle", label: "Sea Turtle", subcategory: "sea", description: "Graceful sea turtle with a patterned green-and-brown shell, flipper-like limbs and a wise wrinkled face" },
|
|
129
|
+
{ id: "jellyfish", label: "Jellyfish", subcategory: "sea", description: "Translucent jellyfish with a glowing bell-shaped body and long trailing filamentous tentacles" },
|
|
130
|
+
{ id: "crab", label: "Crab", subcategory: "sea", description: "Red-shelled crab with a wide armored carapace, large pincer claws and skittering side-stepping legs" },
|
|
131
|
+
{ id: "seahorse", label: "Seahorse", subcategory: "sea", description: "Tiny seahorse with a curled prehensile tail, horse-like head and delicate dorsal fin" },
|
|
132
|
+
{ id: "axolotl", label: "Axolotl", subcategory: "sea", description: "Pink-fleshed aquatic salamander with feathery external gills fanning out from the head, tiny clawed limbs and a distinctive smiling face" },
|
|
133
|
+
|
|
134
|
+
// -------------------- Small Pets --------------------
|
|
135
|
+
{ id: "hamster", label: "Hamster", subcategory: "small-pets", description: "Round fluffy hamster with chubby cheek pouches, tiny paws and bright black bead eyes" },
|
|
136
|
+
{ id: "guinea-pig", label: "Guinea Pig", subcategory: "small-pets", description: "Plump guinea pig with a soft tri-color coat, no visible tail and a sweet alert face" },
|
|
137
|
+
{ id: "ferret", label: "Ferret", subcategory: "small-pets", description: "Sleek long-bodied ferret with a cream-and-sable coat, a dark bandit mask and a playful posture" },
|
|
138
|
+
{ id: "parakeet", label: "Parakeet", subcategory: "small-pets", description: "Small bright green-and-yellow parakeet with a striped head, dark eye spots and a long tapered tail" },
|
|
139
|
+
{ id: "gerbil", label: "Gerbil", subcategory: "small-pets", description: "Slender sandy-brown gerbil with large dark eyes, upright ears and a long tufted tail" },
|
|
140
|
+
|
|
141
|
+
// -------------------- Reptiles --------------------
|
|
142
|
+
{ id: "snake", label: "Snake", subcategory: "reptiles", description: "Coiled snake with a smooth scaled body, diamond-patterned skin, slit pupils and a flickering forked tongue" },
|
|
143
|
+
{ id: "lizard", label: "Lizard", subcategory: "reptiles", description: "Agile lizard with a slender scaled body, long whip-like tail, clawed feet and keen side-facing eyes" },
|
|
144
|
+
{ id: "turtle", label: "Turtle", subcategory: "reptiles", description: "Friendly land turtle with a domed patterned shell, stout scaly legs and a wise wrinkled face" },
|
|
145
|
+
{ id: "crocodile", label: "Crocodile", subcategory: "reptiles", description: "Massive crocodile with armored olive-green scales, a long toothy snout and powerful clawed limbs" },
|
|
146
|
+
{ id: "chameleon", label: "Chameleon", subcategory: "reptiles", description: "Color-shifting chameleon with a tall casqued head, independently swiveling eyes and a tightly curled prehensile tail" },
|
|
147
|
+
{ id: "gecko", label: "Gecko", subcategory: "reptiles", description: "Small gecko with a plump spotted body, large lidless eyes and wide sticky toe pads" },
|
|
148
|
+
|
|
149
|
+
// -------------------- Insects --------------------
|
|
150
|
+
{ id: "butterfly", label: "Butterfly", subcategory: "insects", description: "Delicate butterfly with wide patterned wings in vivid colors, a slender body and long antennae" },
|
|
151
|
+
{ id: "bee", label: "Bee", subcategory: "insects", description: "Fuzzy honey bee with yellow and black stripes, translucent wings and pollen-dusted legs" },
|
|
152
|
+
{ id: "ant", label: "Ant", subcategory: "insects", description: "Busy ant with a segmented dark body, six thin legs, bent antennae and strong mandibles" },
|
|
153
|
+
{ id: "spider", label: "Spider", subcategory: "insects", description: "Eight-legged spider with a bulbous abdomen, clustered dark eyes and fine hairs across its body" },
|
|
154
|
+
{ id: "ladybug", label: "Ladybug", subcategory: "insects", description: "Tiny red ladybug with a glossy rounded shell, bold black spots and delicate legs peeking out" },
|
|
155
|
+
{ id: "dragonfly", label: "Dragonfly", subcategory: "insects", description: "Slender dragonfly with iridescent blue-green body, huge faceted eyes and four long transparent wings" },
|
|
156
|
+
{ id: "beetle", label: "Beetle", subcategory: "insects", description: "Armored beetle with a glossy hard shell, ridged wing covers, sturdy legs and short antennae" },
|
|
157
|
+
{ id: "grasshopper", label: "Grasshopper", subcategory: "insects", description: "Green grasshopper with long powerful hind legs, folded wings along its back and long whip-like antennae" },
|
|
158
|
+
{ id: "praying-mantis", label: "Praying Mantis", subcategory: "insects", description: "Elongated praying mantis with a triangular head, large compound eyes and spiked raptorial forelegs held in a prayer pose" },
|
|
159
|
+
{ id: "mosquito", label: "Mosquito", subcategory: "insects", description: "Slender mosquito with long thin legs, narrow transparent wings and a needle-like proboscis" },
|
|
160
|
+
{ id: "scorpion", label: "Scorpion", subcategory: "insects", description: "Desert scorpion with armored segments, large pincer claws and a curled stinger-tipped tail raised over its back" },
|
|
161
|
+
{ id: "caterpillar", label: "Caterpillar", subcategory: "insects", description: "Plump segmented caterpillar with soft tufts, tiny legs and a cheerful munching posture on a green leaf" },
|
|
162
|
+
{ id: "tarantula", label: "Tarantula", subcategory: "insects", description: "Large hairy hunting spider" },
|
|
163
|
+
|
|
164
|
+
// -------------------- Dinosaurs --------------------
|
|
165
|
+
{ id: "t-rex", label: "Tyrannosaurus Rex", subcategory: "dinosaurs", description: "Massive T-Rex with powerful hind legs, tiny clawed arms, a huge jaw full of dagger teeth and thick scaly hide" },
|
|
166
|
+
{ id: "velociraptor", label: "Velociraptor", subcategory: "dinosaurs", description: "Lean feathered velociraptor with sickle claws, a long stiff tail and a predatory forward-lean posture" },
|
|
167
|
+
{ id: "triceratops", label: "Triceratops", subcategory: "dinosaurs", description: "Armored triceratops with a large bony frill, three sharp horns on its face and a heavy four-legged stance" },
|
|
168
|
+
{ id: "brachiosaurus", label: "Brachiosaurus", subcategory: "dinosaurs", description: "Towering brachiosaurus with an impossibly long neck reaching into treetops, a small head and pillar-like legs" },
|
|
169
|
+
{ id: "stegosaurus", label: "Stegosaurus", subcategory: "dinosaurs", description: "Hulking stegosaurus with two rows of tall diamond-shaped plates along its back and a spiked tail" },
|
|
170
|
+
{ id: "pterodactyl", label: "Pterodactyl", subcategory: "dinosaurs", description: "Flying pterodactyl with vast leathery wings, a long toothed beak and a swept-back head crest" },
|
|
171
|
+
{ id: "spinosaurus", label: "Spinosaurus", subcategory: "dinosaurs", description: "Predatory spinosaurus with a tall sail fin down its back, a long crocodile-like snout and powerful clawed arms" },
|
|
172
|
+
{ id: "diplodocus", label: "Diplodocus", subcategory: "dinosaurs", description: "Enormous long-bodied diplodocus with a whip-thin tail balancing an equally long neck, peg-like teeth and sturdy legs" },
|
|
173
|
+
{ id: "ankylosaurus", label: "Ankylosaurus", subcategory: "dinosaurs", description: "Tank-like ankylosaurus covered in thick armored plates and spikes, with a massive bony club at the end of its tail" },
|
|
174
|
+
{ id: "brontosaurus", label: "Brontosaurus", subcategory: "dinosaurs", description: "Gentle giant brontosaurus with a long sweeping neck, a small head, a thick body and a tapering whip tail" },
|
|
175
|
+
{ id: "parasaurolophus", label: "Parasaurolophus", subcategory: "dinosaurs", description: "Duck-billed parasaurolophus with a long curved tubular crest sweeping back from its head and a slender bipedal body" },
|
|
176
|
+
{ id: "allosaurus", label: "Allosaurus", subcategory: "dinosaurs", description: "Fierce allosaurus predator with a large head, small brow horns, serrated teeth and powerful grasping arms" },
|
|
177
|
+
|
|
178
|
+
// -------------------- Mythical --------------------
|
|
179
|
+
{ id: "dragon", label: "Dragon", subcategory: "mythical", description: "Towering dragon with leathery wings, ridged scales, curved horns, glowing eyes and smoke curling from its nostrils" },
|
|
180
|
+
{ id: "unicorn", label: "Unicorn", subcategory: "mythical", description: "Pure white unicorn with a flowing pastel mane and tail and a single spiraling pearlescent horn on its forehead" },
|
|
181
|
+
{ id: "phoenix", label: "Phoenix", subcategory: "mythical", description: "Majestic phoenix with fiery red, orange and gold plumage, long trailing tail feathers and flames licking its wingtips" },
|
|
182
|
+
{ id: "griffin", label: "Griffin", subcategory: "mythical", description: "Hybrid griffin with the head, wings and taloned front legs of an eagle and the muscular hind body of a lion" },
|
|
183
|
+
{ id: "pegasus", label: "Pegasus", subcategory: "mythical", description: "Pure white winged horse with feathered wings, a flowing mane and an otherworldly presence" },
|
|
184
|
+
{ id: "kraken", label: "Kraken", subcategory: "mythical", description: "Colossal sea-beast kraken with a massive head, glowing eyes and enormous suckered tentacles writhing from the deep" },
|
|
185
|
+
] as const
|
|
186
|
+
|
|
187
|
+
const animalById = new Map<string, Animal>(ANIMALS.map((a) => [a.id, a]))
|
|
188
|
+
|
|
189
|
+
export function getAnimal(id: string | undefined | null): Animal | undefined {
|
|
190
|
+
if (!id) return undefined
|
|
191
|
+
return animalById.get(id)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export function getAnimalLabel(id: string | undefined | null, fallback?: string): string {
|
|
195
|
+
const a = getAnimal(id)
|
|
196
|
+
if (a) return a.label
|
|
197
|
+
if (fallback !== undefined) return fallback
|
|
198
|
+
return (id ?? "").replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const ANIMAL_IDS: ReadonlyArray<string> = ANIMALS.map((a) => a.id)
|
|
202
|
+
|
|
203
|
+
export const ANIMAL_SUBCATEGORY_LABELS: Readonly<Record<AnimalSubcategory, string>> = {
|
|
204
|
+
cats: "Cats",
|
|
205
|
+
dogs: "Dogs",
|
|
206
|
+
transport: "Transport & Working",
|
|
207
|
+
farm: "Farm",
|
|
208
|
+
wild: "Wild",
|
|
209
|
+
birds: "Birds",
|
|
210
|
+
sea: "Sea Life",
|
|
211
|
+
"small-pets": "Small Pets",
|
|
212
|
+
reptiles: "Reptiles",
|
|
213
|
+
insects: "Insects",
|
|
214
|
+
dinosaurs: "Dinosaurs",
|
|
215
|
+
mythical: "Mythical",
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export const ANIMAL_SUBCATEGORY_ORDER: ReadonlyArray<AnimalSubcategory> = [
|
|
219
|
+
"cats",
|
|
220
|
+
"dogs",
|
|
221
|
+
"transport",
|
|
222
|
+
"farm",
|
|
223
|
+
"wild",
|
|
224
|
+
"birds",
|
|
225
|
+
"sea",
|
|
226
|
+
"small-pets",
|
|
227
|
+
"reptiles",
|
|
228
|
+
"insects",
|
|
229
|
+
"dinosaurs",
|
|
230
|
+
"mythical",
|
|
231
|
+
]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated subset of FFmpeg `acrossfade=curve=...` options for combine-videos
|
|
3
|
+
* audio crossfades. We expose 5 well-understood presets out of the ~21 raw
|
|
4
|
+
* curves FFmpeg supports; the rest are either visually indistinguishable to
|
|
5
|
+
* non-audio-engineers or rarely useful in this context.
|
|
6
|
+
*
|
|
7
|
+
* Default `linear` matches today's behavior — adding this catalog is a pure
|
|
8
|
+
* additive change for existing workflows.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export interface AudioCrossfadeCurve {
|
|
12
|
+
readonly id: string
|
|
13
|
+
/** FFmpeg `acrossfade=curve=...` name. */
|
|
14
|
+
readonly ffmpeg: string
|
|
15
|
+
readonly label: string
|
|
16
|
+
readonly description: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const AUDIO_CROSSFADE_CURVES: readonly AudioCrossfadeCurve[] = [
|
|
20
|
+
{
|
|
21
|
+
id: "linear",
|
|
22
|
+
ffmpeg: "tri",
|
|
23
|
+
label: "Linear",
|
|
24
|
+
description: "Straight-line fade. Default; predictable but can dip in the middle for music.",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "equal-power",
|
|
28
|
+
ffmpeg: "qsin",
|
|
29
|
+
label: "Equal Power",
|
|
30
|
+
description: "Quarter-sine. Keeps perceived loudness roughly constant across the crossfade — best for music.",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "smooth",
|
|
34
|
+
ffmpeg: "hsin",
|
|
35
|
+
label: "Smooth (Sine)",
|
|
36
|
+
description: "Half-sine. Gentler than equal-power; good for dialogue and ambient.",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: "logarithmic",
|
|
40
|
+
ffmpeg: "log",
|
|
41
|
+
label: "Logarithmic",
|
|
42
|
+
description: "Compensates for the ear's logarithmic loudness response. Long, slow tails.",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
id: "exponential",
|
|
46
|
+
ffmpeg: "exp",
|
|
47
|
+
label: "Exponential",
|
|
48
|
+
description: "Sharp out / slow in (or vice versa). Punchy — good for impact moments.",
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
export const AUDIO_CROSSFADE_CURVE_IDS: readonly string[] =
|
|
53
|
+
AUDIO_CROSSFADE_CURVES.map((c) => c.id)
|
|
54
|
+
|
|
55
|
+
export const DEFAULT_AUDIO_CROSSFADE_CURVE_ID = "linear"
|
|
56
|
+
|
|
57
|
+
const CURVES_BY_ID: ReadonlyMap<string, AudioCrossfadeCurve> = new Map(
|
|
58
|
+
AUDIO_CROSSFADE_CURVES.map((c) => [c.id, c]),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
export function getAudioCrossfadeCurve(id: string): AudioCrossfadeCurve | undefined {
|
|
62
|
+
return CURVES_BY_ID.get(id)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a curve id to its FFmpeg `acrossfade=curve=` name. Unknown ids fall
|
|
67
|
+
* back to `tri` (linear) — this matches the route's Zod default so callers
|
|
68
|
+
* downstream of validation never see undefined.
|
|
69
|
+
*/
|
|
70
|
+
export function resolveAudioCrossfadeCurve(id: string | undefined): string {
|
|
71
|
+
if (!id) return "tri"
|
|
72
|
+
return CURVES_BY_ID.get(id)?.ffmpeg ?? "tri"
|
|
73
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audio FX node — preset id union (single source of truth).
|
|
3
|
+
*
|
|
4
|
+
* Shared so the backend Zod route enum, the frontend config dropdown, and the
|
|
5
|
+
* `AudioFxData` node type can't drift. The per-preset FFmpeg filter chains
|
|
6
|
+
* (IR DUR/SHAPE, delay/EQ knobs) live in the backend provider's PRESET_CHAINS
|
|
7
|
+
* map — this file only fixes the id set + their human labels.
|
|
8
|
+
*
|
|
9
|
+
* Reverb presets are named by ON-SCREEN SCENARIO (where the voice is happening
|
|
10
|
+
* in the scene) rather than abstract size, so a creator picking "Church" or
|
|
11
|
+
* "Car" gets a believable space for that shot.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
export const AUDIO_FX_PRESETS = [
|
|
15
|
+
// — reverb / spaces (afir + inline-synth IR), ordered small → large —
|
|
16
|
+
"room", // ordinary indoor room — bedroom / office dialogue
|
|
17
|
+
"bathroom", // small, bright, tiled — hard early reflections
|
|
18
|
+
"car", // tight, very damped cabin
|
|
19
|
+
"hall", // lobby / corridor / large room
|
|
20
|
+
"concert-hall", // big, lush, musical tail
|
|
21
|
+
"church", // cathedral — long, dark, reverberant
|
|
22
|
+
"cave", // dark, diffuse, long
|
|
23
|
+
"arena", // stadium / PA — huge, bright tail
|
|
24
|
+
"outdoor", // open air — almost dry, faint early reflections
|
|
25
|
+
// — character / non-reverb —
|
|
26
|
+
"telephone", // band-limited phone line
|
|
27
|
+
"megaphone", // PA / bullhorn — mid-forward + light grit
|
|
28
|
+
"echo", // discrete echo / slap-back
|
|
29
|
+
"custom", // manual: reverb wet · delay · EQ
|
|
30
|
+
] as const
|
|
31
|
+
|
|
32
|
+
export type AudioFxPreset = (typeof AUDIO_FX_PRESETS)[number]
|
|
33
|
+
|
|
34
|
+
export const AUDIO_FX_PRESET_SET: ReadonlySet<string> = new Set(AUDIO_FX_PRESETS)
|
|
35
|
+
|
|
36
|
+
/** Display labels for the config dropdown. */
|
|
37
|
+
export const AUDIO_FX_PRESET_LABELS: Record<AudioFxPreset, string> = {
|
|
38
|
+
room: "Room (indoor)",
|
|
39
|
+
bathroom: "Bathroom",
|
|
40
|
+
car: "Car interior",
|
|
41
|
+
hall: "Hall / Lobby",
|
|
42
|
+
"concert-hall": "Concert Hall",
|
|
43
|
+
church: "Church",
|
|
44
|
+
cave: "Cave",
|
|
45
|
+
arena: "Arena / Stadium",
|
|
46
|
+
outdoor: "Outdoor (open air)",
|
|
47
|
+
telephone: "Telephone",
|
|
48
|
+
megaphone: "Megaphone / PA",
|
|
49
|
+
echo: "Echo / Slap-back",
|
|
50
|
+
custom: "Custom",
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Presets that apply convolution reverb (afir + inline-synth IR). */
|
|
54
|
+
export const AUDIO_FX_REVERB_PRESETS: ReadonlySet<AudioFxPreset> = new Set<AudioFxPreset>([
|
|
55
|
+
"room",
|
|
56
|
+
"bathroom",
|
|
57
|
+
"car",
|
|
58
|
+
"hall",
|
|
59
|
+
"concert-hall",
|
|
60
|
+
"church",
|
|
61
|
+
"cave",
|
|
62
|
+
"arena",
|
|
63
|
+
"outdoor",
|
|
64
|
+
])
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared structural validators for the ai-avatar and cinematic-avatar payloads.
|
|
3
|
+
*
|
|
4
|
+
* ─── Why this exists ─────────────────────────────────────────────────────────
|
|
5
|
+
* The route Zod schemas (`aiAvatarBody` / `cinematicAvatarBody`) only protect the
|
|
6
|
+
* single-node Run path. Workflow runs, published-app runs, MCP run_workflow, and
|
|
7
|
+
* imported/crafted workflow JSON all assemble a payload in
|
|
8
|
+
* `payload-builder.ts` and forward it straight to the worker → provider →
|
|
9
|
+
* HeyGen with NO Zod parse in between. That structural gap is the root cause of
|
|
10
|
+
* the avatar edge-case findings: missing/over-count avatarLooks, reference caps,
|
|
11
|
+
* source/speech-conditional requireds, and voice-param ranges all reach HeyGen
|
|
12
|
+
* unvalidated on those paths.
|
|
13
|
+
*
|
|
14
|
+
* These validators reproduce the route Zod's invariants (minus the userId /
|
|
15
|
+
* workflow wrapper and minus the URL-host allowlist — orchestrated URLs come
|
|
16
|
+
* from trusted upstream R2 outputs). They run inside the `ai-avatar` /
|
|
17
|
+
* `cinematic-avatar` cases of `payload-builder.ts` on the ASSEMBLED payload,
|
|
18
|
+
* throwing `AvatarPayloadError` BEFORE credit reservation + enqueue. The
|
|
19
|
+
* node-executor catches the throw and deletes the orphaned pending job, so both
|
|
20
|
+
* entry points are correct-by-construction rather than relying on the route as
|
|
21
|
+
* the only gate.
|
|
22
|
+
*
|
|
23
|
+
* Keep these in sync with `backend/src/routes/ai-avatar.ts` and
|
|
24
|
+
* `backend/src/routes/cinematic-avatar.ts`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/** Thrown by the avatar payload validators on a structurally-invalid payload. */
|
|
28
|
+
export class AvatarPayloadError extends Error {
|
|
29
|
+
constructor(message: string) {
|
|
30
|
+
super(message)
|
|
31
|
+
this.name = "AvatarPayloadError"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const AI_AVATAR_SOURCES = new Set(["avatar", "image"])
|
|
36
|
+
const AI_AVATAR_ENGINES = new Set(["avatar-v", "avatar-iv"])
|
|
37
|
+
const AI_AVATAR_SPEECH_MODES = new Set(["text", "audio"])
|
|
38
|
+
const AI_AVATAR_RESOLUTIONS = new Set(["720p", "1080p", "4k"])
|
|
39
|
+
const AI_AVATAR_ASPECT_RATIOS = new Set(["16:9", "9:16"])
|
|
40
|
+
|
|
41
|
+
const AI_AVATAR_SCRIPT_MAX = 5000
|
|
42
|
+
const AI_AVATAR_VOICE_SPEED_MIN = 0.5
|
|
43
|
+
const AI_AVATAR_VOICE_SPEED_MAX = 1.5
|
|
44
|
+
const AI_AVATAR_PITCH_MIN = -50
|
|
45
|
+
const AI_AVATAR_PITCH_MAX = 50
|
|
46
|
+
const AI_AVATAR_VOLUME_MIN = 0
|
|
47
|
+
const AI_AVATAR_VOLUME_MAX = 1
|
|
48
|
+
|
|
49
|
+
function isNonEmptyString(v: unknown): v is string {
|
|
50
|
+
return typeof v === "string" && v.length > 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Validate an assembled ai-avatar payload (post-default-application).
|
|
55
|
+
* Mirrors `aiAvatarBody` (`backend/src/routes/ai-avatar.ts`): enum bounds,
|
|
56
|
+
* source/speech-conditional requireds, script length, and voice-param ranges.
|
|
57
|
+
*
|
|
58
|
+
* @throws AvatarPayloadError on any violation.
|
|
59
|
+
*/
|
|
60
|
+
export function validateAiAvatarPayload(payload: Record<string, unknown>): void {
|
|
61
|
+
const avatarSource = (payload.avatarSource as string | undefined) ?? "avatar"
|
|
62
|
+
const speechMode = (payload.speechMode as string | undefined) ?? "text"
|
|
63
|
+
const engine = (payload.engine as string | undefined) ?? "avatar-iv"
|
|
64
|
+
const resolution = (payload.resolution as string | undefined) ?? "720p"
|
|
65
|
+
const aspectRatio = (payload.aspectRatio as string | undefined) ?? "16:9"
|
|
66
|
+
|
|
67
|
+
if (!AI_AVATAR_SOURCES.has(avatarSource)) {
|
|
68
|
+
throw new AvatarPayloadError(`ai-avatar: invalid avatarSource "${avatarSource}" (expected avatar | image)`)
|
|
69
|
+
}
|
|
70
|
+
if (!AI_AVATAR_ENGINES.has(engine)) {
|
|
71
|
+
throw new AvatarPayloadError(`ai-avatar: invalid engine "${engine}" (expected avatar-v | avatar-iv)`)
|
|
72
|
+
}
|
|
73
|
+
if (!AI_AVATAR_SPEECH_MODES.has(speechMode)) {
|
|
74
|
+
throw new AvatarPayloadError(`ai-avatar: invalid speechMode "${speechMode}" (expected text | audio)`)
|
|
75
|
+
}
|
|
76
|
+
if (!AI_AVATAR_RESOLUTIONS.has(resolution)) {
|
|
77
|
+
throw new AvatarPayloadError(`ai-avatar: invalid resolution "${resolution}" (expected 720p | 1080p | 4k)`)
|
|
78
|
+
}
|
|
79
|
+
if (!AI_AVATAR_ASPECT_RATIOS.has(aspectRatio)) {
|
|
80
|
+
throw new AvatarPayloadError(`ai-avatar: invalid aspectRatio "${aspectRatio}" (expected 16:9 | 9:16)`)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Source-conditional requireds: avatar mode needs avatarId; image mode needs imageUrl.
|
|
84
|
+
if (avatarSource === "image") {
|
|
85
|
+
if (!isNonEmptyString(payload.imageUrl)) {
|
|
86
|
+
throw new AvatarPayloadError("ai-avatar: imageUrl is required when avatarSource is image")
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
if (!isNonEmptyString(payload.avatarId)) {
|
|
90
|
+
throw new AvatarPayloadError("ai-avatar: avatarId is required when avatarSource is avatar")
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Speech-conditional requireds.
|
|
95
|
+
if (speechMode === "text") {
|
|
96
|
+
if (!isNonEmptyString(payload.script)) {
|
|
97
|
+
throw new AvatarPayloadError("ai-avatar: script is required when speechMode is text")
|
|
98
|
+
}
|
|
99
|
+
if ((payload.script as string).length > AI_AVATAR_SCRIPT_MAX) {
|
|
100
|
+
throw new AvatarPayloadError(`ai-avatar: script exceeds ${AI_AVATAR_SCRIPT_MAX} characters`)
|
|
101
|
+
}
|
|
102
|
+
if (!isNonEmptyString(payload.voiceId)) {
|
|
103
|
+
throw new AvatarPayloadError("ai-avatar: voiceId is required when speechMode is text")
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
if (!isNonEmptyString(payload.audioUrl)) {
|
|
107
|
+
throw new AvatarPayloadError("ai-avatar: audioUrl is required when speechMode is audio")
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Voice-param ranges (optional fields — only checked when present).
|
|
112
|
+
assertNumberInRange(payload.voiceSpeed, AI_AVATAR_VOICE_SPEED_MIN, AI_AVATAR_VOICE_SPEED_MAX, "ai-avatar: voiceSpeed")
|
|
113
|
+
assertNumberInRange(payload.pitch, AI_AVATAR_PITCH_MIN, AI_AVATAR_PITCH_MAX, "ai-avatar: pitch")
|
|
114
|
+
assertNumberInRange(payload.volume, AI_AVATAR_VOLUME_MIN, AI_AVATAR_VOLUME_MAX, "ai-avatar: volume")
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function assertNumberInRange(v: unknown, min: number, max: number, label: string): void {
|
|
118
|
+
if (v === undefined || v === null) return
|
|
119
|
+
const n = Number(v)
|
|
120
|
+
if (!Number.isFinite(n) || n < min || n > max) {
|
|
121
|
+
throw new AvatarPayloadError(`${label} must be between ${min} and ${max} (got ${String(v)})`)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// cinematic-avatar
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
const CINEMATIC_RESOLUTIONS = new Set(["720p", "1080p"])
|
|
130
|
+
const CINEMATIC_ASPECT_RATIOS = new Set(["16:9", "9:16", "1:1"])
|
|
131
|
+
export const CINEMATIC_PROMPT_MAX = 10000
|
|
132
|
+
|
|
133
|
+
/** HeyGen combined reference caps: ≤3 videos and ≤9 images across avatar looks + references. */
|
|
134
|
+
export const CINEMATIC_MAX_REFERENCE_VIDEOS = 3
|
|
135
|
+
export const CINEMATIC_MAX_REFERENCE_IMAGES = 9
|
|
136
|
+
export const CINEMATIC_MIN_LOOKS = 1
|
|
137
|
+
export const CINEMATIC_MAX_LOOKS = 3
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Validate an assembled cinematic-avatar payload.
|
|
141
|
+
* Mirrors `cinematicAvatarBody` (`backend/src/routes/cinematic-avatar.ts`):
|
|
142
|
+
* prompt presence/length, avatarLooks count (1–3), enum bounds, and the
|
|
143
|
+
* combined reference caps (≤3 videos; avatarLooks + image refs ≤ 9).
|
|
144
|
+
*
|
|
145
|
+
* @throws AvatarPayloadError on any violation.
|
|
146
|
+
*/
|
|
147
|
+
export function validateCinematicAvatarPayload(payload: Record<string, unknown>): void {
|
|
148
|
+
const prompt = payload.prompt
|
|
149
|
+
if (!isNonEmptyString(prompt)) {
|
|
150
|
+
throw new AvatarPayloadError("cinematic-avatar: prompt is required")
|
|
151
|
+
}
|
|
152
|
+
if ((prompt as string).length > CINEMATIC_PROMPT_MAX) {
|
|
153
|
+
throw new AvatarPayloadError(`cinematic-avatar: prompt exceeds ${CINEMATIC_PROMPT_MAX} characters`)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const avatarLooks = payload.avatarLooks
|
|
157
|
+
if (!Array.isArray(avatarLooks)) {
|
|
158
|
+
throw new AvatarPayloadError("cinematic-avatar: avatarLooks must be an array of 1–3 look ids")
|
|
159
|
+
}
|
|
160
|
+
if (avatarLooks.length < CINEMATIC_MIN_LOOKS || avatarLooks.length > CINEMATIC_MAX_LOOKS) {
|
|
161
|
+
throw new AvatarPayloadError(
|
|
162
|
+
`cinematic-avatar: avatarLooks must contain ${CINEMATIC_MIN_LOOKS}–${CINEMATIC_MAX_LOOKS} look ids (got ${avatarLooks.length})`,
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
if (!avatarLooks.every((l) => isNonEmptyString(l))) {
|
|
166
|
+
throw new AvatarPayloadError("cinematic-avatar: every avatarLooks entry must be a non-empty string")
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const resolution = (payload.resolution as string | undefined) ?? "720p"
|
|
170
|
+
const aspectRatio = (payload.aspectRatio as string | undefined) ?? "16:9"
|
|
171
|
+
if (!CINEMATIC_RESOLUTIONS.has(resolution)) {
|
|
172
|
+
throw new AvatarPayloadError(`cinematic-avatar: invalid resolution "${resolution}" (expected 720p | 1080p)`)
|
|
173
|
+
}
|
|
174
|
+
if (!CINEMATIC_ASPECT_RATIOS.has(aspectRatio)) {
|
|
175
|
+
throw new AvatarPayloadError(`cinematic-avatar: invalid aspectRatio "${aspectRatio}" (expected 16:9 | 9:16 | 1:1)`)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Combined reference caps. avatar looks are image looks → count toward the
|
|
179
|
+
// 9-image budget (matches the route superRefine).
|
|
180
|
+
const references = payload.references
|
|
181
|
+
if (references !== undefined) {
|
|
182
|
+
if (!Array.isArray(references)) {
|
|
183
|
+
throw new AvatarPayloadError("cinematic-avatar: references must be an array")
|
|
184
|
+
}
|
|
185
|
+
let videoCount = 0
|
|
186
|
+
let imageRefCount = 0
|
|
187
|
+
for (const r of references) {
|
|
188
|
+
if (!r || typeof r !== "object") {
|
|
189
|
+
throw new AvatarPayloadError("cinematic-avatar: each reference must be an object { type, url }")
|
|
190
|
+
}
|
|
191
|
+
const type = (r as { type?: unknown }).type
|
|
192
|
+
const url = (r as { url?: unknown }).url
|
|
193
|
+
if (type !== "video" && type !== "image" && type !== "audio") {
|
|
194
|
+
throw new AvatarPayloadError(`cinematic-avatar: invalid reference type "${String(type)}" (expected video | image | audio)`)
|
|
195
|
+
}
|
|
196
|
+
if (!isNonEmptyString(url)) {
|
|
197
|
+
throw new AvatarPayloadError("cinematic-avatar: each reference must carry a non-empty url")
|
|
198
|
+
}
|
|
199
|
+
if (type === "video") videoCount++
|
|
200
|
+
else if (type === "image") imageRefCount++
|
|
201
|
+
}
|
|
202
|
+
if (videoCount > CINEMATIC_MAX_REFERENCE_VIDEOS) {
|
|
203
|
+
throw new AvatarPayloadError(
|
|
204
|
+
`cinematic-avatar: at most ${CINEMATIC_MAX_REFERENCE_VIDEOS} video references are allowed (got ${videoCount})`,
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
const totalImages = avatarLooks.length + imageRefCount
|
|
208
|
+
if (totalImages > CINEMATIC_MAX_REFERENCE_IMAGES) {
|
|
209
|
+
throw new AvatarPayloadError(
|
|
210
|
+
`cinematic-avatar: at most ${CINEMATIC_MAX_REFERENCE_IMAGES} images are allowed across avatar looks + image references (got ${totalImages})`,
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Caption styles for the add-captions node. Static path uses FFmpeg drawtext;
|
|
3
|
+
* kinetic styles render via Remotion (BurnCaptions composition).
|
|
4
|
+
*
|
|
5
|
+
* Single source of truth — imported by:
|
|
6
|
+
* - backend route Zod (add-captions.ts)
|
|
7
|
+
* - backend worker handler (ffmpeg.ts)
|
|
8
|
+
* - backend MCP tool (verbs-video.ts)
|
|
9
|
+
* - backend plan schema (plan-schemas.ts)
|
|
10
|
+
* - frontend node config + cost helper
|
|
11
|
+
* - packages/remotion overlay dispatcher
|
|
12
|
+
*/
|
|
13
|
+
export const STATIC_CAPTION_STYLES = ["subtitle"] as const
|
|
14
|
+
export const KINETIC_CAPTION_STYLES = [
|
|
15
|
+
"word-highlight",
|
|
16
|
+
"karaoke",
|
|
17
|
+
"tiktok-words",
|
|
18
|
+
"word-pop",
|
|
19
|
+
"bouncy",
|
|
20
|
+
] as const
|
|
21
|
+
export const ALL_CAPTION_STYLES = [...STATIC_CAPTION_STYLES, ...KINETIC_CAPTION_STYLES] as const
|
|
22
|
+
|
|
23
|
+
export type StaticCaptionStyle = (typeof STATIC_CAPTION_STYLES)[number]
|
|
24
|
+
export type KineticCaptionStyle = (typeof KINETIC_CAPTION_STYLES)[number]
|
|
25
|
+
export type CaptionStyle = (typeof ALL_CAPTION_STYLES)[number]
|
|
26
|
+
|
|
27
|
+
const KINETIC_SET = new Set<string>(KINETIC_CAPTION_STYLES)
|
|
28
|
+
|
|
29
|
+
export function isKineticCaptionStyle(style: string | undefined | null): style is KineticCaptionStyle {
|
|
30
|
+
return style !== null && style !== undefined && KINETIC_SET.has(style)
|
|
31
|
+
}
|