Building Animated Covers for Video with Sprites

Kawandeep Virdee
Embedly Notes
Published in
5 min readMay 27, 2016

--

Last week we introduced animations for mobile covers based on jpeg sprites. This is a technical workaround for browser limitations, specifically iOS disabling video autoplay on mobile web. While GIFs work for animations, they are large and can take a while to load on mobile compared to sprites.

See the animated covers in action. If you view this on mobile, it too will be an animated sprite.

This hasn’t been the first time sprites have been used in media for animations, you can see a prototype by NPR here and their inspiration here.

I found it was possible to use a similar method described in those posts, but a bit simpler. To begin, the initial problem is slightly different. They are converting GIFs to sprites, in our case, we are taking stills from the video and creating a sprite. The two parts of the process are (1) creating the sprite sheet, and (2) animating the sprite. The general process is to stack the frames, and then animate with CSS.

Creating the Sprite

Once you have the image stills the first step is to combine them to form a strip. ImageMagick is awesome for this.

To stack the images, you can run the following command:

convert frames_*.jpg -append sprite.jpg

Where the frames are labeled consecutively, for example: frames_00.jpg, frames_01.jpg, etc.

I’m going to run it a few frames of a video, dimensions 450×254 px:

The first frame of the animation

To further reduce the size of the sprite sheet, you can reduce the quality of the jpg. The quality can be reduced and still look great on mobile. I run the same frames to make a sprite sheet of 30 frames. For this example, at 100% it is 828K, at 60% it is 448K and at 40% it is 328K. You can compare the resulting frames here. On desktop the differences are apparent, but animating on mobile they become less noticeable. For comparison, the GIF comes at 2.7M, which is 8 times the size of the sprite sheet. Now imagine that bandwidth reduction scaled up to thousands of users.

Another trick is to add -interlace Plane to the ImageMagick call to have the sprite sheet load progressively. This means that the image loads blurry and then more clear. For lower bandwidth connections, like on mobile, this makes a difference. You can also strip the meta info of the image, more on that here.

Animating the Sprite with CSS Animations

Now that we have the sprite sheet, we can animate it.

The sprite sheet. It kind of almost animates when you scroll down.

Notice when you scrolled it kind of animated. Maybe sort of just a bit. What we want to do next is set the image as a background to some div, and then cycle through it consistently. The cool thing is that this can be done pretty elegantly in CSS.

In this case I create a div and give it a class name “animation”. First we will set the background image, and the size of the div to be the width and height of a single frame:

.animation {
background-image: url(‘http://i.imgur.com/EdWjn94.jpg');
background-position: 0px 0px;
width: 450px;
height: 254px;}

In order to animate it I have to create a new animation that runs through the full height of the image. Basically I change the background position. The height is the total height of the image (frame height ×number of frames).

@keyframes play{
100% { background-position: 0 -7620px; }
}

And to the CSS we name the keyframe we just defined as the animation, the duration of the animation, and to loop it forever.

animation: play 2.5s infinite ;

Now you’ll see the frames animate, but it is slow then fast then slow. It’s a strange transition. In order to step through it consistently, we’ll use steps() which specifies the number of steps for the animation.

animation: play 2.5s steps(30) infinite ;

It’s kind of fun to play with the number of steps to get interesting frame artifacts. Notice though that by change the duration you can change the framerate of the animation now. Here is the sprite animating now:

Feels like a GIF, but it’s not.

Here it is at a different framerate:

See the code here: https://jsfiddle.net/u6ryogb4/2

Make it Responsive

Okay, we’re almost done. The thing is that our videos are responsive. The animated cover should also be responsive. Based on this post, we can add a few things to make it responsive. The width and the height are variable, and this is reflected in the CSS. For the div holding the animation, the height is set to 0 and a padding is added based on the frame dimensions. The background-size is not based on pixels anymore, but number of frames ×100%, so in this case 3000%.

width: 100%;
height: 0;
padding-bottom: 56.44%; // height/width * 100%
display: block;
background-size: auto 3000%;

And the animation is updated from pixels to percent, reflecting the update in background-size:

@keyframes play{
100% { background-position: 0 -3000%; }
}

Here is the new responsive animation:

See the code here: https://jsfiddle.net/u6ryogb4/4/.

Space Considerations Across Aspect Ratios

In running the tests, mobile animations were set to be at width 450px, making this decision based on the mobile screen size. However, in testing we noticed if the videos are vertical or square, this can significantly increase the size of the loading sprite sheet. For these cases the vertical height is limited to 450px (adjusting width accordingly), and for square videos each side is scaled to 350px. The result is that the animation size is reduced, while still giving a preview for the video.

Additional Benefits of Sprite Animations

The sprites can be programmatically controlled to play or stop, or adjust framerate. Frames can also be programmatically set, to do things like set the animation to certain frames based on events.

There you have it! The intention was to create a dynamic preview to the video that could work on mobile and be low bandwidth. You can try out the mobile covers by making a video, and adding a cover. When it is viewed in mobile, it will have the animated sprite cover and on desktop it will have a video cover.

If you found this post or the code samples helpful, please click the ❤ to help spread it. Thanks for reading!

--

--

Building. Author of “Feeling Great About My Butt.” Previously: Creators @Medium, Product @embedly, Research @NECSI. http://whichlight.com.