How can I detect if AVIF image is animated?

375 Views Asked by At

Is there a way to detect if an AVIF image is animated using plain JavaScript only?

2

There are 2 best solutions below

6
Kaiido On BEST ANSWER

The new ImageDecoder API can tell this to you.

You'd pass a ReadableStream of your data to it, and then check if one of the decoder's tracks has its animated metadata set to true:

if (!window.ImageDecoder) {
  console.warn("Your browser doesn't support the ImageDecoder API yet, we'd need to load a library");
}
// from https://colinbendell.github.io/webperf/animated-gif-decode/avif.html
fetch("https://colinbendell.github.io/webperf/animated-gif-decode/6.avif").then((resp) => test("animated", resp.body));
// from https://github.com/link-u/avif-sample-images cc-by-sa 4.0 Kaede Fujisaki
fetch("https://raw.githubusercontent.com/link-u/avif-sample-images/master/fox.profile1.8bpc.yuv444.avif").then((resp) => test("static", resp.body));

document.querySelector("input").onchange = ({target}) => test("your image", target.files[0].stream());


async function test(name, stream) {
  const decoder = new ImageDecoder({ data: stream, type: "image/avif" });
  // wait for we have some metadata
  await decoder.tracks.ready;
  // log if one of the tracks is animated
  console.log(name, [...decoder.tracks].some((track) => track.animated));
}
<input type=file>

However beware this API is still not widely supported, since only Chromium based browsers have an implementation currently.

0
boylett On

Turns out this (seems to be) criminally easy with JavaScript.

Written in TypeScript for posterity:

/**
 * Sniff for an animated AVIF byte
 * @param buffer 
 * @returns boolean
 * @example
 * `return sniffAVIF(
 *   new Uint8Array(
 *     await uploadedFile.arrayBuffer()
 *   )
 * )`
 */
const sniffAVIF = (view: Uint8Array) =>
  return view[ 3 ] === 44;

Yes, really!

The first few bytes of every AVIF file (that I have tested at least) tend to look pretty much the same when loaded as a Uint8Array;

0, 0, 0, 44, 102, 116 for animated files

0, 0, 0, 28, 102, 116 for static files

So fairly trivial to discern one from the other. Of course, I have only been able to test this on a limited number of images, so please do feel free to correct me if you can find an AVIF that doesn't start with this series of bytes.

Hope this helps!