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 F Mor­ton.

Video with transparency in Chrome, Edge, Firefox, Safari, iOS and Android, circa 2022 (updated in late 2024)

Transparent video

The narration of this post was created with Bespoken plugin for Craft CMS.

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 with an alpha chan­nel and it will work every­where.

But, as I write this post in Jan­u­ary 2022, and have updat­ed in 2024, after much research and try­ing dif­fer­ent approach­es, I have 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 Desk­top
  • 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.

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.

controls = 1 to show player controls color = This parameter specifies the color that will be used in the player's video progress bar to highlight the amount of the video that the viewer has already seen. Valid parameter values are red and white, and, by default, the player uses the color red in the video progress bar. See the YouTube API blog for more information about color options. Note: Setting the color parameter to white will disable the modestbranding option.

Start with good source material

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

My source video was uncom­pressed and enor­mous. I used Adobe After Effects to trim and resize it to meet my needs. The video had no audio chan­nel on the video. This was per­fect for my needs. Not hav­ing audio allows me to auto­play the video using Javascript. 

I also resized the video dimen­sions. Tip: web video does not have to be the tra­di­tion­al video aspect ratio.

As shown in the fol­low­ing screen­shot, I export­ed that video using Apple ProRes 4444 XQ. This will result in a file that is 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 hardware

Before going fur­ther, you should know I use an Apple Sil­i­con Mac, a Mac­Book Pro. If you’re on any oth­er plat­form, your results may vary. I use the hard­ware accel­er­a­tion option set to OSX VideoTool­box” in one of the video con­ver­sions we’ll dis­cuss below. The option does­n’t exist on a PC. This does­n’t mean you need a Mac, but I don’t have the hard­ware to test on oth­er plat­forms. (Since writ­ing this post, I’ve spo­ken with a few PC users who were unsuc­cess­ful in their attempts in gen­er­at­ing the H265 video. I’ve helped a few of these peo­ple cre­ate their video con­ver­sions.)

Shutter Encoder

After many tests, I chose 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: When I orig­i­nal­ly wrote this post, I used Shut­ter Encoder ver­sion 15.7 for the encod­ing process. I worked on encod­ing anoth­er video, as described here, using Shut­ter Encoder ver­sion 15.9, which 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 soft­ware.

Update, 25MAY2023: I recent­ly cre­at­ed a video with an alpha chan­nel, as described in this post. I’m hap­py to report that Shut­ter Encoder ver­sion 17.1, the cur­rent ver­sion as of May 2023, suc­cess­ful­ly encodes the alpha chan­nel. Based on the changel­og, it looks like this was fixed in Shut­ter Encoder ver­sion 16.8.

Update, 29OCT2024: I don’t reg­u­lar­ly make H265 videos, so I only revis­it this top­ic occa­sion­al­ly. As of today, in Octo­ber 2024, the most cur­rent ver­sion of Shut­ter Encoder is 18.5. Unfor­tu­nate­ly, that ver­sion no longer cor­rect­ly pro­duces the H265 video with the alpha chan­nel. I do not know at what ver­sion num­ber it broke. For­tu­nate­ly, you can down­load old­er ver­sions of Shut­ter Encoder. By using ver­sion 17.1, Shut­ter Encoder will still work to cre­ate videos with an alpha chan­nel that works in Safari.

Creating a webm version of the video

I’ve made two ver­sions of the video. The first is a .webm ver­sion. Shut­ter Encoder allows you to pre­serve the alpha chan­nel when you cre­ate 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.

Creating an H.265 version of the video, i.e., 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. Unfor­tu­nate­ly, in my tests, Safar­i’s .webm video sup­port 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? We will do that, but it’s not the tra­di­tion­al H.264 video you may be famil­iar with.

After some 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 codec 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 chan­nel.

Using Shut­ter 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­ter 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 accel­er­a­tion.

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.

The code is not read in this audio file. See the orig­i­nal arti­cle for the code block.

<video muted playsinline id='ambientVideo'>
 <source src="~@/assets/my_video_H.265.mp4" type='video/mp4;codecs=hvc1'>
 <source src="~@/assets/my_video_VP9.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. I will use this to trig­ger the ani­ma­tion with an inter­sec­tion observ­er, which 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 web browsers which think they know how to play a .mp4 try to play the video but are unsuc­cess­ful 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 dis­play­ing.

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 in your envi­ron­ment.

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 the code in this post, too.

The code is not read in this audio file. See the orig­i­nal arti­cle for the code block.

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. This code could be made to be more reusable, but it works for this pur­pose.

What does this code do?

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

Check out the Inter­sec­tion Observ­er options if you want to cus­tomize when the Inter­sec­tion Observ­er trig­gers. For 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 set­tings.

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 ele­ment.

Good luck!