SuperGeekery: A blog probably of interest only to nerds by John F Morton.

A blog prob­a­bly of inter­est only to nerds by John Morton.

18Jan2022

Video with trans­paren­cy in Chrome, Edge, Fire­fox, Safari, iOS and Android, cir­ca 2022

Transparent video

This post on using video with a trans­par­ent back­ground will prob­a­bly not age well. At least I hope that is the case! Ide­al­ly, in the future, you can use a sin­gle .webm video file and it will work everywhere. 

But, as I write this post in Jan­u­ary 2022, after a full day of research and try­ing dif­fer­ent approach­es, I’ve got a <video> tag that will play a video with a trans­par­ent back­ground across a wide vari­ety of browsers.

  • Chrome
  • Fire­fox
  • Safari on Desktop
  • Safari on iPhone
  • Android

I assume that the oth­er browsers based on Chromi­um will also work, although I’ve not test­ed them when I write this. 

If you’re try­ing to get a video with trans­paren­cy work­ing, let me show you what I’ve done. I hope this saves you some time.

Source mate­r­i­al

I’m lucky in that I’m start­ing with a nice short piece of pro­fes­sion­al­ly-pro­duced video with an alpha chan­nel. If you don’t have an alpha chan­nel in your source video, you need to solve that prob­lem first.

The source video I had was very big. I used Adobe After Effects to trim and resize it to meet my needs. I want­ed no audio chan­nel on the video which allows me to auto­play the video using Javascript. I also resized the video dimen­sions. Pro tip: web video does not have to be the tra­di­tion­al video aspect ratio.

I export­ed that video using the Apple ProRes 4444 XQ. This will result in a file that is still not usable on the web, but it will be ready for the next step in the process.

After effect video export settings

After Effect Output Module Settings

My hard­ware

Before going fur­ther, you should know I am using an Apple Sil­i­con Mac, a Mac­Book Pro. If you’re on any oth­er plat­form, your result may vary since I use the hard­ware accel­er­a­tion option in one of the video con­ver­sions we’ll dis­cuss below. This does­n’t mean you need a Mac, but I don’t have the hard­ware to test on oth­er platforms.

Shut­ter Encoder

After many tests, I’ve cho­sen Shut­ter Encoder as the best encoder for this process. I tried FFm­peg, Hand­brake, Adobe Media Encoder, and sev­er­al oth­er online video encod­ing ser­vices. None of them worked as well as Shut­ter Encoder, which is free. If you find the app use­ful, you should sup­port the author. I did because I like the soft­ware I use to stick around.

Update, 10MAY2022: Dur­ing the encod­ing process, I used Shut­tle Encoder, ver­sion 15.7. I worked on encod­ing anoth­er video as I describe here using ver­sion 15.9 and it failed. Based on what I’ve read, there is some issue with FFM­PEG in ver­sions after 15.7. Rein­stalling ver­sion 15.7 allowed me to con­tin­ue to con­vert videos suc­cess­ful­ly. I hope the bug is fixed in future ver­sions of the software.

Cre­at­ing a webm ver­sion of the video

I’ve made two ver­sions of the video. The first is a .webm ver­sion. Shut­ter Encoder will allow you to pre­serve the alpha chan­nel when you’re cre­at­ing your webm. Let’s review the options I used.

Shutter Encoder settings for webm video

Shutter Encoder settings for creating .webm with alpha channel

Add your source video in the Choose files area then select VP9 as your func­tion. Under the Advanced fea­tures area, choose Enable alpha chan­nel.

Now click the Start func­tion but­ton and gen­er­ate your .webm video.

Cre­at­ing an H.265 ver­sion of the video, and not an H.264 video

Now that Safari added sup­port for .webm, you might be won­der­ing why we’re mak­ing anoth­er ver­sion of the video at all. In my tests, Safar­i’s sup­port of .webm video does­n’t include sup­port for the alpha chan­nel. A black back­ground is shown where you’d expect the trans­paren­cy to be used. 

Why not use an .mp4 with an alpha chan­nel? That’s what we’re going to do, but it’s not the tra­di­tion­al H.264 video you may be famil­iar with. 

