Recently a technical challenge came my way that involved auto playing video on mobile devices. This isn’t technically possible though because data is not loaded unless the user initiates the request. So my adventure in trying to workaround this issue began, and lucky for me - the internets most famous media, gif, came to save the day.
Where to start and Why
I knew the HTML5
<video> tag was out, so I had to think of something else. A couple of ideas came to mind.
Change up the UX
The best choice is to change the user experience to make video playback and explicit interaction. Unfortunately, this was not an option. The experience called for a celebratory video to automatically play once a few decisions were made. We needed the video to feel like a surprise that would encourage users about the decisions they did make. For this reason, switching the user experience really wasn’t on the table.
Essentially the idea here is to export every frame of a movie as an image (JPG or PNG if you need a transparent background) and then merging each frame into a gigantic filmstrip. Each filmstrip could then be loaded in as a background image and animated with
requestAnimationFrame, moving the image left as per the width of each frame.
There are some difficult challenges here.
- file size - this solution results in a large amount of data and would not be appropriate for a mobile solution.
- long term maintainability- this requires creating a video player resulting in greater overhead and potential for technical debt over time.
- performance - this solution has technical challenges from a performance perspective that might decrease the UX quality
This solution is definitely doable. I’ve done it previously and it worked great for those projects. If you don’t have the limitations I mentioned above in your project, it’s worth exploring. Unfortunately, the project requirements I had made this a non-starter.
After thinking through the above, I asked myself - “Why can’t I use a gif?”
Seriously, why not? I know that we use it on blogs, presentations and more - but we could use it as an alternative to video. Thinking through what we needed, I came up with the following requirements:
- Autoplay media
- Only loop once
- No need for sound
Because of these low level requirements, GIF seems to be the perfect choice. Mobile devices do not limit autoplay for GIF’s. You can control the number of loops for a GIF. There is no sound.
Creating GIF’s from video
There are multiple ways to generate GIF’s from video, but the easiest way I was able to do this efficiently was through the use of ffmpeg. What is ffmpeg?
ffmpeg is a very fast video and audio converter that can also grab from a live audio/video source. It can also convert between arbitrary sample rates and resize video on the fly with a high quality polyphase filter.
As part of the installation instructions below I’ve also included ImageMagick, for reasons that will be explained later in this article.
So lets get started by installing ffmpeg and ImageMagick.
Installing with Homebrew
This is definitely optional, but I do prefer to use homebrew to install dependencies. If you don’t already have this installed, all you need to do is run this command in your terminal:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
If you already have homebrew installed, its always a good idea to ensure brew is updated. You can do this with the update command:
This way you ensure that you 1) have the latest version of homebrew and 2) have the latest formulae references.
Installing ffmpeg and ImageMagick
Now that you have homebrew installed, all you need to do is install it:
brew install ffmpeg imagemagick
Installing with a Package Installer
If you just want to get it installed on your computer and get going quickly, you can simply download the package installer for ffmpeg here. And for ImageMagick you can install it from here. For both these packages make sure to follow the directions as per their advice on each page.
Once you have ffmpeg installed, you’re ready to go. If you have a source video you would like to convert (input.mp4) - you can simply run:
ffmpeg -i input.mp4 output.gif
This will generate an
output.gif file in the directory you are currently in. To make this more video like, we’ll want to set the GIF to loop only once. This is where it gets a bit tricky.
From ffmpeg’s documentation, it seemed that I could use the
-loop option to specify the number of loops the GIF should play. In my particular use case, I wanted it to only loop once. I assumed that the command
ffmpeg -i input.mp4 --loop 1 output.gif would work, but the resulting gif wouldn’t play. I needed to look for another solution to help me out.
Luckily, we’ve got ImageMagick as a solution, which also contains an option for setting the loop value of a GIF. Since we already have a GIF, all we need to do is tell ImageMagick to set the loop to play once and to output the updated gif:
convert -loop 1 output.gif output.gif
This command will essentially produce a new GIF with the loop value set to 1. By keeping the name the same, we’re just overwriting our GIF. Now we have a GIF that functionally works and mimics a video being played automatically.
A sample of the GIF this default output would produce:
Optimizing your exported GIF’s
Compared to the picture quality of a video, GIF’s just can’t compete by default. Once I had a GIF that worked functionally I was pretty happy with it, but I did notice the picture quality was funky. There were a lot of artifacts and honestly it couldn’t compete with the picture quality of the original video source. So another adventure had started - optimizing the quality of my GIF.
GIF’s are palette based, each frame basing their RGB values by 256 different colors in a default palette. Because there might be unused or missing colors in the palette, the quality of the GIF will be lower. To fix this, we essentially need to apply a color palette that encompasses the average color scheme throughout the video.
Generating a Color Palette
FFmpeg library comes with a filtering component called ffmpeg-filters that contains a palette generator. This creates a color palette based on a whole video stream. To generate this palette we can do:
ffmpeg -v warning -i tango.mp4 -vf fps=15,scale=320: -1:flags=lanczos,palettegen -y palette.png
Let’s break this down to something we can understand.
ffmpegis the command we’re using
-v warningsets the logging level to warning
-i tango.mp4is the input we want to send to
-vfis defining the filters we want to use against the source
- In this case we’re setting the following:
- Set the
fpsor frames per second to 15
- Scale the video, with
scale, to 320px
- Use the
- and ultimately use the
palettegenfilter to generate a palette
- Set the
- In this case we’re setting the following:
palette.pngTells the filter to output the generated palette to the location specified (in this case
If this all sounds like magic to you, you’re not alone - this was definitely how I felt when I first went through this. With some time reading through documentation and experimentation this made some sense to me. But if you’re still confused I would definitely recommend reading
Applying the Palette
Now that we have a palette that is a true representation of our video, we can now apply to the source video to generate a higher quality GIF. To do this, we can simply run a similar command:
ffmpeg -i input.mp4 -i palette.png -filter_complex "fps=15,scale=320: -1:flags=lanczos[x];[x][1:v]paletteuse" output.gif
Similar to previous commands, we use the ffmpeg command to define the input and output source. Between these we specify another input to use the
palette.png generated in the last step. We also define the filter(s) to be used, which can be adjusted as per your preference. In this case we ensure that the frames per second is 15, the scale is set to 320 and that we use the lanczos rescaling algorithm as a flag.
In the example we’ve been following the generated GIF would then look like:
Phew! So whats this about again?!
Autoplaying a movie on mobile isn’t supported and for good reasons. However, if the needs of your experience calls for this kind of value - it isn’t the end of the world. We can utilize GIF’s to simulate a video experience.
Generating a GIF is super easy, just use
ffmpeg ! If you really need to have something a bit more precise, you can utilize the filtering tools inside of
ffmpeg to generate a 256 color palette to be applied during the GIF generation process.
Once you have the high quality GIF you were looking for, you can replace your video for a GIF on mobile and deliver a similar experience. The obvious drawback is sound, which is pretty important - luckily we also have a solution for that. In my next article, I’ll be covering how to play audio with your new awesome GIF.