import { Asset } from '@happyvertical/smrt-assets'; import { AssetOptions } from '@happyvertical/smrt-assets'; import { Content } from '@happyvertical/smrt-content'; import { ContentOptions } from '@happyvertical/smrt-content'; import { MediaBundleFileDescriptor } from '@happyvertical/smrt-assets'; import { MediaBundleGpsTrackPoint } from '@happyvertical/smrt-assets'; import { MediaBundleInspection } from '@happyvertical/smrt-assets'; import { MediaBundleInspectionLike } from '@happyvertical/smrt-assets'; import { MediaBundleNormalizedMetadata } from '@happyvertical/smrt-assets'; import { MediaBundleSupportFileInspection } from '@happyvertical/smrt-assets'; import { MediaSupportFileVisibility } from '@happyvertical/smrt-assets'; import { PersistMediaBundleAssetInput } from '@happyvertical/smrt-assets'; import { PersistMediaBundleAssociationInput } from '@happyvertical/smrt-assets'; import { persistMediaBundleInspection } from '@happyvertical/smrt-assets'; import { PersistMediaBundleInspectionOptions } from '@happyvertical/smrt-assets'; import { PersistMediaBundleInspectionResult } from '@happyvertical/smrt-assets'; import { PersistMediaBundleMetadataArtifactInput } from '@happyvertical/smrt-assets'; import { SmrtCollection } from '@happyvertical/smrt-core'; import { SmrtJunction } from '@happyvertical/smrt-core'; import { SmrtMediaBundlePersistenceAdapter } from '@happyvertical/smrt-assets'; import { SmrtObject } from '@happyvertical/smrt-core'; import { SmrtObjectOptions } from '@happyvertical/smrt-core'; import { WordTiming } from '@happyvertical/smrt-voice'; /** * Anchor point for character placement in scene */ export declare interface AnchorPoint { /** Anchor point identifier */ id: string; /** Human-readable name */ name: string; /** Position as normalized coordinates (0-1) */ position: { x: number; y: number; }; /** Suggested character scale at this point */ suggestedScale: number; /** Ground plane Y coordinate for perspective */ groundY: number; /** Optional viewpoint this anchor belongs to */ viewpointId?: string; } /** * Branding configuration for video overlays */ export declare interface BrandingConfig { /** Asset ID for logo overlay */ logoAssetId?: string | null; /** Primary brand color (hex) */ primaryColor?: string | null; /** Background color (hex) */ backgroundColor?: string | null; /** Lower-third template name */ lowerThirdTemplate?: string | null; /** Font family for text overlays */ fontFamily?: string | null; /** Whether to show news ticker */ tickerEnabled?: boolean; } /** * Virtual character for AI-powered video production * * Character represents a virtual persona combining: * - Visual identity: Seed image for I2V (image-to-video) generation * - Voice identity: Link to a VoiceProfile for TTS * - Branding: Logo overlays, lower-thirds, colors * * @example * ```typescript * import { Character } from '@happyvertical/smrt-video'; * * const character = new Character({ * name: 'Bentley News Anchor', * description: 'Professional news anchor for local broadcasts', * imageAssetId: 'asset-123', * voiceProfileId: 'voice-456', * brandingKit: { * logoAssetId: 'asset-789', * primaryColor: '#1a73e8', * lowerThirdTemplate: 'news-standard', * tickerEnabled: true, * }, * }); * await character.save(); * ``` */ declare class Character extends SmrtObject { /** Tenant ID for multi-tenant isolation */ tenantId: string | null; /** Human-readable name for the character */ name: string; /** Description of the character persona */ description: string | null; /** Asset ID of the seed image for I2V generation */ imageAssetId: string | null; /** Asset ID of pre-baked base motion video */ baseMotionAssetId: string | null; /** Voice profile ID for speech synthesis */ voiceProfileId: string | null; /** Branding configuration for video overlays */ brandingKit: BrandingConfig; /** Character status */ status: CharacterStatus; /** Linked performer for IP-Adapter face consistency */ performerId: string | null; /** Default scene for this character */ defaultSceneId: string | null; /** Scene-specific configurations */ sceneConfigs: CharacterSceneConfig[]; /** 1-1 profile record for this character */ profileId: string | null; constructor(options?: CharacterOptions); private getCharacterAssetCollection; private getLegacyFieldAssetIds; private setLegacyFieldAssetId; private clearLegacyFieldAssetId; getAssets(role?: CharacterAssetRole): Promise; getAssetByRole(role: CharacterAssetRole): Promise; addAsset(asset: Asset, role?: CharacterAssetRole, sortOrder?: number): Promise; removeAsset(assetId: string, role?: CharacterAssetRole): Promise; /** * Check if the character has a pre-baked base motion video * @deprecated Use getAssetByRole('base-motion') instead */ get hasBaseMotion(): boolean; /** Check if the character is complete and ready for video generation */ get isComplete(): boolean; } export { Character } export { Character as PersonalityProfile } export declare class CharacterAsset extends Asset { characterId: string | null; role: CharacterAssetRole; constructor(options?: CharacterAssetOptions); } export declare interface CharacterAssetOptions extends AssetOptions { /** Character this asset belongs to */ characterId?: string | null; /** Role of this asset for the character */ role?: CharacterAssetRole; } /** Roles a character asset can play */ export declare type CharacterAssetRole = 'seed-image' | 'base-motion' | 'logo'; export declare class CharacterCollection extends SmrtCollection { static readonly _itemClass: typeof Character; /** Find all characters belonging to a specific tenant */ findByTenant(tenantId: string): Promise; /** * Find all global characters (no tenant association). * * Routes through the shared tenant-global helper so it does not throw under * an active tenant context (an explicit `tenant_id IS NULL` filter would be * flagged as an isolation violation). (#1600) */ findGlobal(): Promise; /** Find characters by performer */ findByPerformer(performerId: string): Promise; /** Find characters that are ready for video generation */ findReady(): Promise; } /** * Character creation options */ declare interface CharacterOptions extends SmrtObjectOptions { /** Human-readable name for the character */ name?: string; /** Description of the character persona */ description?: string | null; /** Asset ID of the seed image for image-to-video generation */ imageAssetId?: string | null; /** Asset ID of pre-baked base motion video */ baseMotionAssetId?: string | null; /** Voice profile ID for speech synthesis */ voiceProfileId?: string | null; /** Branding configuration for video overlays */ brandingKit?: BrandingConfig; /** Character status */ status?: CharacterStatus; /** Linked performer for IP-Adapter face consistency */ performerId?: string | null; /** Default scene for this character */ defaultSceneId?: string | null; /** Scene-specific configurations */ sceneConfigs?: CharacterSceneConfig[]; /** 1-1 profile record for this character */ profileId?: string | null; /** Tenant ID for multi-tenant isolation */ tenantId?: string | null; } export { CharacterOptions } export { CharacterOptions as PersonalityProfileOptions } export declare class CharacterOwnedAsset extends SmrtObject { tenantId: string | null; characterId: string; assetId: string; role: CharacterAssetRole; sortOrder: number; constructor(options?: CharacterOwnedAssetOptions); } export declare class CharacterOwnedAssetCollection extends SmrtJunction { static readonly _itemClass: typeof CharacterOwnedAsset; protected leftField: string; protected rightField: string; } export declare interface CharacterOwnedAssetOptions extends SmrtObjectOptions { characterId?: string; assetId?: string; role?: CharacterAssetRole; sortOrder?: number; tenantId?: string | null; } /** * Scene-specific configuration for a character */ export declare interface CharacterSceneConfig { /** Scene ID */ sceneId: string; /** Preferred viewpoint ID (for 360° scenes) */ viewpointId?: string; /** Anchor point ID for placement */ anchorPointId?: string; /** Character scale in this scene */ scale: number; /** Character position in this scene (normalized 0-1) */ position: { x: number; y: number; }; } /** * Character status */ declare type CharacterStatus = 'pending' | 'ready'; export { CharacterStatus } export { CharacterStatus as PersonalityProfileStatus } /** * Composite job for tracking virtual production compositing * * @example * ```typescript * import { CompositeJob } from '@happyvertical/smrt-video'; * * const job = new CompositeJob({ * characterVideoAssetId: 'asset-video-123', * sceneId: 'scene-townhall', * scale: 0.8, * position: { x: 0.5, y: 0.7 }, * }); * await job.save(); * ``` */ export declare class CompositeJob extends SmrtObject { tenantId: string | null; /** Character video asset ID (after lip-sync) */ characterVideoAssetId: string | null; /** Scene ID to composite onto */ sceneId: string | null; /** Viewpoint ID (for 360° scenes) */ viewpointId: string | null; /** Anchor point ID for placement */ anchorPointId: string | null; /** Character scale */ scale: number; /** Character position (normalized 0-1) */ position: { x: number; y: number; }; /** Job status */ status: CompositeJobStatus; /** Progress percentage (0-100) */ progress: number; /** Output video asset ID */ outputAssetId: string | null; /** Error message if failed */ errorMessage: string | null; constructor(options?: CompositeJobOptions); /** Check if the job is complete */ get isComplete(): boolean; /** Check if the job is in progress */ get isProcessing(): boolean; } /** * Composite job creation options */ export declare interface CompositeJobOptions extends SmrtObjectOptions { /** Character video asset ID (after lip-sync) */ characterVideoAssetId?: string | null; /** Scene ID to composite onto */ sceneId?: string | null; /** Viewpoint ID (for 360° scenes) */ viewpointId?: string | null; /** Anchor point ID for placement */ anchorPointId?: string | null; /** Character scale */ scale?: number; /** Character position (normalized 0-1) */ position?: { x: number; y: number; }; /** Job status */ status?: CompositeJobStatus; /** Progress percentage (0-100) */ progress?: number; /** Output video asset ID */ outputAssetId?: string | null; /** Error message if failed */ errorMessage?: string | null; /** Tenant ID for multi-tenant isolation */ tenantId?: string | null; } /** * Composite job status */ export declare type CompositeJobStatus = 'pending' | 'removing_bg' | 'analyzing_light' | 'compositing' | 'complete' | 'failed'; /** * Lighting profile for IC-Light matching */ export declare interface LightingProfile { /** Dominant light direction (normalized vector) */ direction?: { x: number; y: number; z: number; }; /** Light color temperature (Kelvin) */ colorTemperature?: number; /** Ambient light intensity (0-1) */ ambientIntensity?: number; /** Key light intensity (0-1) */ keyLightIntensity?: number; /** Shadow softness (0-1) */ shadowSoftness?: number; /** Environment map asset ID for reflections */ envMapAssetId?: string; } export { MediaBundleFileDescriptor } export { MediaBundleGpsTrackPoint } export { MediaBundleInspection } export { MediaBundleInspectionLike } export { MediaBundleNormalizedMetadata } export { MediaBundleSupportFileInspection } export { MediaSupportFileVisibility } /** * Node mapping for dynamic parameter injection */ export declare interface NodeMapping { /** * Node ID for anchor seed image input */ seedImage?: string; /** * Node ID for TTS audio input */ audioFile?: string; /** * Node ID for base motion video input */ baseVideo?: string; /** * Node ID for final video output */ outputVideo?: string; /** * Node ID for text prompt input */ prompt?: string; /** * Node ID for negative prompt input */ negativePrompt?: string; /** * Node ID for sampler/scheduler settings */ sampler?: string; /** * Node ID for video duration control */ duration?: string; /** * Additional custom node mappings */ [key: string]: string | undefined; } /** * Performer - The physical likeness/face DNA * * A Performer represents a person's visual identity for consistent * face generation across multiple Characters. One Performer can play * many Characters (e.g., same face as "Evening Anchor" and "Weekend Host"). * * @example * ```typescript * import { Performer } from '@happyvertical/smrt-video'; * * const performer = new Performer({ * name: 'Alex Bentley', * dna: { * gender: 'male', * ageRange: 'adult', * ipAdapterWeight: 0.75, * }, * referenceAssetIds: ['ref-img-1', 'ref-img-2'], * }); * await performer.save(); * ``` */ export declare class Performer extends SmrtObject { tenantId: string | null; /** Human-readable name */ name: string; /** Description */ description: string | null; /** Performer DNA for consistent face generation */ dna: PerformerDNA; /** Reference images for IP-Adapter (multiple angles/expressions) */ referenceAssetIds: string[]; /** Generated seed image asset ID */ seedImageAssetId: string | null; /** Default voice profile for this performer */ voiceProfileId: string | null; /** Performer status */ status: PerformerStatus; /** 1-1 profile record for this performer */ profileId: string | null; constructor(options?: PerformerOptions); private getPerformerAssetCollection; private getLegacyFieldAssetIds; private setLegacyFieldAssetId; private clearLegacyFieldAssetId; getAssets(role?: PerformerAssetRole): Promise; getAssetByRole(role: PerformerAssetRole): Promise; addAsset(asset: Asset, role?: PerformerAssetRole, sortOrder?: number): Promise; removeAsset(assetId: string, role?: PerformerAssetRole): Promise; /** Check if the performer has reference images */ get hasReferences(): boolean; /** Check if the performer has a face embedding */ get hasFaceEmbedding(): boolean; /** Check if the performer is ready for generation */ get isReady(): boolean; } export declare class PerformerAsset extends Asset { performerId: string | null; role: PerformerAssetRole; constructor(options?: PerformerAssetOptions); } export declare interface PerformerAssetOptions extends AssetOptions { /** Performer this asset belongs to */ performerId?: string | null; /** Role of this asset for the performer */ role?: PerformerAssetRole; } /** Roles a performer asset can play */ export declare type PerformerAssetRole = 'reference' | 'seed'; /** * Performer DNA for IP-Adapter FaceID consistency */ export declare interface PerformerDNA { /** Gender */ gender: 'male' | 'female' | 'neutral'; /** Age range */ ageRange: 'child' | 'teen' | 'young_adult' | 'adult' | 'middle_aged' | 'senior'; /** Face embedding for IP-Adapter FaceID (512-dim vector) */ faceEmbedding?: number[]; /** Default clothing style (can be overridden per Character) */ defaultClothing?: { style: 'business' | 'casual' | 'formal' | 'outdoor'; colors?: string[]; description?: string; }; /** IP-Adapter weight for consistency (0.5-1.0) */ ipAdapterWeight: number; /** FaceID weight for face consistency */ faceIdWeight?: number; } /** * Performer creation options */ export declare interface PerformerOptions extends SmrtObjectOptions { /** Human-readable name */ name?: string; /** Description */ description?: string | null; /** Performer DNA for consistent face generation */ dna?: PerformerDNA; /** Reference images for IP-Adapter (multiple angles/expressions) */ referenceAssetIds?: string[]; /** Generated seed image asset ID */ seedImageAssetId?: string | null; /** Default voice profile for this performer */ voiceProfileId?: string | null; /** Performer status */ status?: PerformerStatus; /** 1-1 profile record for this performer */ profileId?: string | null; /** Tenant ID for multi-tenant isolation */ tenantId?: string | null; } export declare class PerformerOwnedAsset extends SmrtObject { tenantId: string | null; performerId: string; assetId: string; role: PerformerAssetRole; sortOrder: number; constructor(options?: PerformerOwnedAssetOptions); } export declare class PerformerOwnedAssetCollection extends SmrtJunction { static readonly _itemClass: typeof PerformerOwnedAsset; protected leftField: string; protected rightField: string; } export declare interface PerformerOwnedAssetOptions extends SmrtObjectOptions { performerId?: string; assetId?: string; role?: PerformerAssetRole; sortOrder?: number; tenantId?: string | null; } /** * Performer status */ export declare type PerformerStatus = 'pending' | 'ready'; export { PersistMediaBundleAssetInput } export { PersistMediaBundleAssociationInput } export { persistMediaBundleInspection } export { PersistMediaBundleInspectionOptions } export { PersistMediaBundleInspectionResult } export { PersistMediaBundleMetadataArtifactInput } /** * Render status for the composition */ export declare type RenderStatus = 'draft' | 'rendering' | 'ready' | 'failed'; /** * Scene for virtual production compositing * * Supports 360° panoramas, standard images, and video backgrounds * with viewpoint extraction, lighting analysis, and character placement. * * @example * ```typescript * import { Scene } from '@happyvertical/smrt-video'; * * const scene = new Scene({ * name: 'Town Hall Exterior', * sourceAssetId: 'asset-townhall-pano', * sourceType: 'panorama_360', * projection: 'equirectangular', * }); * await scene.save(); * ``` */ export declare class Scene extends SmrtObject { tenantId: string | null; /** Human-readable name */ name: string; /** Description */ description: string | null; /** Source media asset ID */ sourceAssetId: string | null; /** Type of source media */ sourceType: SceneSourceType; /** Projection type for panoramas */ projection: SceneProjection | null; /** Extracted camera angles from 360° panoramas */ viewpoints: SceneViewpoint[]; /** Lighting analysis for IC-Light matching */ lightingProfile: LightingProfile | null; /** Location metadata */ location: { name: string; coordinates?: { lat: number; lng: number; }; } | null; /** Anchor points for character placement */ anchorPoints: AnchorPoint[]; /** Scene status */ status: SceneStatus; constructor(options?: SceneOptions); private getSceneAssetCollection; private getLegacyFieldAssetIds; private setLegacyFieldAssetId; private clearLegacyFieldAssetId; getAssets(role?: SceneAssetRole): Promise; getAssetByRole(role: SceneAssetRole): Promise; addAsset(asset: Asset, role?: SceneAssetRole, sortOrder?: number): Promise; removeAsset(assetId: string, role?: SceneAssetRole): Promise; /** Check if this is a 360° panorama */ get isPanorama(): boolean; /** Check if the scene has viewpoints extracted */ get hasViewpoints(): boolean; /** Check if the scene is ready for compositing */ get isReady(): boolean; } export declare class SceneAsset extends Asset { sceneId: string | null; role: SceneAssetRole; constructor(options?: SceneAssetOptions); } export declare interface SceneAssetOptions extends AssetOptions { /** Scene this asset belongs to */ sceneId?: string | null; /** Role of this asset for the scene */ role?: SceneAssetRole; } /** Roles a scene asset can play */ export declare type SceneAssetRole = 'source' | 'viewpoint-extract' | 'env-map'; /** * Scene creation options */ export declare interface SceneOptions extends SmrtObjectOptions { /** Human-readable name */ name?: string; /** Description */ description?: string | null; /** Source media asset ID */ sourceAssetId?: string | null; /** Type of source media */ sourceType?: SceneSourceType; /** Projection type for panoramas */ projection?: SceneProjection | null; /** Extracted camera angles from 360° panoramas */ viewpoints?: SceneViewpoint[]; /** Lighting analysis for IC-Light matching */ lightingProfile?: LightingProfile | null; /** Location metadata */ location?: { name: string; coordinates?: { lat: number; lng: number; }; } | null; /** Anchor points for character placement */ anchorPoints?: AnchorPoint[]; /** Scene status */ status?: SceneStatus; /** Tenant ID for multi-tenant isolation */ tenantId?: string | null; } export declare class SceneOwnedAsset extends SmrtObject { tenantId: string | null; sceneId: string; assetId: string; role: SceneAssetRole; sortOrder: number; constructor(options?: SceneOwnedAssetOptions); } export declare class SceneOwnedAssetCollection extends SmrtJunction { static readonly _itemClass: typeof SceneOwnedAsset; protected leftField: string; protected rightField: string; } export declare interface SceneOwnedAssetOptions extends SmrtObjectOptions { sceneId?: string; assetId?: string; role?: SceneAssetRole; sortOrder?: number; tenantId?: string | null; } /** * Scene projection type */ export declare type SceneProjection = 'equirectangular' | 'cubemap'; /** * Scene source type */ export declare type SceneSourceType = 'image' | 'video' | 'panorama_360' | 'panorama_180'; /** * Scene status */ export declare type SceneStatus = 'pending' | 'processing' | 'ready' | 'failed'; /** * Viewpoint extracted from 360° scene */ export declare interface SceneViewpoint { /** Viewpoint identifier */ id: string; /** Human-readable name */ name: string; /** Horizontal rotation (-180 to 180°) */ pan: number; /** Vertical rotation (-90 to 90°) */ tilt: number; /** Field of view (60-120°) */ fov: number; /** Generated rectilinear image asset ID */ extractedAssetId?: string; /** Viewpoint-specific lighting profile */ lightingProfile?: LightingProfile; } export { SmrtMediaBundlePersistenceAdapter } /** * Transition type to the next sequence */ export declare type TransitionType = 'none' | 'fade' | 'slide' | 'wipe'; /** * Publishable video composition * * VideoComposition is the top-level container for a rendered video. * It defines the render spec and contains ordered VideoSequences. * * @example * ```typescript * import { VideoComposition } from '@happyvertical/smrt-video'; * * const composition = new VideoComposition({ * title: 'Evening News - January 25, 2026', * fps: 30, * width: 1920, * height: 1080, * }); * await composition.save(); * ``` */ export declare class VideoComposition extends Content { /** Frames per second — everything downstream is in frames */ fps: number; /** Render width in pixels */ width: number; /** Render height in pixels */ height: number; /** Computed total: sum of sequences minus transition overlaps */ durationInFrames: number; /** Render status */ renderStatus: RenderStatus; /** Render progress (0-100) */ renderProgress: number; constructor(options?: VideoCompositionOptions); /** Duration in seconds */ get durationInSeconds(): number; /** Check if the composition is ready for publishing */ get isReady(): boolean; /** Check if the composition is currently rendering */ get isRendering(): boolean; getAssets(relationship?: string): Promise; getAssets(role?: VideoCompositionAssetRole): Promise; getAssetByRole(role: VideoCompositionAssetRole): Promise; } export declare class VideoCompositionAsset extends Asset { videoCompositionId: string | null; role: VideoCompositionAssetRole; constructor(options?: VideoCompositionAssetOptions); } export declare interface VideoCompositionAssetOptions extends AssetOptions { /** VideoComposition this asset belongs to */ videoCompositionId?: string | null; /** Role of this asset for the composition */ role?: VideoCompositionAssetRole; } /** Roles a video composition asset can play */ export declare type VideoCompositionAssetRole = 'video' | 'audio' | 'thumbnail'; export declare class VideoCompositionCollection extends SmrtCollection { static readonly _itemClass: typeof VideoComposition; /** Find compositions by render status */ findByRenderStatus(renderStatus: RenderStatus): Promise; /** Find compositions that are ready for publishing */ findReady(): Promise; } /** * VideoComposition creation options */ export declare interface VideoCompositionOptions extends ContentOptions { /** Frames per second (e.g., 30) — everything downstream is in frames */ fps?: number; /** Render width in pixels */ width?: number; /** Render height in pixels */ height?: number; /** Computed total: sum of sequences minus transition overlaps */ durationInFrames?: number; /** Render status */ renderStatus?: RenderStatus; /** Render progress (0-100) */ renderProgress?: number; } /** * Video metadata */ export declare interface VideoMetadata { /** Actual duration in seconds */ duration?: number; /** Video resolution (e.g., "1920x1080") */ resolution?: string; /** Aspect ratio (e.g., "16:9", "9:16") */ aspectRatio?: string; /** Video codec (e.g., "h264", "h265") */ codec?: string; /** Frames per second */ fps?: number; /** File size in bytes */ fileSize?: number; /** Word timing data from TTS for lip-sync */ wordTimings?: WordTiming[]; /** ComfyUI prompt ID for tracking */ comfyPromptId?: string; } /** * Thematic section of a video composition * * VideoSequence groups VideoShots into a logical section. It can belong * to a VideoComposition or exist standalone (e.g., during long-video generation). * * @example * ```typescript * import { VideoSequence } from '@happyvertical/smrt-video'; * * const sequence = new VideoSequence({ * title: 'Top Story', * position: 0, * transitionType: 'fade', * transitionDurationFrames: 15, * }); * await sequence.save(); * ``` */ export declare class VideoSequence extends Content { /** Composition this sequence belongs to */ compositionId: string | null; /** Order within composition */ position: number; /** Computed duration: sum of shot frames */ durationInFrames: number; /** Transition type to the next sequence */ transitionType: TransitionType; /** Overlap frames with next sequence for transition */ transitionDurationFrames: number; constructor(options?: VideoSequenceOptions); getAssets(relationship?: string): Promise; getAssets(role?: VideoSequenceAssetRole): Promise; getAssetByRole(role: VideoSequenceAssetRole): Promise; } export declare class VideoSequenceAsset extends Asset { videoSequenceId: string | null; role: VideoSequenceAssetRole; constructor(options?: VideoSequenceAssetOptions); } export declare interface VideoSequenceAssetOptions extends AssetOptions { /** VideoSequence this asset belongs to */ videoSequenceId?: string | null; /** Role of this asset for the sequence */ role?: VideoSequenceAssetRole; } /** Roles a video sequence asset can play */ export declare type VideoSequenceAssetRole = 'video' | 'audio' | 'thumbnail'; export declare class VideoSequenceCollection extends SmrtCollection { static readonly _itemClass: typeof VideoSequence; /** Find sequences belonging to a composition, ordered by position */ findByComposition(compositionId: string): Promise; /** Find standalone sequences (not in any composition) */ findStandalone(): Promise; } /** * VideoSequence creation options */ export declare interface VideoSequenceOptions extends ContentOptions { /** Composition this sequence belongs to (nullable — can exist standalone) */ compositionId?: string | null; /** Order within composition */ position?: number; /** Computed duration: sum of shot frames */ durationInFrames?: number; /** Transition type to the next sequence */ transitionType?: TransitionType; /** Overlap frames with next sequence for transition */ transitionDurationFrames?: number; } /** * Atomic video generation unit * * VideoShot represents a single pipeline run producing one video clip. * It can belong to a VideoSequence (for multi-segment long videos) or * exist standalone. Characters are linked via the VideoShotCharacter join model. * * @example * ```typescript * import { VideoShot } from '@happyvertical/smrt-video'; * * const shot = new VideoShot({ * scriptText: 'Welcome to the evening news.', * targetDuration: 30, * title: 'Evening News - Opening', * }); * await shot.save(); * ``` */ declare class VideoShot extends Content { /** Sequence this shot belongs to */ sequenceId: string | null; /** Scene for this shot */ sceneId: string | null; /** Order within sequence */ position: number; /** Actual frame count of generated clip */ durationInFrames: number; /** Frames to skip at start (overlap handling) */ trimBeforeFrames: number; /** Frames to skip at end */ trimAfterFrames: number; /** Script text to be spoken */ scriptText: string; /** Word count in the script */ scriptWordCount: number; /** Target duration in seconds */ targetDuration: number; /** Video generation status */ shotStatus: VideoShotStatus; /** Generation progress (0-100) */ progress: number; /** Error message if status is 'failed' */ errorMessage: string | null; /** Detailed status message for progress tracking */ statusMessage: string | null; /** Video metadata (duration, resolution, etc.) */ videoMetadata: VideoMetadata; constructor(options?: VideoShotOptions); /** Estimate speech duration based on word count (2.7 words/sec) */ get estimatedDuration(): number; /** Check if the script length matches target duration (+/- 15%) */ get isScriptLengthValid(): boolean; /** Get the recommended word count for target duration */ get recommendedWordCount(): { min: number; max: number; target: number; }; /** Effective frame count after trimming */ get effectiveFrames(): number; /** Check if video generation is in progress */ get isGenerating(): boolean; /** Check if video is ready for publishing */ get isReady(): boolean; getAssets(relationship?: string): Promise; getAssets(role?: VideoShotAssetRole): Promise; getAssetByRole(role: VideoShotAssetRole): Promise; /** Update script text and recalculate word count */ setScript(text: string): void; } export { VideoShot as VideoContent } export { VideoShot } export declare class VideoShotAsset extends Asset { videoShotId: string | null; role: VideoShotAssetRole; constructor(options?: VideoShotAssetOptions); } export declare interface VideoShotAssetOptions extends AssetOptions { /** VideoShot this asset belongs to */ videoShotId?: string | null; /** Role of this asset for the shot */ role?: VideoShotAssetRole; } /** Roles a video shot asset can play */ export declare type VideoShotAssetRole = 'video' | 'audio' | 'thumbnail'; /** * Join model linking a VideoShot to a Character * * @example * ```typescript * import { VideoShotCharacter } from '@happyvertical/smrt-video'; * * const link = new VideoShotCharacter({ * videoShotId: 'shot-123', * characterId: 'char-456', * role: 'primary', * position: 0, * }); * await link.save(); * ``` */ export declare class VideoShotCharacter extends SmrtObject { tenantId: string | null; /** Video shot ID */ videoShotId: string; /** Character ID */ characterId: string; /** Role of the character in this shot */ role: VideoShotCharacterRole; /** Order/layer position within the shot */ position: number; constructor(options: VideoShotCharacterOptions); } export declare class VideoShotCharacterCollection extends SmrtCollection { static readonly _itemClass: typeof VideoShotCharacter; /** Find all character links for a shot, ordered by position */ findByShot(videoShotId: string): Promise; /** Find all shot links for a character */ findByCharacter(characterId: string): Promise; } /** * VideoShotCharacter creation options */ export declare interface VideoShotCharacterOptions extends SmrtObjectOptions { /** Video shot ID */ videoShotId: string; /** Character ID */ characterId: string; /** Role of the character in this shot */ role?: VideoShotCharacterRole; /** Order/layer position within the shot */ position?: number; /** Tenant ID for multi-tenant isolation */ tenantId?: string | null; } /** * Character role within a shot */ export declare type VideoShotCharacterRole = 'primary' | 'secondary' | 'background'; export declare class VideoShotCollection extends SmrtCollection { static readonly _itemClass: typeof VideoShot; /** Find shots belonging to a specific sequence, ordered by position */ findBySequence(sequenceId: string): Promise; /** Find shots by status */ findByStatus(shotStatus: VideoShotStatus): Promise; /** Find standalone shots (not in any sequence) */ findStandalone(): Promise; } /** * Video shot creation options */ declare interface VideoShotOptions extends ContentOptions { /** Sequence this shot belongs to (nullable — shots can exist standalone) */ sequenceId?: string | null; /** Scene for this shot (nullable) */ sceneId?: string | null; /** Order within sequence */ position?: number; /** Actual frame count of generated clip */ durationInFrames?: number; /** Frames to skip at start (overlap handling) */ trimBeforeFrames?: number; /** Frames to skip at end */ trimAfterFrames?: number; /** Script text to be spoken */ scriptText?: string; /** Word count in the script */ scriptWordCount?: number; /** Target duration in seconds */ targetDuration?: number; /** Video generation status */ shotStatus?: VideoShotStatus; /** Generation progress (0-100) */ progress?: number; /** Error message if status is 'failed' */ errorMessage?: string | null; /** Detailed status message for progress tracking */ statusMessage?: string | null; /** Video metadata */ videoMetadata?: VideoMetadata; } export { VideoShotOptions as VideoContentOptions } export { VideoShotOptions } /** * Video shot status */ declare type VideoShotStatus = 'draft' | 'queued' | 'processing' | 'ready' | 'failed' | 'published'; export { VideoShotStatus as VideoContentStatus } export { VideoShotStatus } /** * ComfyUI workflow template for video generation * * VideoWorkflow stores ComfyUI workflow definitions with node mappings * for dynamic parameter injection. This allows the Histrio agent to * inject anchor images, audio, and other inputs at runtime. * * @example * ```typescript * import { VideoWorkflow } from '@happyvertical/smrt-video'; * * const workflow = new VideoWorkflow({ * name: 'Wan 2.6 + EchoMimic', * description: 'Full broadcast generation with lip-sync', * workflowType: 'broadcast', * workflowJson: comfyuiWorkflowJson, * nodeMapping: { * seedImage: '1', * audioFile: '5', * outputVideo: '12', * }, * estimatedTime: 600, // 10 minutes * requiredModels: ['wan_2.6_t2v_14b_fp8', 'echomimic_v2'], * }); * await workflow.save(); * ``` */ export declare class VideoWorkflow extends SmrtObject { /** * Tenant ID for multi-tenant isolation */ tenantId: string | null; /** * Human-readable name for the workflow */ name: string; /** * Description of what this workflow does */ description: string | null; /** * Workflow type classification * - prebake: Pre-generate base motion from seed image * - broadcast: Full video generation pipeline * - lipsync: Lip-sync only (requires base video + audio) * - postprod: Post-production overlays and effects * - custom: User-defined workflow */ workflowType: WorkflowType; /** * ComfyUI API format JSON * This is the workflow definition that will be sent to ComfyUI */ workflowJson: object | null; /** * Node ID mappings for dynamic parameter injection * Maps semantic names to ComfyUI node IDs */ nodeMapping: NodeMapping; /** * Estimated processing time in seconds * Used for progress estimation */ estimatedTime: number; /** * Whether this workflow is active/usable */ isActive: boolean; /** * ComfyUI models required by this workflow * Used for validation before queuing */ requiredModels: string[]; constructor(options?: VideoWorkflowOptions); /** * Check if the workflow has all required node mappings */ get hasRequiredMappings(): boolean; /** * Get a copy of the workflow JSON with injected parameters * * Parameter injection follows ComfyUI node structure conventions: * - seedImage, audioFile, baseVideo → node.inputs.image (file path) * - prompt → node.inputs.text (string) * - Other parameters → node.inputs[paramKey] * * @param params - Key-value pairs of parameters to inject * @returns Modified workflow JSON or null if no workflowJson set */ injectParameters(params: Record): object | null; } /** * Video workflow creation options */ export declare interface VideoWorkflowOptions extends SmrtObjectOptions { /** * Human-readable name for the workflow */ name?: string; /** * Description of what this workflow does */ description?: string | null; /** * Workflow type classification * @default 'custom' */ workflowType?: WorkflowType; /** * ComfyUI API format JSON */ workflowJson?: object | null; /** * Node ID mappings for dynamic parameter injection */ nodeMapping?: NodeMapping; /** * Estimated processing time in seconds */ estimatedTime?: number; /** * Whether this workflow is active/usable * @default true */ isActive?: boolean; /** * ComfyUI models required by this workflow */ requiredModels?: string[]; /** * Tenant ID for multi-tenant isolation */ tenantId?: string | null; } /** * Workflow type classification */ export declare type WorkflowType = 'prebake' | 'broadcast' | 'lipsync' | 'postprod' | 'custom'; export { }