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 less than straightforward to manage on iOS because it lacks support for using video as a source for the canvas drawImage() method. The trick is to 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 and demo code in full, thewhodidthis/playah →

Reference