@ -17,13 +17,8 @@ import { useEffect, useRef, useState } from "react";
export function useVideoBlobUrl ( videoUrl : string | null ) : string | null {
export function useVideoBlobUrl ( videoUrl : string | null ) : string | null {
const [ blobUrl , setBlobUrl ] = useState < string | null > ( null ) ;
const [ blobUrl , setBlobUrl ] = useState < string | null > ( null ) ;
const prevBlobUrlRef = useRef < string | null > ( null ) ;
const prevBlobUrlRef = useRef < string | null > ( null ) ;
const prevInputRef = useRef < string | null > ( null ) ;
useEffect ( ( ) = > {
useEffect ( ( ) = > {
// Input unchanged — skip
if ( videoUrl === prevInputRef . current ) return ;
prevInputRef . current = videoUrl ;
// Revoke previous blob URL
// Revoke previous blob URL
if ( prevBlobUrlRef . current ) {
if ( prevBlobUrlRef . current ) {
URL . revokeObjectURL ( prevBlobUrlRef . current ) ;
URL . revokeObjectURL ( prevBlobUrlRef . current ) ;
@ -47,11 +42,13 @@ export function useVideoBlobUrl(videoUrl: string | null): string | null {
setBlobUrl ( videoUrl ) ;
setBlobUrl ( videoUrl ) ;
let cancelled = false ;
let cancelled = false ;
let createdUrl : string | null = null ;
fetch ( videoUrl )
fetch ( videoUrl )
. then ( ( r ) = > r . blob ( ) )
. then ( ( r ) = > r . blob ( ) )
. then ( ( blob ) = > {
. then ( ( blob ) = > {
if ( cancelled ) return ;
if ( cancelled ) return ;
const url = URL . createObjectURL ( blob ) ;
const url = URL . createObjectURL ( blob ) ;
createdUrl = url ;
prevBlobUrlRef . current = url ;
prevBlobUrlRef . current = url ;
setBlobUrl ( url ) ;
setBlobUrl ( url ) ;
} )
} )
@ -61,6 +58,10 @@ export function useVideoBlobUrl(videoUrl: string | null): string | null {
return ( ) = > {
return ( ) = > {
cancelled = true ;
cancelled = true ;
// If a blob URL was created after we decided to cancel, revoke it
if ( createdUrl && createdUrl !== prevBlobUrlRef . current ) {
URL . revokeObjectURL ( createdUrl ) ;
}
} ;
} ;
}
}