Seamless video looping on iOS

June 19, 2013

A difficult problem that developers often run into with iOS is how to loop videos. Using AVPlayer does not work. Well, it sort of works, but the results you end up with do not look professional. Under iOS, hardware is used to render h.264 streams and that works well for most videos. But, short videos do not work well because of lag when starting the video. A developer will run into frustrating glitches attempting to loop a video and to switch from one short video to another. AVPlayer just was not designed for this. Here are a couple of stackoverflow examples of this sort of question:

Since this kind of animation problem comes up over and over again, this post will provide a concrete example of seamless looping using the AVAnimator library. A lot of time was spent on this library specifically to solve the problem of looping video clips and starting playback at exactly the right moment. In this example, these three video clips will be combined into very simple demo Xcode project.


As you can guess from the third animation, a bug will get zapped. The implementation will switch from the plain bug animation cycle to the zap loop at certain times. I could have implemented things with a more complex zap overlay layer that sits over the existing bug animation, but this example will just keep things as simple as possible and use 2 bug animations. Both bug animations will be 32BPP videos with an alpha channel.

The background radar animation loop is an animated GIF found online. The GIF can be attached to the Xcode project file as a normal file and decoded with existing GIF support in AVAnimator. In addition to the 2 bug animation videos, I also added a CoreAnimation scale CABasicAnimation to make the bug jump over the radar line. The results look like this:


Of course, the animations look a lot better when run on the simulator or on a device. This example is configured as either an iPhone or iPad project and the Xcode project can be found on github.

All of the animation logic can be found in the ViewController.m file. The key to understanding why this implementation is able to seamlessly loop the radar animation and quickly switch between bug animations is because AVAnimator will decode animation data and store the video pixels in an optimal format on disk. When switching between the bug walk cycle animation and the zap cycle animation the library need only choose between two cached video files sitting on disk.

The implementation means that an app can switch from any video to any other video very quickly. This example only switches between 2 videos but the approach would work equally well if there were 10 or 50 videos to switch between. Seamless looping of the background radar video is the same, simply begin reading from the start of the cached video file at the end of the loop. Seamless looping logic is already implemented by AVAnimator, see the source code for example code showing how easy it is to setup animations and callbacks.

This example does not include sound. If you are interested in an example that also includes sound clips, see this StreetFighter 2 example project.