Getting video to render on canvas on iOS

playah.js Render HTML video on canvas by tweaking the currentTime attribute.

Inlining video components although mostly useful on mobile is used to be less than straightforward to achieve on iOS because it lacks used to lack support for using video as a source for the canvas drawImage() method. Instead, it's possible to programmatically advance the playhead position at an even pace much like you would when manually fiddling with a tape roll. First create an off screen video element for hosting input data,

// Set up video source, note automatic preload problematic on iOS
const source = document.createElement('video')

source.setAttribute('src', '/path/to/video.mp4')
source.load()

Then prepare for adjusting the currentTime attribute to match the interval or delta since the last update call, as is common practice with sprite based animations,

// Last update timestamp
let then

// Flag on if playing
let busy = false

// Advance playhead before rendering
function update(now) {
  const step = now - (then || now)

  if (busy) {
    source.currentTime += step * 0.001

    // Reset
    if (source.currentTime >= source.duration) {
      source.currentTime = 0

      busy = false
    }
  }

  // Reset
  then = time
}

Then pasting the latest video frame onto the target canvas is as simple as,

const target = document.querySelector('canvas').getContext('2d')

function render() {
  target.drawImage(source, 0, 0)
}

But of course only trigger the animation once the video is playback ready,

source.addEventListener('loadstart', () => {
  // Safe to call
  window.requestAnimationFrame(repeat)
})

function repeat(t) {
  update(t)
  render()

  window.requestAnimationFrame(repeat)
}

Module & demo code in full is @thewhodidthis/playah ›

Reference