Timing Media Clips

Media elements (Multimedia) report buffered (downloaded), seekable and played spans as TimeRanges: length plus start(i) and end(i) in seconds. Ranges are ordered and merged, so a gap appears as a second entry.

Reading buffered, seekable and played rangesJavaScript
const video = Object.assign(document.createElement('video'),
  { muted: true, src: 'https://mdn.github.io/shared-assets/videos/flower.webm' });
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const show = (r) => Array.from({ length: r.length },
  (_, i) => `${r.start(i).toFixed(1)}-${r.end(i).toFixed(1)}`).join(', ');
video.addEventListener('loadedmetadata', async () => {
  video.currentTime = 1;   await video.play(); await sleep(1000);   // play from 1.0 s
  video.currentTime = 3.5; await sleep(500);   video.pause();       // skip ahead
  for (const name of ['buffered', 'seekable', 'played']) {
    console.log(`${name}: ${show(video[name])}`);
  }
});
Output
buffered: 0.0-5.1
seekable: 0.0-5.1
played: 1.0-2.0, 3.5-3.8

The small file downloaded completely, so buffered holds one range. Re-read it on each progress event. start() and end() throw an IndexSizeError for an out-of-range index, such as end(0) before any data arrives, so check length first.