DEV Community

Cover image for GIF Image To Media Stream
Ethan
Ethan

Posted on

4 2

GIF Image To Media Stream

Introduction

Hello! Today I had to stream a GIF image from canvas to WebRTC, I can't show the full code but I am thinking of doing a full tutorial in the future for my WebRTC series.

Libraries used:

  • Konva
  • Gifler

What is Konva?

Konva is an HTML5 Canvas Javascript framework that enables high performance animations, transitions, node nesting, layering, filtering, caching, event handling for desktop, and mobile applications etc.

What is a Konva Stage?

In simple terms a Konva Stage is used as a display that displays layers.

What is a Konva Layer?

A layer is something that can be drawn to.


What is Gifler?

A library that renders GIF frames to a canvas element.


Creating a basic HTML file

The HTML is pretty simple:

<!DOCTYPE html>
<html lang="jp">
  <head>
    <title>Canvas</title>
    <meta charset="utf-8"/>
  </head>

  <body>
    <button onclick="publish();">Publish</button>
    <div id="container"></div>

    <script src="https://unpkg.com/konva@8.3.5/konva.min.js"></script>
    <script src="https://unpkg.com/gifler@0.1.0/gifler.min.js"></script>
    <script src="./main.js"></script>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

The container is div will be used to display the GIF image.

Next the Javascript part.


Displaying the GIF image

First I created the Konva stage and the layer in a file called "main.js".

const stage = new Konva.Stage({
  container: 'container',
  width: 640,
  height: 480 
});

const layer = new Konva.Layer();
stage.add(layer);
Enter fullscreen mode Exit fullscreen mode

Once the layer is created it is added to the stage.

Next was to create the canvas element and create the "onDrawFrame" function:

const canvas = document.createElement('canvas');

const onDrawFrame = (ctx, frame) => {
  canvas.width = frame.width;
  canvas.height = frame.height;
  ctx.drawImage(frame.buffer, 0, 0); 

  layer.draw();
};
Enter fullscreen mode Exit fullscreen mode

Then read the image and add it to the Konva layer:

gifler('./200.gif').frames(canvas, onDrawFrame);

const image = new Konva.Image({
  image: canvas
});

layer.add(image);
Enter fullscreen mode Exit fullscreen mode

The frames from the GIF file will be processed via the "onDrawFrame" function, which is then drawn to the canvas.


From Canvas to MediaStream

Once the Publish button is clicked the following happens:

const publish = async () => {
  try {
    const mediaStream = await navigator.mediaDevices.getUserMedia({ video: false, audio: true });
    const audioTrack = mediaStream.getAudioTracks()[0];

    if (!audioTrack) {
      alert('no audio');

      return;
    }

    const localCanvas = document.getElementsByTagName('canvas')[0];
    const canvasStream = localCanvas.captureStream(30);
    const canvasTrack = canvasStream.getVideoTracks()[0];

    if (!canvasTrack) {
      alert('failed to get video track');

      return;
    }

    console.log('got audio and video tracks');
    mediaStream.addTrack(canvasTrack);

    // Add the stream to a PeerConnection etc.    
  } catch (error) {
    console.error(error);
  }
};
Enter fullscreen mode Exit fullscreen mode

The above basically calls "getUserMedia" to obtain the user's mic only.
Once done "captureStream" is called with an argument of 30 FPS, the canvas video track is obtained and finally we add the canvas video track to the media stream object.

Once done you can then stream the media stream object via an RTCPeerConnection, which I will go over in more detail in the near future.

Note you can use the captureStream function on a canvas displaying anything it doesn't have to be a GIF.


Conclusion

Today I learned about both the Konva and Gifler libraries.

TBH I probably didn't need to use Konva and could have probably done the same with Gifler. ๐Ÿ˜…
But it was a good learning experience. ๐Ÿ˜ƒ


Like me work? I post about a variety of topics, if you would like to see more please like and follow me.
Also I love coffee.

โ€œBuy Me A Coffeeโ€

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (0)

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

๐Ÿ‘‹ Kindness is contagious

Please leave a โค๏ธ or a friendly comment on this post if you found it helpful!

Okay