Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/core/VideoTexture.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react'
import * as THREE from 'three'
import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'
import { useThree } from '@react-three/fiber'
import { suspend } from 'suspend-react'
import { suspend, clear } from 'suspend-react'
import { type default as Hls, Events } from 'hls.js'

const IS_BROWSER = /* @__PURE__ */ (() =>
Expand Down Expand Up @@ -98,13 +98,25 @@ export function useVideoTexture(
useEffect(() => {
start && texture.image.play()

// NOTE: This cleanup assumes a single consumer per srcOrSrcObject. If multiple
// components share the same source, the first to unmount will release the video
// and evict the cache, leaving others with a dead texture.
return () => {
const video = texture.image as HTMLVideoElement
video.pause()
video.removeAttribute('src')
video.srcObject = null
video.load()

if (hlsRef.current) {
hlsRef.current.destroy()
hlsRef.current = null
}

texture.dispose()
clear([srcOrSrcObject])
}
}, [texture, start])
}, [texture, start, srcOrSrcObject])

return texture
}
Expand All @@ -125,10 +137,6 @@ export const VideoTexture = /* @__PURE__ */ forwardRef<VideoTexture, VideoTextur
({ children, src, ...config }, fref) => {
const texture = useVideoTexture(src, config)

useEffect(() => {
return () => void texture.dispose()
}, [texture])

useImperativeHandle(fref, () => texture, [texture]) // expose texture through ref

return <>{children?.(texture)}</>
Expand Down