hotwired / turbo

The speed of a single-page web application without having to write any JavaScript
https://turbo.hotwired.dev
MIT License
6.65k stars 421 forks source link

Videos with autoplay keep playing after a page change #1017

Open n-studio opened 11 months ago

n-studio commented 11 months ago

If I play a video with the autoplay attribute, and then go to another page using Turbo, the video (that is supposed to be removed from the DOM) plays again. The video is not visible but the audio still plays.

If I disable Turbo, the video will stop when changing to a new page as expected.

Same if I remove the autoplay attribute, it won't replay the video when changing to a new page.

<video controls="controls" autoplay="autoplay" loop="loop" src="/video.mp4"></video>
<a href="/page2" data-turbo="true">Then go to page 2</a>

Here is a repository reproducing the issue: https://github.com/n-studio/turboVideoBug

It will occur on Safari, Firefox and Chrome on macOS Sonoma.

domchristie commented 11 months ago

You may find the alternative solution here useful: https://github.com/turbolinks/turbolinks/pull/432 (Event names need updating to turbo rather than turbolinks)

n-studio commented 11 months ago

Thank you! 🙏

n-studio commented 11 months ago

Is there any plan to port your PR to hotwired/turbo?

seanpdoyle commented 11 months ago

Is there a possibility that some of the work done in https://github.com/hotwired/turbo/pull/1019 might improve this experience?

domchristie commented 11 months ago

Is there any plan to port your PR to hotwired/turbo?

@n-studio no plans yet, sorry (I have tended to avoid autoplay because it's not reliable in Safari due to their autoplay policy.)

Is there a possibility that some of the work done in https://github.com/hotwired/turbo/pull/1019 might improve this experience?

@seanpdoyle Possibly, although from the sounds of things, #1019 only affects page refreshes. The problem here is that autoplay elements get cloned to the cache, and start playing behind-the-scenes. I've not gone through the PR fully, but it looks like the cloning behaviour still exists.

scuml commented 6 months ago

This is still occurring in Turbo 7 and 8. This is an updated version of @domchristie 's workaround by until I can start on a PR.

/* Store autoplay elements so Turbo does not play them while updating the snapshot */
let autoplayIds = []
document.addEventListener('turbo:before-cache', () => {
  const autoplayElements = document.querySelectorAll('[autoplay]')
  autoplayElements.forEach((element) => {
    if (!element.id) throw 'Turbo requires autoplay elements to have an ID attribute'
    autoplayIds.push(element.id)
    element.removeAttribute('autoplay')
  })
})

document.addEventListener('turbo:before-render', (event) => {
  autoplayIds = autoplayIds.reduce((ids, id) => {
    const autoplay = event.detail.newBody.querySelector(`#${id}`)
    if (autoplay) autoplay.setAttribute('autoplay', true)
    else ids.push(id)
    return ids
  }, [])
})