Coding a Countdown Timer in OBS

Coding a Countdown Timer in OBS

Today we're building a super useful widget - a countdown timer! Watch a narrated timelapse of coding the widget from scratch in our YouTube video below, and grab the final source code at the bottom of this article. You can customize it, change the font, tweak the CSS, and make it fit your channel!

Watch the Timelapse

Watch Coding a Countdown Timer in OBS on YouTube

About the Timer

This timer counts down to the top of the next hour, by default. This works great for most events - you can just start your stream ~10 minutes early, queue up this scene, and it counts down to the hour! But you can also set a custom target time - there's an example in the code near var target.

Using the Timer

To use this widget in OBS:

Get the Code

 Copy<!DOCTYPE>
<html style="background:none">
  <head>
    <!-- https://fonts.google.com/specimen/Paytone+One -->
    <link rel="preconnect" href="https://fonts.gstatic.com">
    <link href="https://fonts.googleapis.com/css2?family=Paytone+One&display=swap" rel="stylesheet">

    <style>
     body {
       color:#fff;
       font-family: "Paytone One";

       opacity:0;
       transition: opacity 0.2s ease;
       text-align:center;
       font-size:20vw;
     }

     /* You'll need to adjust these 1.3 and 0.7 widths if you change the font */
     span.section {
       display: inline-block;
       width: 1.3em;
       max-width: 1.3em;
     }
     span.section.half {
       width: 0.7em;
       max-width: 0.7em;
     }
     span.section.wunset {
       width:unset;
       max-width:unset;
     }
    </style>
  </head>
  <body>
  </body>
  <script>
    setTimeout(function() {
      document.body.style.opacity = "1";
    }, 1500);

    // Uncomment this line to count to a specific time:
    //var target = "Tue Jan 12 2021, 8:38 pm MST";
    var target = ""; // empty means top of the next hour
    var tgt;
    if (target=="") {
      tgt = new Date(); // now
      tgt.setMinutes(0); // start of this last hour
      tgt.setSeconds(0); // start of this last hour
      tgt = new Date(tgt.getTime()+3600*1000); // Plus an hour
    } else {
      tgt = new Date(target); // Whatever time you specify
    }

    function double_zero(i) {
      return i<10 ? "0"+i : i;
    }
    function get_section(v, dz, align) {
      var v = dz==false ? v : double_zero(v);
      var cls = (dz==false && v<10) ? "section half" : "section";
      if (v==0) cls += " wunset";
      return "<span class='"+cls+"' style='text-align:"+align+"'>"+v+"</span>";
    }
    setInterval(function() {
      var now = new Date();

      // Countdown
      var dt = Math.floor((tgt.getTime() - now.getTime())/1000);

      var d_s = dt;
      var d_m = Math.floor(d_s / 60);
      d_s = d_s % 60;

      var d_h = Math.floor(d_m / 60);
      d_m = d_m % 60;

      // Stick at zero:
      if (dt < 0) {
        d_h = 0; d_m = 0; d_s = 0;
      }

      var hours = d_h > 0 ? get_section(d_h, false, "right") + ":" : "";
      var minutes = hours=="" ? get_section(d_m, false, "right") + ":" : get_section(d_m, true, "center") + ":";
      document.body.innerHTML = hours + minutes + get_section(d_s, true, "left");
    }, 1000);
  </script>
</html>