Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions docs/specs/assets.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,25 @@ Even if an image asset does not have any intrinsic size, its contents MUST
still stay within the `w`-`h` bounds when rendered.

Authoring tools SHOULD export files where `w` and `h` match the physical size of the assets.

<h2 id="video">Video</h2>

{schema_string:assets/video/description}

Video formats supported vary depending on the player. Some commonly supported formats are MP4, WebM, and MOV.

{schema_object:assets/video}

Video assets define the source video content that can be referenced by video frame assets.
This enables the use of video compression techniques to reduce the overall animation size, when working with raster-based animations.

Players MUST support extracting individual frames from video assets at specified timestamps when initializing animations.

<h2 id="video-frame">Video Frame</h2>

{schema_string:assets/video-frame/description}

{schema_object:assets/video-frame}

Video frame assets reference a video asset by ID and specify a timestamp to extract a specific frame. Players MUST extract the frame at the exact timestamp specified, or the closest available frame if the exact timestamp is not available. The extracted frame should be treated as a static image for rendering purposes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should

Is this a SHOULD or a MUST?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This point is up for discussion.

The advantage of using MUST is that Lottie players could extract frames on the fly, which speeds up animation initialization and reduces memory usage before playback starts. At the same time, if players don’t treat the extracted frame as a static image but instead process it in real time, it could impose constraints on the video itself - for example, requiring more keyframes to ensure fast seeking, which would increase file size.

That’s why I would vote for MUST.

In the future, if we want to support optimization for initialization we could extend videoFrame with initialization: static | dynamic param to achieve that.

@fmalita fmalita Sep 2, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the same functionality be achieved using time remapping to lock a video layer's time? IOW do we actually need video frame assets, or would video assets be sufficient?

I can think of some advantages to having a dedicated asset type, mostly on the implementation side (caching) - but there are also some downsides (more verbose than video asset + time-locked video layer).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main motivation of having VideoFrame is ability to set time or frame number, I didn't find better way to express it with existing lottie primitives


6 changes: 6 additions & 0 deletions schema/assets/all-assets.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
},
{
"$ref": "#/$defs/assets/image"
},
{
"$ref": "#/$defs/assets/video"
},
{
"$ref": "#/$defs/assets/video-frame"
}
]
}
46 changes: 46 additions & 0 deletions schema/assets/video-frame.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Video Frame",
"description": "Asset representing a frame from a video at a specific timestamp.",
"allOf": [
{
"$ref": "#/$defs/assets/asset"
},
{
"$ref": "#/$defs/helpers/slottable-object"
},
{
"type": "object",
"properties": {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should introduce a ty for assets (not strictly required for this proposal)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbasaglia , I agree. Added ty prop

"vsid": {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Naming bike-shed: normally sid refers for "slot ID", which I guess could be adopted here if we squint. But since we're not dealing with real slots, that may be confusing.

How about refId, which is the normal way to reference assets?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, refId makes more sense, updated

"title": "Video Asset ID",
"description": "ID of the video asset to extract frame from",
"type": "string"
},
"t": {
"title": "Timestamp",
"description": "Timestamp in seconds where to extract the frame from the video",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this interact with start-time/time-stretch/general time remapping in referencing layers?

Also actual time units seem a bit odd since everything else in Lottie is expressed as frame indices (ip, op, etc).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you are right, we can define time in frames here

"type": "number",
"minimum": 0
},
"w": {
"title": "Width",
"description": "Width of the frame",
"type": "number"
},
"h": {
"title": "Height",
"description": "Height of the frame",
"type": "number"
}
Comment on lines +33 to +42

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The video asset schema also has w and h, are they needed here as well? if so, what's their semantic?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbasaglia I was thinking about extracting a frame from VideoResource, specifying width, height, x, y from the top left corner. But you are right, as a first iteration we can drop w/h from frame

},
"if": {
"required": ["sid"]
},
"else": {
"required": ["vsid", "t"]
}
}
]
}
71 changes: 71 additions & 0 deletions schema/assets/video.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"title": "Video",
"description": "Asset containing a video that can be referenced by layers or video frame assets.",
"allOf": [
{
"$ref": "#/$defs/assets/asset"
},
{
"$ref": "#/$defs/helpers/slottable-object"
},
{
"type": "object",
"properties": {
"w": {
"title": "Width",
"description": "Width of the video",
"type": "number"
},
"h": {
"title": "Height",
"description": "Height of the video",
"type": "number"
},
"duration": {
"title": "Duration",
"description": "Duration of the video in seconds",
"type": "number",
"minimum": 0
},
"p": {
"title": "File Name",
"description": "Name of the video file or a data url",
"type": "string"
},
"u": {
"title": "File Path",
"description": "Path to the video file",
"type": "string"
},
"e": {
"title": "Embedded",
"description": "If '1', 'p' is a Data URL",
"$ref": "#/$defs/values/int-boolean"
}
},
"allOf": [
{
"if": {
"properties": {
"e": {"const": 1}
},
"required": ["e"]
},
"then": {
"properties": {
"p": {"$ref": "#/$defs/values/data-url"}
}
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd extract this into an abstract file-asset schema so we can share the definition between image and video assets (and other future assets

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mbasaglia Added file-asset

],
"if": {
"required": ["sid"]
},
"else": {
"required": ["w", "h", "duration", "p"]
}
}
]
}