Optimising for faster Image Loading for Indian Vernacular Users

Bolo is a video Question & Answer platform that allows users to ask and answer questions. Answers are short videos less than 1 minute each and questions range from a variety of topics including Beauty & Fashion, Cooking to Career Counselling.

Bolo Team
Bolo
6 min readMar 4, 2019

--

By Chirag Maheshwari

Home screen of Bigo Live vs Bolo App immediately after home screen loading at <200 kbps internet speeds

There was a time when people would wait for things to load on web and mobile. Internet was slow and people wouldn’t complain if some app took more than 10 seconds to load the feed. But now the times have changed and people expect things to load as soon as they open it. When something doesn’t load for a while people start complaining and most of them would quit the app.

While India has seen rapid adoption of 4G thanks to the Jio wave, the internet speeds are still slow and unreliable in many places. As a platform whose vast majority of users are from tier 2&3 cities this is a challenge that we need to keep in mind while building our product.

Bolo app’s home page consists of questions relevant to the user and thumbnail of their answers, thus a major portion of the screen is composed of images. These thumbnails are a deciding factor for user to select which answer to watch.

Bolo App’s home screen uses a lot of images

The Problem

At slow internet speeds, when user launches the Bolo app, while the user is able to see all the questions’ text, their answers show a generic placeholder thumbnail for a few seconds (ex. the Bigo image above) leading to an incomplete user experience.

This happens because the home screen data which contains data of questions and answers along with their thumbnail url is fetched first. The actual thumbnails are loaded separately after home screen data is fetched successfully. This causes the delay that we see in loading the thumbnails on the home screens.

The Solution

Multiple Variants of the Image

The first solution that popped out was to create multiple variants of the thumbnails. We have three different places in our app where we load the thumbnail, each one of different dimension where we used the thumbnails of the same size. So we made three variants of the images: small (320 pixels max height), medium (640 pixels max height), large (960 pixels max height); keeping the width as per the aspect ratio.

We then simply used the different variants of the images at different places in our app. This made it better for a lot of devices with decent internet connection. But still, on devices where internet speed is as low as 100 KBPS, it would take quite a lot of seconds to load the lowest quality images in the feed.

Blurred Preview

We then thought, what if we could show a basic blurred preview of the images as soon as the feed loads instead of the placeholder image. This would make the experience significantly better as it would give the user an idea of what is about to load and the feeling that something is about to load. We stumbled upon this blog post from the Facebook engineering team which explains the working of the preview technology in detail. Though it works pretty well, they have done lot of changes to the original JPEG format, removing the headers and sending only the data which is combined with pre-stored fixed JPEG headers on the app itself and then decoded to the raw pixel data to show the image. All this to save on the number of bytes.

But we wanted something simpler but also as effective and since we were to send this preview image’s encoded data in our feed API itself, the size mattered. So then while searching for some solution to this, we found out about webp. This is a new image compression format by Google, having lossless images 26% smaller in size compared to PNGs and lossy images 25–34% smaller than comparable JPEG images at equivalent SSIM quality index.

JPEG vs WebP (credits: @andysolomon)

Used WebP as opposed to JPEG to save on the image size

WebP format is natively supported in Android apps and it reduces the image size significantly without compromising the quality of the image.

We stored the Base64 encoded WebP image data with a limit of 42 pixels in the largest dimension, maintaining the aspect ratio. Along with this, we reduce the quality of the image to 10% to reduce its size to ~200bytes. This allows us to store the thumbnail in the database itself and we send it along with the API to fetch a user’s home screen. So this eliminates the separate network request for the preview thumbnail and the blurred previews can be shown instantly as soon as the feed loads.

data:image/webp;base64,UklGRsQAAABXRUJQVlA4ILgAAABwBgCdASoYACoAP22gvVi0q6WjsAqqkC2JaAClrCFcBnRUWCbiSjs8ht6VgaD9Swd4qZfk0Yp3QJKkTgAA/c6n0ZnJxKTt2iPEiWXjiX/nGE0k6IJpuJRYJYtHP8jcvl7HxNsmZkbFZJBR4xPdlhIk0m1xNBTtbGBNxG2FA7L6bG1R76HSB0rGsRXMfJIkzp977d9HoU0K0cbuU8dR8RjPn6Q8ETYKMIJzFLDGuOP7FVhxGWN8khoA
24 x 42 pixels preview image at 10% quality (204 Bytes)

Blurring and Scaling on Android

After we’ve compressed the image, we’ve reduced the size significantly but are left with an image which isn’t aesthetically pleasing. For this we decided to generate a blurred version which looks much better and at the same time give an idea of what’s in store to the user. We have used Glide transformations to first scale the image to the size of ImageView (keeping aspect ratio) and then applying a Gaussian Blur with a radius of 25.

scaled (180 x 320) and blurred version. Blurred version looks much more pleasing and conveys what’s in store as well.

Multiple thumbnail variants using AWS Lambda

To prepare multiple variants of thumbnails on the fly as soon as new image is uploaded and convert them to webp, we used AWS Lambda. From their documentation, “AWS Lambda is a compute service that runs your code in response to events and automatically manages the compute resources for you, making it easy to build applications that respond quickly to new information”.

We use AWS S3 buckets for storage of the images. So we linked the Lambda function to trigger on any ObjectCreated event on that particular S3 bucket.

The basic flow for image processing goes as follows:

Image processing flow on AWS
  1. Our servers upload the new thumbnail image to the source S3 bucket.
  2. The bucket emits an event which is listened by our AWS Lambda function.
  3. The function then processes the images and stores them in the target bucket.

This is very simple to configure on the AWS console, more details regarding this can be found here.

size comparison between different variants of images

Lambda Code for Image Conversion

The code is self explanatory and the inline comments will make reading the code easier. For any help/issues, feel free to comment on the gist.

Summary

While building for India, optimising every aspect of the product for slow internet and weak devices is crucial. By using a blurred preview and appropriate size thumbnail we were able to enhance our user experience significantly.

India is rapidly moving forward with 100s of millions of Indians coming online for the first time every year. The product challenges that they face are unique in the world with slow internet speeds, weak devices and dozens of languages.

We at Bolo are committed to solving these problems and are passionate about building world class products to propel India forward. We have multiple openings across tech and ops, if you are among those who feel strongly about the India story, do hit us up at contact@theboloapp.com

--

--