reading time
2 min
Creating a custom start and end screen in the player

The problem

We’ve been busy with helping customers with specific use cases. This is actually one of them. We got the question whether it would be possible to add custom HTML before the video starts and after a video has played.

For example, a custom intro could be a title, a description, a logo, a button, etc. The same goes for the outro, but this is shown after the video, for example: a form to capture an email of your customer to get updates on new videos.

So in this post, we’ll be building exactly that. Showing you an example with what’s possible. Let’s start with what you’ve probably seen before: our script, which includes some HTML and CSS by default.

<script type="module">
  import "https://cdn.video-dns.com/npm/@maveio/components/+esm";
</script>

<mave-player
  embed="ubg50lro9d5Cuzu"
  style="display: block; width: 100%; background: center / contain no-repeat url(https://space-ubg50.video-dns.com/lro9d5Cuzu/thumbnail.jpg); aspect-ratio: 16 / 9;"
></mave-player>

This simply results in our default player:

The solution

As <mave-player /> is a webcomponent, therefore we can make use of the slot attribute. This allows us to place custom HTML inside <mave-player />. For example:

<!-- slot[start-screen] is shown before the video plays and requires "height: 100%; position: relative;" for initial render -->
<div slot="start-screen" style="height: 100%; position: relative;">
  <!-- call <mave-player>.play(), which starts the video -->
  <div
    onClick="event.preventDefault(); this.closest('mave-player').play();"
    class="container"
  >
    <div class="playbutton">
      <svg
        style="width: 34px; height: 34px;"
        xmlns="http://www.w3.org/2000/svg"
        stroke="rgba(0,0,0,0.7)"
        fill="rgba(0,0,0,0.15)"
        viewBox="0 0 24 24"
      >
        <polygon
          fill-rule="evenodd"
          stroke-linecap="round"
          stroke-linejoin="round"
          stroke-width="1.1"
          points="8 19 19 12 8 5"
        ></polygon>
      </svg>
    </div>
  </div>
</div>

The trick is adding slot="start-screen" inside the component. You can use your own custom CSS and make however you like. This start-screen will only be shown before the video is played (and only once). In this example we create an overlay and use the onClick handler to start the video using this.closest('mave-player').play();. This is what you will get:

The ending however is even more cool. We can use the slot="end-screen" to show custom HTML after the video has ended. For example:

<!-- slot[end-screen] is shown after the video ends and requires "display: none" for initial render -->
<div slot="end-screen" style="display: none;">
  <div>
    <h3>
      Get notified on updates
    </h3>
    <p>
      Leave your email and we'll let you know when we release a new video.
    </p>
    <form>
      <input type="text"></input>
      <button>Subscribe</button>
    </form>
    <!-- call <mave-player>.play(), which replays the video when ended -->
    <a href="#" onClick="event.preventDefault(); this.closest('mave-player').play();">or watch it again ↻</a>
  </div>
</div>

This results in (we’re skipping to the end):

Get notified on updates

Leave your email and we'll let you know when we release a new video.

or watch it again ↻

Here’s the complete code when you combine everything together:

<mave-player id="mave_end" embed="ubg50lro9d5Cuzu" style="display: block; width: 100%; background: center / contain no-repeat url(https://space-ubg50.video-dns.com/lro9d5Cuzu/thumbnail.jpg); aspect-ratio: 16 / 9;">
  <!-- slot[start-screen] is shown before the video plays and requires "height: 100%; position: relative;" for initial render -->
  <div slot="start-screen" style="height: 100%; position: relative;">
    <!-- call <mave-player>.play(), which starts the video -->
    <div
      onClick="event.preventDefault(); this.closest('mave-player').play();"
      class="container"
    >
      <div class="playbutton">
        <svg
          style="width: 34px; height: 34px;"
          xmlns="http://www.w3.org/2000/svg"
          stroke="rgba(0,0,0,0.7)"
          fill="rgba(0,0,0,0.15)"
          viewBox="0 0 24 24"
        >
          <polygon
            fill-rule="evenodd"
            stroke-linecap="round"
            stroke-linejoin="round"
            stroke-width="1.1"
            points="8 19 19 12 8 5"
          ></polygon>
        </svg>
      </div>
    </div>
  </div>

  <!-- slot[end-screen] is shown after the video ends and requires "display: none" for initial render -->
  <div slot="end-screen" style="display: none;">
    <div>
      <h3>
        Get notified on updates
      </h3>
      <p>
        Leave your email and we'll let you know when we release a new video.
      </p>
      <form>
        <input type="text"></input>
        <button>Subscribe</button>
      </form>
      <!-- call <mave-player>.play(), which replays the video when ended -->
      <a href="#" onClick="event.preventDefault(); this.closest('mave-player').play();">or watch it again ↻</a>
    </div>
  </div>
</mave-player>

Have other ideas or feedback? We’d love to hear what you think! Join the discussion and share your thoughts on our Discord. Click here to jump in!

Published on October 31, 2023
works with
Developer?
Our docs guide you through the process of embedding video, starting with simple steps for novices and advancing to manual configurations for experienced users. It outlines multiple hosting alternatives, including a default CDN, and highlights compatibility with popular web frameworks.
script
react
vue
1
2
3
4
5
🍪 Press 'Accept' to confirm that you accept we don't use cookies. Yes, this banner is just for show!
Accept