{"course":{"slug":"motion-and-audio","title":"Motion, Sound and Music","url":"https://addaly.com/learn/motion-and-audio","level":"intermediate","track":"create"},"lesson":{"slug":"alpha-on-the-web","title":"Transparent video, and why it is two files","url":"https://addaly.com/learn/motion-and-audio/alpha-on-the-web","position":23,"of":72,"minutes":10,"answer":"No single video file carries alpha everywhere: VP9 in WebM covers Chrome and Firefox, HEVC with the hvc1 tag covers Safari, and the luma-matte workaround doubles the frame width and requires WebGL.","keyIdea":"No single video file carries alpha everywhere: VP9 in WebM covers Chrome and Firefox, HEVC with the hvc1 tag covers Safari, and the luma-matte workaround doubles the frame width and requires WebGL, so the first question is whether the background is genuinely arbitrary."},"body":{"format":"markdown","text":"## The request that sounds simple\n\n\"Can we have the animated logo float over the photograph, with the background showing through?\" This is a transparent video, and it is the single most annoying request in web motion, because the format support is poor and the workarounds all have costs.\n\nThe reason is historical. Video codecs were built for broadcast and cinema, where there is no background behind the frame. Alpha was bolted on afterwards, by different people, in incompatible ways.\n\n## What actually exists\n\n**VP9 with alpha, in WebM.** The pixel format is `yuva420p`: the extra `a` is the alpha plane. Supported in Chrome, Firefox and Edge. Not in Safari. Encode with:\n\n```bash\nffmpeg -i in.mov -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 0 -crf 32 out.webm\n```\n\nYour source has to carry alpha to begin with: ProRes 4444, QuickTime Animation, or a PNG sequence. Export from your editor with \"RGB + Alpha\" and a codec that supports it, or the alpha never existed.\n\n**HEVC with alpha, in MP4.** Safari only, on macOS and iOS. Apple documents the requirement precisely: the video track must use the `hvc1` tag rather than `hev1`, and the alpha is carried as an auxiliary layer. It is encodable from Apple's own tools and from ffmpeg builds with `videotoolbox`, and it is not encodable everywhere.\n\nSo the working answer on the web today is **two files and a source-order fallback**: HEVC-alpha MP4 first for Safari, VP9-alpha WebM second for everyone else. Both have to be produced, both have to be tested, and if either is missing a large share of users see a black box.\n\n**Animated WebP and APNG** both carry real 8-bit alpha and are supported everywhere. They are images, so they are far larger than video and cannot be paused, but for a short loop under a couple of seconds they are frequently the pragmatic answer.\n\n## The luma-matte trick\n\nWhen the two-file route is unacceptable, the standard workaround is to put the colour and the transparency in the same ordinary video, side by side: the image on the left half of the frame, a black-and-white matte of its alpha on the right. One file, any codec, universal support.\n\nAt playback, a small WebGL shader (or a canvas loop, more slowly) reads both halves each frame and writes the matte's luminance into the output's alpha channel. Several open-source implementations exist; the technique is old and comes from broadcast, where a \"fill and key\" pair has always been two signals.\n\nThe costs are real and worth stating: the frame is twice as wide, so you are paying for more pixels; the matte is compressed lossily along with everything else, so soft edges pick up ringing; and you now require WebGL, which excludes anyone with it disabled and adds a code path to maintain.\n\n## The option people forget\n\nAsk whether the background is arbitrary.\n\nVery often the \"transparent\" video is going over one known colour, or one known photograph. If so, composite it in the edit, export an ordinary opaque MP4, and the whole problem disappears along with 60 per cent of the file size. The number of transparent-video requests that survive this question is smaller than you would expect, and asking it takes ten seconds.\n\nIf the content is vector (a logo, an illustrated character, a line animation) the right answer is almost always **Lottie or SVG**, which have transparency for free because they are drawings rather than rectangles of pixels. Transparent video is for filmed or rendered raster content specifically.\n\n## Checking that alpha survived\n\nThe failure mode is silent: your file plays, the background is black, and you cannot tell whether the alpha is missing or being ignored. Check the file rather than guessing.\n\n```bash\nffprobe -v error -select_streams v:0 \\\n  -show_entries stream=pix_fmt,codec_name -of default=nw=1 out.webm\n```\n\nIf `pix_fmt` is `yuv420p` rather than `yuva420p`, the alpha was discarded at encode: usually because the source did not have it, or because a filter in the chain dropped it. `-vf format=yuva420p` early in the chain fixes a surprising number of these.\n\nThe other common cause is **premultiplied versus straight alpha**, covered properly in the compositing module. If your edges have a dark or light fringe rather than being cleanly transparent, the alpha survived and is being interpreted with the wrong convention.\n\n## Performance notes\n\nAn alpha video is decoded with an extra plane, so it costs more memory and more decode time than the same clip opaque: roughly 30 to 50 per cent in practice. On a low-end phone, a full-screen alpha video at 60fps is not realistic, and the fallback should be a static image rather than a stuttering one.\n\nSet `poster` on the video element so that something sensible is visible before the first frame decodes, and remember that a looping decorative video is continuous motion: it belongs behind the reduced-motion check.\n\n## The free path\n\n**ffmpeg** encodes VP9 with alpha, converts sequences, builds side-by-side mattes with the `hstack` filter, and probes the result, all free. **Blender** renders with a transparent film and exports ProRes 4444 or a PNG sequence. **DaVinci Resolve**'s free edition exports alpha in several formats. **Kdenlive** and **Shotcut** both handle alpha sources. The gap in the free toolchain is HEVC-with-alpha encoding, which in practice requires an Apple machine.\n\n## The limitation\n\nThere is no single file today that carries video with alpha and plays everywhere. Every route above is a compromise: two files and double the testing, an image format and a size penalty, or a shader and a dependency. Anybody who tells you otherwise has tested on one browser.\n\nThis will probably improve (AVIF sequences carry alpha and support is growing) but treat any claim of universal support as something to verify on a real Safari and a real Android device before it goes in a plan."},"check":{"question":"An alpha video plays but the transparent areas render black. ffprobe reports pix_fmt as yuv420p. What does that tell you?","options":[{"text":"The alpha is present but premultiplied, and the player is interpreting it as straight alpha, which multiplies the colour by zero in the transparent regions.","correct":false,"tempting":"A real class of bug, but it produces fringing on edges rather than a fully black background, and it would not change the reported pixel format."},{"text":"The browser is falling back to the MP4 source because the WebM failed a codec check, so you are seeing an opaque file that was never meant to carry alpha.","correct":false,"tempting":"Plausible as a delivery fault, but ffprobe was run on the file itself, so the answer is in the encode rather than in source selection."},{"text":"The alpha plane was discarded during encoding, because a pixel format without the trailing 'a' has no channel to store it in.","correct":true},{"text":"The alpha plane is present but stored in a separate auxiliary track that ffprobe does not list under the primary video stream, which is the normal arrangement for VP9 and means the file is correct and the fault is in the CSS compositing of the video element against its parent background.","correct":false,"tempting":"Describes how HEVC-alpha stores its layer; VP9 carries alpha in the pixel format itself, which is exactly what the probe reports."}]},"prev":{"slug":"gif-is-not-a-video-format","title":"Why a GIF costs twenty times what a video costs","url":"https://addaly.com/learn/motion-and-audio/gif-is-not-a-video-format"},"next":{"slug":"sprite-sheets","title":"Frames in a grid, and the memory they cost","url":"https://addaly.com/learn/motion-and-audio/sprite-sheets"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'Transparent video, and why it is two files', in Motion, Sound and Music. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/motion-and-audio/alpha-on-the-web (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"Transparent video, and why it is two files","courseTitle":"Motion, Sound and Music","module":{"index":3,"slug":"shipping-the-motion","title":"Shipping the motion"},"answer":null,"keyIdea":"No single video file carries alpha everywhere: VP9 in WebM covers Chrome and Firefox, HEVC with the hvc1 tag covers Safari, and the luma-matte workaround doubles the frame width and requires WebGL, so the first question is whether the background is genuinely arbitrary.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"the-request-that-sounds-simple","runs":[{"text":"The request that sounds simple"}]},{"t":"p","runs":[{"text":"“Can we have the animated logo float over the photograph, with the background showing through?” This is a transparent video, and it is the single most annoying request in web motion, because the format support is poor and the workarounds all have costs."}]},{"t":"p","runs":[{"text":"The reason is historical. Video codecs were built for broadcast and cinema, where there is no background behind the frame. Alpha was bolted on afterwards, by different people, in incompatible ways."}]},{"t":"h2","id":"what-actually-exists","runs":[{"text":"What actually exists"}]},{"t":"p","runs":[{"text":"VP9 with alpha, in WebM.","b":true},{"text":" The pixel format is "},{"text":"yuva420p","code":true},{"text":": the extra "},{"text":"a","code":true},{"text":" is the alpha plane. Supported in Chrome, Firefox and Edge. Not in Safari. Encode with:"}]},{"t":"code","lang":"bash","label":"Bash","text":"ffmpeg -i in.mov -c:v libvpx-vp9 -pix_fmt yuva420p -b:v 0 -crf 32 out.webm"},{"t":"p","runs":[{"text":"Your source has to carry alpha to begin with: ProRes 4444, QuickTime Animation, or a PNG sequence. Export from your editor with “RGB + Alpha” and a codec that supports it, or the alpha never existed."}]},{"t":"p","runs":[{"text":"HEVC with alpha, in MP4.","b":true},{"text":" Safari only, on macOS and iOS. Apple documents the requirement precisely: the video track must use the "},{"text":"hvc1","code":true},{"text":" tag rather than "},{"text":"hev1","code":true},{"text":", and the alpha is carried as an auxiliary layer. It is encodable from Apple’s own tools and from ffmpeg builds with "},{"text":"videotoolbox","code":true},{"text":", and it is not encodable everywhere."}]},{"t":"p","runs":[{"text":"So the working answer on the web today is "},{"text":"two files and a source-order fallback","b":true},{"text":": HEVC-alpha MP4 first for Safari, VP9-alpha WebM second for everyone else. Both have to be produced, both have to be tested, and if either is missing a large share of users see a black box."}]},{"t":"p","runs":[{"text":"Animated WebP and APNG","b":true},{"text":" both carry real 8-bit alpha and are supported everywhere. They are images, so they are far larger than video and cannot be paused, but for a short loop under a couple of seconds they are frequently the pragmatic answer."}]},{"t":"h2","id":"the-luma-matte-trick","runs":[{"text":"The luma-matte trick"}]},{"t":"p","runs":[{"text":"When the two-file route is unacceptable, the standard workaround is to put the colour and the transparency in the same ordinary video, side by side: the image on the left half of the frame, a black-and-white matte of its alpha on the right. One file, any codec, universal support."}]},{"t":"p","runs":[{"text":"At playback, a small WebGL shader (or a canvas loop, more slowly) reads both halves each frame and writes the matte’s luminance into the output’s alpha channel. Several open-source implementations exist; the technique is old and comes from broadcast, where a “fill and key” pair has always been two signals."}]},{"t":"p","runs":[{"text":"The costs are real and worth stating: the frame is twice as wide, so you are paying for more pixels; the matte is compressed lossily along with everything else, so soft edges pick up ringing; and you now require WebGL, which excludes anyone with it disabled and adds a code path to maintain."}]},{"t":"h2","id":"the-option-people-forget","runs":[{"text":"The option people forget"}]},{"t":"p","runs":[{"text":"Ask whether the background is arbitrary."}]},{"t":"p","runs":[{"text":"Very often the “transparent” video is going over one known colour, or one known photograph. If so, composite it in the edit, export an ordinary opaque MP4, and the whole problem disappears along with 60 per cent of the file size. The number of transparent-video requests that survive this question is smaller than you would expect, and asking it takes ten seconds."}]},{"t":"p","runs":[{"text":"If the content is vector (a logo, an illustrated character, a line animation) the right answer is almost always "},{"text":"Lottie or SVG","b":true},{"text":", which have transparency for free because they are drawings rather than rectangles of pixels. Transparent video is for filmed or rendered raster content specifically."}]},{"t":"h2","id":"checking-that-alpha-survived","runs":[{"text":"Checking that alpha survived"}]},{"t":"p","runs":[{"text":"The failure mode is silent: your file plays, the background is black, and you cannot tell whether the alpha is missing or being ignored. Check the file rather than guessing."}]},{"t":"code","lang":"bash","label":"Bash","text":"ffprobe -v error -select_streams v:0 \\\n  -show_entries stream=pix_fmt,codec_name -of default=nw=1 out.webm"},{"t":"p","runs":[{"text":"If "},{"text":"pix_fmt","code":true},{"text":" is "},{"text":"yuv420p","code":true},{"text":" rather than "},{"text":"yuva420p","code":true},{"text":", the alpha was discarded at encode: usually because the source did not have it, or because a filter in the chain dropped it. "},{"text":"-vf format=yuva420p","code":true},{"text":" early in the chain fixes a surprising number of these."}]},{"t":"p","runs":[{"text":"The other common cause is "},{"text":"premultiplied versus straight alpha","b":true},{"text":", covered properly in the compositing module. If your edges have a dark or light fringe rather than being cleanly transparent, the alpha survived and is being interpreted with the wrong convention."}]},{"t":"h2","id":"performance-notes","runs":[{"text":"Performance notes"}]},{"t":"p","runs":[{"text":"An alpha video is decoded with an extra plane, so it costs more memory and more decode time than the same clip opaque: roughly 30 to 50 per cent in practice. On a low-end phone, a full-screen alpha video at 60fps is not realistic, and the fallback should be a static image rather than a stuttering one."}]},{"t":"p","runs":[{"text":"Set "},{"text":"poster","code":true},{"text":" on the video element so that something sensible is visible before the first frame decodes, and remember that a looping decorative video is continuous motion: it belongs behind the reduced-motion check."}]},{"t":"h2","id":"the-free-path","runs":[{"text":"The free path"}],"role":"free"},{"t":"p","runs":[{"text":"ffmpeg","b":true},{"text":" encodes VP9 with alpha, converts sequences, builds side-by-side mattes with the "},{"text":"hstack","code":true},{"text":" filter, and probes the result, all free. "},{"text":"Blender","b":true},{"text":" renders with a transparent film and exports ProRes 4444 or a PNG sequence. "},{"text":"DaVinci Resolve","b":true},{"text":"’s free edition exports alpha in several formats. "},{"text":"Kdenlive","b":true},{"text":" and "},{"text":"Shotcut","b":true},{"text":" both handle alpha sources. The gap in the free toolchain is HEVC-with-alpha encoding, which in practice requires an Apple machine."}]},{"t":"h2","id":"the-limitation","runs":[{"text":"The limitation"}],"role":"limit"},{"t":"p","runs":[{"text":"There is no single file today that carries video with alpha and plays everywhere. Every route above is a compromise: two files and double the testing, an image format and a size penalty, or a shader and a dependency. Anybody who tells you otherwise has tested on one browser."}]},{"t":"p","runs":[{"text":"This will probably improve (AVIF sequences carry alpha and support is growing) but treat any claim of universal support as something to verify on a real Safari and a real Android device before it goes in a plan."}]}],"check":{"question":[{"text":"An alpha video plays but the transparent areas render black. ffprobe reports pix_fmt as yuv420p. What does that tell you?"}],"options":[{"text":[{"text":"The alpha is present but premultiplied, and the player is interpreting it as straight alpha, which multiplies the colour by zero in the transparent regions."}],"correct":false,"tempting":[{"text":"A real class of bug, but it produces fringing on edges rather than a fully black background, and it would not change the reported pixel format."}]},{"text":[{"text":"The browser is falling back to the MP4 source because the WebM failed a codec check, so you are seeing an opaque file that was never meant to carry alpha."}],"correct":false,"tempting":[{"text":"Plausible as a delivery fault, but ffprobe was run on the file itself, so the answer is in the encode rather than in source selection."}]},{"text":[{"text":"The alpha plane was discarded during encoding, because a pixel format without the trailing ‘a’ has no channel to store it in."}],"correct":true,"tempting":null},{"text":[{"text":"The alpha plane is present but stored in a separate auxiliary track that ffprobe does not list under the primary video stream, which is the normal arrangement for VP9 and means the file is correct and the fault is in the CSS compositing of the video element against its parent background."}],"correct":false,"tempting":[{"text":"Describes how HEVC-alpha stores its layer; VP9 carries alpha in the pixel format itself, which is exactly what the probe reports."}]}],"order":[0,3,1,2],"why":null},"prev":{"slug":"gif-is-not-a-video-format","title":"Why a GIF costs twenty times what a video costs","minutes":9},"next":{"slug":"sprite-sheets","title":"Frames in a grid, and the memory they cost","minutes":9}}}