After a lit­tle online research, you may incor­rect­ly dis­cov­er the .mp4 video file does not sup­port an alpha chan­nel. This was my assump­tion, too, but I was con­flat­ing an mp4 file and an H.264 video file as the same thing. There is a dif­fer­ence though. H.264 is the codec, the piece of soft­ware, that con­verts the uncom­pressed video into a stream of com­pressed bits. The file­type, .mp4 (or .webm, or .avi, etc.) con­tains the stream of video and/​or audio. 

In oth­er words, the .mp4 file can use the H.264 codec. The H.264 cod­ed does­n’t sup­port hav­ing an alpha chan­nel. But there is a new­er codec called H.265. Spoil­er alert: it sup­ports the alpha channel.

Using Shut­tle Encoder again, make the H.265 ver­sion of the video. Let’s review the options I used.

Shutter Encoder settings for H.265 video

Shutter Encoder settings for creating .mp4 with alpha channel

There are three options in the screen­shot above. 

After you’ve added your source video, select H.265 as your func­tion. Under the Advanced fea­tures area, the Enable alpha chan­nel option should be checked auto­mat­i­cal­ly. Also, turn on the Hard­ware accel­er­a­tion option. In my tests, the hard­ware accel­er­a­tion was the only way to get Shut­tle Encoder to cre­ate the alpha chan­nel suc­cess­ful­ly. Depend­ing on your com­put­er, you may achieve dif­fer­ent results when using hard­ware acceleration. 

Now click the Start func­tion but­ton and gen­er­ate your .mp4 video.

The video tag for your HTML

Let’s look at <video> tag I’m using.

<video muted playsinline id='ambientVideo'>
  <source src="~@/assets/my_video_H.265_2.mp4" type='video/mp4;codecs=hvc1'>
  <source src="~@/assets/my_video_VP9_3.webm" type="video/webm">
</video>

This video tag is for a small ani­ma­tion that plays inline and it has no audio. You can see those para­me­ters at the begin­ning of the video tag. I also have an id of ambientVideo which I use to trig­ger the ani­ma­tion with an Inter­sec­tion Observ­er that I’ll describe at the end of this post. (Read more about the options for the video tag in the MDN Web Docs.)

The two most impor­tant things are the order of the source tags and the type of each source.

The .mp4 source tag is the first tag. Browsers will see this as the first source, and if they can play it, that’s the one they’ll choose to use. In my tests, Safari on desk­top and on mobile will use this. Be sure you’ve got the type set to include the codecs por­tion. With­out that, you’ll find browsers that think they know how to play a .mp4 try­ing to play that video unsuc­cess­ful­ly because they are not aware of the hvc1 codec. 

Next, include the link to the .webm source. This is what most browsers will end up displaying.

In case you’re won­der­ing, the ~@/assets path is how I refer to the root of my pub­lic fold­er. You need to use the path to the video that makes sense to your environment.

Bonus: Play video when it appears on the screen

In my video tag, I’ve got an ID of ambientVideo.

I’ve post­ed the Javascript file I’m using in this gist: ambient-video-play-on-enter.js

Since you are here already, I’ll share it in this post too. 

var ambientVideo = document.getElementById("ambientVideo");

var io = new IntersectionObserver(
  entries => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        ambientVideo.play();
      } else {
        ambientVideo.pause();
      }
    });
  },
  {
    root: null,
    rootMargin: "0px",
    threshold: 0.5
  }
);

// after confirming the element exists, look for the #ambientVideo when visible in viewport
if (ambientVideo) {
  io.observe(ambientVideo)
}

In the first line, I look for my video tag with the id of ambientVideo. Next, I cre­ate a new Inter­sec­tionOb­serv­er. Yes, this code could be made to be more reusable, but it works for this purpose. 

What does this code do?

Basi­cal­ly, when the video ele­ment comes into frame, we tell it to play. When it leaves the frame, it gets paused. 

If you want to cus­tomize when the Inter­sec­tion Observ­er trig­gers, check out the Inter­sec­tion observ­er options. As an exam­ple, my thresh­old set­ting of 0.5 means I want to detect the vis­i­bil­i­ty of my video when 50% of it is vis­i­ble. You may need dif­fer­ent settings.

To make it work, I have the Inter­sec­tion Observ­er that I cre­ate start observ­ing, look­ing for the ambientVideo video element. 

Good luck!