Animated Assets: GIFs & Videos
Motion brings a UI to life, but using the wrong asset type can put significant pressure on your game’s memory and performance budget. This article covers the constraints of GIF animations, how to implement WebM video playback correctly, and why you should prioritize alternatives like Sprite Sheets and Live Views for most use cases.
The Reality of GIFs
Section titled “The Reality of GIFs”While GIFs are common on the traditional web, the format is generally not recommended for game UI. It carries several technical limitations that make it a poor fit for production use in Gameface.
-
Compression and file size. GIF animations rely on an older compression algorithm. For the same animation, a GIF file tends to be 5 to 10 times larger than an equivalent efficiently encoded video. This translates directly into larger asset bundles and longer load times.
-
Visual quality. The GIF standard supports only 256 colors per frame and provides no support for semi-transparency. Every pixel is either fully opaque or fully transparent. Artwork with gradients or soft alpha edges will show visible color banding and rough outlines compared to formats like PNG.
-
Memory consumption. Gameface optimizes GIF playback by preloading all frames to avoid decoding them at runtime. While this prevents per-frame CPU spikes during animation, it means the entire animation is unpacked into memory up front. High-resolution or high-framerate GIFs will have a notable impact on your game’s memory consumption.
Safe GIF Usage
Section titled “Safe GIF Usage”If your design requires GIF animations, they remain practical for one specific use case: small animated emojis . GIFs are
currently supported as a source for <img> elements.
To keep memory consumption manageable, follow these limits:
- Keep the resolution at or below 128x128 pixels .
- Keep the frame count at or below 30 frames per animation.
How to Use GIFs
Section titled “How to Use GIFs”The only supported way to render GIF animations in Gameface is through standard HTML <img> tags. The following example places a small animated emoji
inline within a chat message:
<div class="chat-message"> <span>Great shot!</span> <img src="thumbs_up_emoji.gif" width="32" height="32" alt="Thumbs Up" /></div>Unsupported GIF Usage
Section titled “Unsupported GIF Usage”GIFs are not supported as values for background-image, border-image, or mask-image. Further support and enhancements for
these CSS properties are not planned.
The following patterns will not produce an animated result in Gameface:
/* Unsupported: GIF as a CSS background will not animate */.chat-reaction-button { width: 64px; height: 64px; background-image: url("spinning_star.gif");}
/* Unsupported: GIF as a CSS mask will not animate */.avatar-mask { mask-image: url("animated_mask.gif");}Playing Videos (<video>)
Section titled “Playing Videos (<video>)”While GIFs work for tiny emoji-sized animations, the preferred and more effective solution for anything larger is to use the <video> element.
Gameface provides full support for the standard HTML <video> element, including playback of both opaque and transparent videos.
Supported Formats and Codecs
Section titled “Supported Formats and Codecs”Gameface requires videos that meet these specifications:
- The container format must be WebM .
- The video track must be encoded with VP8 or VP9 .
- If audio is needed, it must be a single audio track encoded in Vorbis .
The supported standard attributes are src, autoplay, loop, muted, and preload="auto".
Common Video Patterns
Section titled “Common Video Patterns”Depending on your UI needs, configure the <video> element to achieve different behaviors. Below are the most common patterns for game UI.
Background Looping Video (Main Menu)
Section titled “Background Looping Video (Main Menu)”For a dynamic main menu background, combine autoplay, loop, and muted to start the video immediately without interfering with the engine’s menu
music:
<video width="1920" height="1080" src="main_menu_bg.webm" autoplay loop muted></video>Synchronized UI Sequences (Loot Box, Reveal Animations)
Section titled “Synchronized UI Sequences (Loot Box, Reveal Animations)”For one-off UI animations like a loot box opening, you want the video ready to play immediately when the user triggers the action. Use
preload="auto" to preload all keyframe data in advance so there is no buffering delay on playback:
<video id="lootbox-video" width="800" height="600" src="lootbox_open.webm" preload="auto"></video>Generating a Video Preview (Thumbnail)
Section titled “Generating a Video Preview (Thumbnail)”Gameface does not render video frames unless the video is actively playing or has been seeked to a specific time. To display a static preview frame without starting playback, seek the video element to the desired timestamp. The following snippet forces the first frame to render as a thumbnail:
const videoElement = document.getElementById("tutorial-video");videoElement.currentTime = 0;Encoding Videos with ffmpeg
Section titled “Encoding Videos with ffmpeg”Regardless of what video editing software you use for authoring, encoding your final assets with ffmpeg is recommended. It consistently produces strong decoding performance with its default VPX encoder settings, and no additional encoder options are typically required.
A basic transcoding command takes an input file and converts it to WebM with VP9 video and Vorbis audio:
ffmpeg -i VideoIn.mp4 -c:v libvpx-vp9 -b:v 1M -c:a libvorbis -b:a 128k VideoOut.webmFor higher visual quality, use two-pass encoding. The first pass analyzes the source and generates statistics, while the second pass uses that data to produce an optimally compressed output:
ffmpeg -i VideoIn.mp4 -c:v libvpx-vp9 -b:v 1M -an -pass 1 -f webm NULffmpeg -i VideoIn.mp4 -c:v libvpx-vp9 -b:v 1M -c:a libvorbis -b:a 128k -pass 2 VideoOut.webmEncoding Transparent Videos
Section titled “Encoding Transparent Videos”Transparent videos are useful for overlaying animated elements (character portraits, ability effects, UI transitions) on top of other content without
a solid background. To enable the alpha channel in the VPX encoder, add the -pix_fmt yuva420p flag:
ffmpeg -i TransparentSource.mov -c:v libvpx-vp9 -b:v 1M -pix_fmt yuva420p -c:a libvorbis -b:a 128k TransparentOut.webmIf your source is a sequence of transparent PNG frames rather than a single video file, pass the frame pattern as input:
ffmpeg -i sequence-%05d.png -c:v libvpx-vp9 -b:v 1M -pix_fmt yuva420p TransparentOut.webmSeek Performance
Section titled “Seek Performance”Most video compression formats store only incremental changes between frames, with full image data stored at specific intervals called keyframes .
When you seek to an arbitrary point in the video, the decoder must start from the nearest previous keyframe and apply all intermediate frame changes to reconstruct the target frame. If your video has long stretches without keyframes, a single seek operation can require hundreds of frames to be decoded before the target frame is ready to display.
Gameface provides several custom APIs to help manage seek performance.
Fast seeking to the nearest keyframe.
Section titled “Fast seeking to the nearest keyframe.”The cohfastseek HTML attribute (or the HTMLMediaElement.cohFastSeek JS property) forces any seek operation to snap to the nearest keyframe instead
of decoding all intermediate frames:
<video src="cinematic.webm" cohfastseek></video>Reading keyframe positions.
Section titled “Reading keyframe positions.”The cohGetKeyframeTimestamps() method returns an array of all keyframe timestamps (in seconds) once the video metadata has been parsed. You can use
this to build seek controls that only target valid keyframe positions:
const video = document.getElementById("cinematic-video");const keyframes = video.cohGetKeyframeTimestamps();// Example result: [0, 1.5, 5, 12.3, ...]Pre-buffering keyframe data.
Section titled “Pre-buffering keyframe data.”The cohPrebufferKeyframe(timestamp) method pre-buffers the encoded data for a specific keyframe so that a subsequent seek to that timestamp can
begin decoding immediately without waiting for data to load from disk or network:
const video = document.getElementById("cinematic-video");video.cohGetKeyframeTimestamps().forEach((t) => video.cohPrebufferKeyframe(t));Video Playback Events
Section titled “Video Playback Events”Gameface supports the standard media playback events on the <video> element, including durationchange, ended, pause, play, playing,
seeked, seeking, timeupdate, volumechange, and error.
In addition, Gameface fires two custom events that are particularly useful when synchronizing video playback with other UI animations:
cohplaybackstalled: Fired when the video decoder cannot keep up with the playback rate and is unable to provide new frames quickly enough. If you are running CSS or JavaScript animations that need to stay in sync with the video, pause those animations when this event fires.cohplaybackresumed: Fired when the decoder has caught up and normal playback resumes. Resume any synchronized animations at this point.
The following example keeps a subtitle overlay animation in sync with a cinematic video that may experience momentary decoding delays:
const video = document.getElementById("cinematic-video");const animatedOverlay = document.getElementById("subtitle-overlay");
video.addEventListener("cohplaybackstalled", () => { animatedOverlay.style.animationPlayState = "paused";});
video.addEventListener("cohplaybackresumed", () => { animatedOverlay.style.animationPlayState = "running";});Video Performance Considerations
Section titled “Video Performance Considerations”Video playback performance depends on three primary factors:
- Bitrate: Lower bitrate reduces the amount of data the decoder must process per second, improving performance. Variable bitrate (VBR) encoding
produces better visual quality but can spike in high-motion scenes. If you use VBR, consider setting an upper limit with ffmpeg’s
-maxrateflag. - Resolution: Higher resolution increases the per-frame pixel data that must be displayed. Unlike bitrate, resolution is constant throughout playback, making it a fixed and predictable performance cost.
- Transparency: Adds up to 60% more decoding data and roughly 25% more display data compared to opaque videos.
Because video compression reuses frame data from previous frames and only encodes the differences, the actual decoding cost varies frame-to-frame depending on how much motion and scene change occurs. Sequences with rapid movement or frequent cuts will be more expensive to decode than static or slow-panning footage.
High-Performance Alternatives
Section titled “High-Performance Alternatives”While the <video> element is suitable for pre-rendered sequences and background loops, it is not the best tool for every animated element in your
UI. Video decoding consumes CPU cycles, and preloading large GIFs consumes RAM. For many common game UI animation patterns, Gameface supports more efficient approaches .
Sprite Sheet Animations (For 2D Assets)
Section titled “Sprite Sheet Animations (For 2D Assets)”For standard 2D UI animations (glowing icons, looping loading spinners, simple character idles, particle effects), sprite
sheets are the preferred technique. Instead of loading a video file or a GIF, a sprite sheet packs all animation frames into a single
image. You then animate the background-position via CSS to step through each frame.
This approach completely bypasses video decoding. The engine only needs to shift a texture offset on an already-loaded image, making it lightweight and allowing instantaneous playback with no buffering delay.
Live Views (For 3D Assets and Heavy Media)
Section titled “Live Views (For 3D Assets and Heavy Media)”If your design requires complex 3D character portraits, rotating inventory item previews, or streaming heavy video content, embedding pre-rendered video files directly in the DOM is not the recommended approach.
Live Views allow you to stream a live render texture directly from the game engine into your frontend layout. The engine renders the 3D scene or video on its side and pushes the result as a texture that your UI element displays. This integrates real-time 3D content and heavy media into your UI layout without the overhead of packaging and decoding video files in the HTML layer.
© 2026 Coherent Labs. All rights reserved.