useMediaInfo
Functions
useMediaInfo(mediaRef: RefObject<MediaElement>): MediaInfoAccess media metadata from Video or Audio ref
Returns:
MediaInfo object with intrinsicDurationMs and loading stateAccess media metadata like duration and loading state from Video and Audio components.
Import
import { useMediaInfo } from "@editframe/react";
Return Type
interface MediaInfo {intrinsicDurationMs: number | undefined; // Media duration in millisecondsloading: boolean; // True while metadata is loading}
Basic Usage
import { useRef } from "react";import { Video, useMediaInfo } from "@editframe/react";const VideoWithDuration = () => {const videoRef = useRef(null);const { intrinsicDurationMs, loading } = useMediaInfo(videoRef);return (<><Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/>{loading ? (<div className="absolute top-4 right-4 text-white">Loading...</div>) : (<div className="absolute top-4 right-4 text-white">Duration: {((intrinsicDurationMs || 0) / 1000).toFixed(1)}s</div>)}</>);};
With Audio
import { useRef } from "react";import { Audio, Waveform, useMediaInfo } from "@editframe/react";const AudioWithInfo = () => {const audioRef = useRef(null);const { intrinsicDurationMs, loading } = useMediaInfo(audioRef);return (<><Audioref={audioRef}src="/assets/music.mp3"/>{!loading && intrinsicDurationMs && (<><Waveform target={audioRef} className="w-full h-24" /><div className="text-white text-center mt-2">{(intrinsicDurationMs / 1000).toFixed(1)} seconds</div></>)}</>);};
Format Duration Display
import { useRef } from "react";import { Video, useMediaInfo } from "@editframe/react";const formatDuration = (ms: number | undefined): string => {if (ms === undefined) return "--:--";const totalSeconds = Math.floor(ms / 1000);const minutes = Math.floor(totalSeconds / 60);const seconds = totalSeconds % 60;return `${minutes}:${seconds.toString().padStart(2, '0')}`;};const VideoWithFormattedTime = () => {const videoRef = useRef(null);const { intrinsicDurationMs } = useMediaInfo(videoRef);return (<><Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/><div className="absolute bottom-4 right-4 bg-black/70 text-white px-3 py-1 rounded">{formatDuration(intrinsicDurationMs)}</div></>);};
Dynamic Timegroup Duration
Set timegroup duration based on media duration:
import { useRef, useEffect, useState } from "react";import { Timegroup, Video, useMediaInfo } from "@editframe/react";const DynamicDurationScene = () => {const videoRef = useRef(null);const { intrinsicDurationMs, loading } = useMediaInfo(videoRef);const [duration, setDuration] = useState("10s");useEffect(() => {if (intrinsicDurationMs) {setDuration(`${intrinsicDurationMs}ms`);}}, [intrinsicDurationMs]);if (loading) {return <div className="text-white">Loading video...</div>;}return (<Timegroup mode="fixed" duration={duration} className="absolute w-full h-full"><Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/></Timegroup>);};
Loading States
import { useRef } from "react";import { Video, useMediaInfo } from "@editframe/react";const VideoWithLoadingState = () => {const videoRef = useRef(null);const { intrinsicDurationMs, loading } = useMediaInfo(videoRef);return (<div className="relative w-full h-full"><Videoref={videoRef}src="/assets/large-video.mp4"className="size-full object-cover"/>{loading && (<div className="absolute inset-0 flex items-center justify-center bg-black/50"><div className="text-white text-xl">Loading video metadata...</div></div>)}{!loading && !intrinsicDurationMs && (<div className="absolute inset-0 flex items-center justify-center bg-red-500/50"><div className="text-white text-xl">Failed to load video</div></div>)}</div>);};
Progress Indicator
import { useRef } from "react";import { Video, useMediaInfo, useTimingInfo } from "@editframe/react";const VideoWithProgress = () => {const videoRef = useRef(null);const { ref: timegroupRef, ownCurrentTimeMs } = useTimingInfo();const { intrinsicDurationMs } = useMediaInfo(videoRef);const progress = intrinsicDurationMs? (ownCurrentTimeMs / intrinsicDurationMs) * 100: 0;return (<div ref={timegroupRef} className="relative w-full h-full"><Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/><div className="absolute bottom-0 left-0 right-0 h-1 bg-gray-700"><divclassName="h-full bg-blue-500 transition-all"style={{ width: `${progress}%` }}/></div></div>);};
Multiple Videos
import { useRef } from "react";import { Video, useMediaInfo } from "@editframe/react";const MultiVideoInfo = () => {const video1Ref = useRef(null);const video2Ref = useRef(null);const video1Info = useMediaInfo(video1Ref);const video2Info = useMediaInfo(video2Ref);const totalDuration =(video1Info.intrinsicDurationMs || 0) +(video2Info.intrinsicDurationMs || 0);return (<><Video ref={video1Ref} src="/assets/clip1.mp4" className="size-full" /><Video ref={video2Ref} src="/assets/clip2.mp4" className="size-full" /><div className="absolute top-4 left-4 bg-black/70 text-white px-3 py-2 rounded"><div>Clip 1: {((video1Info.intrinsicDurationMs || 0) / 1000).toFixed(1)}s</div><div>Clip 2: {((video2Info.intrinsicDurationMs || 0) / 1000).toFixed(1)}s</div><div className="border-t border-white/30 mt-1 pt-1">Total: {(totalDuration / 1000).toFixed(1)}s</div></div></>);};
Conditional Rendering
Only show content when media is loaded:
import { useRef } from "react";import { Timegroup, Video, Text, useMediaInfo } from "@editframe/react";const ConditionalScene = () => {const videoRef = useRef(null);const { loading } = useMediaInfo(videoRef);return (<Timegroup mode="contain" className="absolute w-full h-full"><Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/>{!loading && (<Textduration="5s"className="absolute top-8 left-8 text-white text-3xl">Video Title</Text>)}</Timegroup>);};
Error Handling
import { useRef, useEffect, useState } from "react";import { Video, useMediaInfo } from "@editframe/react";const VideoWithErrorHandling = () => {const videoRef = useRef(null);const { intrinsicDurationMs, loading } = useMediaInfo(videoRef);const [error, setError] = useState(false);useEffect(() => {// If still loading after 10 seconds, consider it an errorif (loading) {const timeout = setTimeout(() => {if (loading && !intrinsicDurationMs) {setError(true);}}, 10000);return () => clearTimeout(timeout);}}, [loading, intrinsicDurationMs]);if (error) {return (<div className="flex items-center justify-center w-full h-full bg-red-500 text-white">Failed to load video</div>);}return (<Videoref={videoRef}src="/assets/video.mp4"className="size-full object-cover"/>);};
Notes
- The ref must point to a Video or Audio component from
@editframe/react intrinsicDurationMsisundefineduntil metadata loadsloadingistruewhile media metadata is being fetched- Updates automatically when the media source changes
- Duration is in milliseconds for consistency with other timing APIs
- Works with both local and remote media files