three version: ^0.159.0
@react-three/fiber version: ^9.0.0
@react-three/drei version: latest (confirmed by reading current master source)
node version: N/A (reproducible across versions)
npm (or yarn) version: N/A
Problem description:
useVideoTexture uses suspend-react to cache the <video> element creation, keyed by [srcOrSrcObject]. When a component using useVideoTexture unmounts (e.g. by changing a key prop), the cached video element persists and continues playing in the background.
The current cleanup effect only destroys the HLS instance but does not pause or dispose the underlying video element, nor does it evict the suspend-react cache entry:
useEffect(() => {
start && texture.image.play()
return () => {
if (hlsRef.current) {
hlsRef.current.destroy()
hlsRef.current = null
}
// no video.pause(), no video.src = "", no cache eviction
}
}, [texture, start])
The VideoTexture component does call texture.dispose() on unmount, but that only disposes the Three.js texture object - the HTML <video> element that suspend-react keeps in its cache remains alive and playing.
Expected behavior: when a component using useVideoTexture unmounts, the underlying <video> element should be paused and cleaned up, and the suspend-react cache entry should be evicted.
Steps to reproduce:
- Render a component that uses
useVideoTexture with a video source
- Switch to a different video by changing a
key prop (causing unmount + remount with a new source)
- Unmute audio - you can hear both videos playing simultaneously
- Switch back - the timestamp of the previous video is preserved (it never stopped)
Relevant code:
Minimal reproduction repo: https://github.com/mohamedtahaguelzim/drei-video-bug
- Clone,
npm install, npm run dev
- Use the buttons to switch videos and unmute
- Open the console to observe mount/unmount logs - the cached video persists despite unmounting
Suggested solution:
The cleanup effect in useVideoTexture should:
- Pause the video element (
video.pause())
- Clear the video source (
video.removeAttribute('src'); video.load())
- Dispose the texture
- Evict the
suspend-react cache entry using clear() with the matching key ([srcOrSrcObject])
This follows the same cleanup pattern already used by WebcamVideoTexture and ScreenVideoTexture.
Fix submitted in #2714.
threeversion: ^0.159.0@react-three/fiberversion: ^9.0.0@react-three/dreiversion: latest (confirmed by reading currentmastersource)nodeversion: N/A (reproducible across versions)npm(oryarn) version: N/AProblem description:
useVideoTextureusessuspend-reactto cache the<video>element creation, keyed by[srcOrSrcObject]. When a component usinguseVideoTextureunmounts (e.g. by changing akeyprop), the cached video element persists and continues playing in the background.The current cleanup effect only destroys the HLS instance but does not pause or dispose the underlying video element, nor does it evict the
suspend-reactcache entry:The
VideoTexturecomponent does calltexture.dispose()on unmount, but that only disposes the Three.js texture object - the HTML<video>element thatsuspend-reactkeeps in its cache remains alive and playing.Expected behavior: when a component using
useVideoTextureunmounts, the underlying<video>element should be paused and cleaned up, and thesuspend-reactcache entry should be evicted.Steps to reproduce:
useVideoTexturewith a video sourcekeyprop (causing unmount + remount with a new source)Relevant code:
Minimal reproduction repo: https://github.com/mohamedtahaguelzim/drei-video-bug
npm install,npm run devSuggested solution:
The cleanup effect in
useVideoTextureshould:video.pause())video.removeAttribute('src'); video.load())suspend-reactcache entry usingclear()with the matching key ([srcOrSrcObject])This follows the same cleanup pattern already used by
WebcamVideoTextureandScreenVideoTexture.Fix submitted in #2714.