DEV Community

Cover image for Creating your own dynamic stream overlay
Adam
Adam

Posted on • Originally published at adamlearns.com

Creating your own dynamic stream overlay

Introduction

This post is for people who want a custom, dynamic overlay and know how to program.

As for why you'd want an overlay in the first place, here are common uses:

  • Displaying information
    • Latest followers
    • Commands of interest like !game or !help
    • Advertising your social-media platforms
  • Adding pizzazz
    • Fanfare for a new subscriber
    • Bursts of emotes
    • Playing sounds or music

Regarding the dynamic aspect—your streaming software can already render text and graphics. However, it may not allow for event-based triggers or animations. For example, I made a custom overlay that reads a file from my system, fades in a marquee with that text every so often, then fades it out when enough time has elapsed. With my streaming software, I only would have been able to render static text on the stream.

How do overlays work?

I use OBS, so I'll talk about its specifics here, but software like XSplit also supports this method.

OBS has a built-in "Browser" source that lets you show the contents of a webpage:

How to add a browser source in OBS

From there, you type in a file path or URL, and OBS will render whatever you would see if you had pointed your actual browser at the same page:

Customizing the browser source in OBS

That means that you "only" have to make a webpage with your overlay's contents. If you wanted something basic enough, you could write a simple HTML file with CSS animations. However, this is where game engines really shine since they're built to handle graphics, animations, and even sounds! As long as the game engine can export to HTML, then you can use it to make overlays.

I prefer to use Phaser since it's relatively easy to learn. It's also specifically intended for WebGL games, which means you can just save your JavaScript file as you're working and click "refresh cache of current page" in OBS to see your changes (as opposed to having to export a build from your game engine).

Setting up your webpage

Phaser itself can be loaded as a single JavaScript file. There are three ways you can set up your webpage:

Single HTML file

If you put everything into a standalone HTML file and load Phaser from a CDN, you won't need a web server running anywhere. On the flip side, it also means that you can't read any files from your hard drive, including JavaScript files, so you'll need to place all of your JavaScript inside the HTML file itself.

This HTML snippet will float the word "Hello" from the bottom of the screen to the top:

<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/phaser@3.23.0/dist/phaser.js"></script>
  <style>body { margin: 0; }</style>
  <script>
    let textObject = null;
    const width = 1920;
    const height = 1080;
    const phaserGame = new Phaser.Game({
      type: Phaser.WEBGL,
      scale: {
        mode: Phaser.Scale.FIT,
        width,
        height,
      },
      transparent: true,
      scene: {
        update,
        create,
      },
    });

    function update(time, delta) {
      textObject.y -= delta / 20;
    }

    function create() {
      textObject = this.add.text(0, 0, "Hello world", {
        font: "64px Lato",
        fill: "#0000ff"
      });

      textObject.x = width / 2 - textObject.displayWidth / 2;
      textObject.y = height + textObject.displayHeight;
    }
  </script>
</head>
<body></body>
</html>

You can use this as a foundational overlay via any of these three methods that I'm outlining here by saving the contents as index.html and pointing OBS at it.

Local server

Using any web server (e.g. http-server for Node.js, Python's http.server, or even something heavier like Apache's HTTP server), you can serve a directory from your hard drive and point OBS at the resulting local URL. For example, I run Node.js's server via

http-server -p 5896 .

Then, I can point OBS at http://127.0.0.1:5896

Running a web server allows you to load files from the directory that you're serving. This means that you can separate out the JavaScript from the HTML:

<html>
<head>
  <script src="phaser_3_23_0.js"></script>
  <script src="main.js"></script>
</head>
<body></body>
</html>

This has an added benefit of fetching Phaser directly from your hard drive rather than a CDN, so it will load faster.

While this works and gives you flexibility, you'll need the web server running any time you want to stream. I solve that particular problem by creating a prestream.cmd file that I run before each stream. It sets my microphone volume, starts my chat bot, and serves my stream overlays.

Online site

OBS supports using an online URL instead of a local path. This is how services like Streamlabs work; they host a page for you to use from OBS.

I only suggest putting a server online if:

  • You stream from multiple computers and want the same overlay available everywhere.
  • You want to make a generic overlay (like how Streamlabs did) that anyone can use.
  • You really dislike starting a server every time you have to stream.

Taking it further

A natural next step would be to integrate features from your streaming platform directly into your overlays. For example, when someone follows the channel, you may want to spawn fireworks in your overlay. In order to accomplish this, you would need to connect to the streaming platform's API.

I want to keep this blog post brief, so I'll just outline one possible solution for this in the form of a stream-event microservice:

  • Make a separate server, e.g. in Node.js, that will connect to the Twitch API and detect when there are new followers.
  • Connect from the overlay client to this new server via a websocket.
  • On the server, listen for a particular API event. When one occurs, emit a message over the websocket to the overlay.
  • Spawn an animation in the overlay's code.

Conclusion

Making your own overlay is a great way to achieve a specific effect and stand out from template-users. If you already know a game engine or rendering library that can output to HTML, then there's practically no setup involved. Otherwise, there'll be a bit of a learning curve, so unless you require custom functionality, then it may not be worth pursuing.

If you enjoyed this post, consider taking a look through the courses that I offer.

Top comments (0)