DEV Community

Jonas Birmé for Eyevinn Video Dev-Team Blog

Posted on

Service to generate preview image from HLS stream

This is an example of how you could write a service that on-the-fly generates a preview image or video from an HLS stream. Before we start, why would you need this type of service? One use case is that you want to add basic metadata for a web page containing video and you want that metadata to include a poster image or preview video. For example:

    <title>Video Page</title>
    <script src=""></script>
    <eyevinn-video source="" muted="true" autoplay="true"></eyevinn-video>
Enter fullscreen mode Exit fullscreen mode

It would be nice to have a poster when sharing this web page in social media. You can add that by adding the open graph tag og:image with a URL to an image. And here is where this service becomes relevant. It will on request generate an image from the HLS in question and you could use it this way by adding this metadata tag to the header.

  <meta property="og:url" content="" />
Enter fullscreen mode Exit fullscreen mode

A live example below:

poster image example

As you can see a very neat way of obtaining a poster image of an HLS stream.

How does it work?

The source code for this service is available on GitHub and released under open source so you are welcome to use and contribute to it.

It is a micro service written in NodeJS and uses ffmpeg for the video processing. It provides two endpoints /image and /video who both takes two query parameters u and pos where the second one is optional. The parameter u contains the urlencoded URL to the HLS stream.

Once this endpoint is requested it fetches and parses the HLS.

const m3u = await fetchAndParseHLS(searchParams.get("u"));
Enter fullscreen mode Exit fullscreen mode

then it fetches the media chunk closes to the value of parameter pos (in seconds). If not provided it will assume the first media chunk.

const segmentUrl = findSegmentAtPosition(m3u, pos).get("uri");
Enter fullscreen mode Exit fullscreen mode

The URL to the media chunk is then passed to a function that renders a PNG from this media chunk.

const data = await renderPngFromTS(segmentUrl);
Enter fullscreen mode Exit fullscreen mode

It returns a binary buffer containing the image data. This binary data is in response to the client request with the Content-Type set to image/png.

To process the media chunk we use ffmpeg:

ffmpeg -y -i <media-chunk-url> -ss 1 -t 1 -f mjpeg <outputfile-path>.png
Enter fullscreen mode Exit fullscreen mode

The outputfile name is generated based on an md5 hash of the media chunk url. We then read the file and store the content in a buffer.

const data = readFileSync(outputFilePath);
Enter fullscreen mode Exit fullscreen mode

This micro service is also available as a public container if you want to use it directly.

docker run --rm -p 8000:8000 eyevinntechnology/hlspreview:<version>
Enter fullscreen mode Exit fullscreen mode


To make this service scale we use cache directives and place a CDN in front. Important when configuring the CDN property is to make sure to include the query parameters in the cache key and part of identifying the cached resource. In this example we set an max-age of 3600 seconds (1 hour) in the response, which would offload this service for all requests for the very same image to be generated. In this example setup we are running the container on AWS ECS using an AWS ELB to access it and AWS Cloudfront as CDN. A setup that could easily be replicated to another cloud infrastructure as it does not contain any AWS specific functions.

Hope you found this interesting and inspiring. Let me know if you have any questions or thoughts. You find me on Twitter in addition to here.

About Eyevinn Technology

Eyevinn Technology is an independent consultant firm specialized in video and streaming. Independent in a way that we are not commercially tied to any platform or technology vendor.

At Eyevinn, every software developer consultant has a dedicated budget reserved for open source development and contribution to the open source community. This give us room for innovation, team building and personal competence development. And also gives us as a company a way to contribute back to the open source community.

Want to know more about Eyevinn and how it is to work here. Contact us at!

Top comments (1)

tachib_shin profile image
Tachibana Shin

awesome this is what i was looking for. can i use this live service for open source projects? does it have any limit?