Appearance
useMediaControls
Reactive media controls for both audio and video elements
Demo
Usage
Basic Usage
tsx
import { useMediaControls } from '@reause/core'
import { useEffect, useRef } from 'react'
const video = useRef<HTMLVideoElement>(null)
const { playing, currentTime, duration, volume, setVolume, toggle, seek } = useMediaControls(video, {
src: 'video.mp4',
})
// Change initial media properties
useEffect(() => {
setVolume(0.5)
seek(60)
}, [])
// <video ref={video} onClick={() => toggle()} />
// <span>{formatDuration(currentTime)} / {formatDuration(duration)}</span>Providing Captions, Subtitles, etc...
You can provide captions, subtitles, etc in the tracks options of the useMediaControls function. The function will return an array of tracks along with two functions for controlling them, enableTrack, disableTrack, and selectedTrack. Using these you can manage the currently selected track. selectedTrack will be -1 if there is no selected track.
tsx
import { useMediaControls } from '@reause/core'
import { useRef } from 'react'
const video = useRef<HTMLVideoElement>(null)
const {
tracks,
enableTrack,
} = useMediaControls(video, {
src: 'video.mp4',
tracks: [
{
default: true,
src: './subtitles.vtt',
kind: 'subtitles',
label: 'English',
srcLang: 'en',
},
],
})tsx
// <video ref={video} />
// {tracks.map(track => (
// <button type="button" key={track.id} onClick={() => enableTrack(track)}>
// {track.label}
// </button>
// ))}Playback Controls
Upstream's writable refs (playing, currentTime, volume, rate, muted) are control methods here. They all resolve the current target element at call time (upstream usingElRef) and are referentially stable:
tsx
const {
play, // () => void — start playback
pause, // () => void — pause playback
toggle, // () => void — play / pause toggle
seek, // (time: number) => void — jump to `time` seconds
setVolume, // (volume: number) => void — 0..1
setRate, // (rate: number) => void — e.g. 0.5 / 1 / 2
mute, // () => void
unmute, // () => void
toggleMute, // () => void
} = useMediaControls(videoRef)Type Declarations
Toggle
ts
export interface UseMediaSource {
src: string;
type?: string;
media?: string;
}
export interface UseMediaTextTrackSource {
default?: boolean;
kind: TextTrackKind;
label: string;
src: string;
srcLang: string;
}
export interface UseMediaControlsOptions {
document?: Document;
src?: string | UseMediaSource | UseMediaSource[];
tracks?: UseMediaTextTrackSource[];
}
export interface UseMediaTextTrack {
id: number;
label: string;
language: string;
mode: TextTrackMode;
kind: TextTrackKind;
inBandMetadataTrackDispatchType: string;
cues: TextTrackCueList | null;
activeCues: TextTrackCueList | null;
}
export type UseMediaControlsTarget = RefObject<HTMLMediaElement | null | undefined>
export interface UseMediaControlsReturn {
currentTime: number;
duration: number;
waiting: boolean;
seeking: boolean;
ended: boolean;
stalled: boolean;
buffered: [
number,
number
][];
playing: boolean;
rate: number;
volume: number;
muted: boolean;
tracks: UseMediaTextTrack[];
selectedTrack: number;
supportsPictureInPicture: boolean;
isPictureInPicture: boolean;
onSourceError: EventHookOn<Event>;
onPlaybackError: EventHookOn<Event>;
play: () => void;
pause: () => void;
toggle: () => void;
seek: (time: number) => void;
setVolume: (volume: number) => void;
mute: () => void;
unmute: () => void;
toggleMute: () => void;
setRate: (rate: number) => void;
enableTrack: (track: number | UseMediaTextTrack, disableTracks?: boolean) => void;
disableTrack: (track?: number | UseMediaTextTrack) => void;
togglePictureInPicture: () => Promise<PictureInPictureWindow | void>;
}
type EventHookOn<T = any> = (fn: (param: T) => void) => () => void
export function useMediaControls(target: UseMediaControlsTarget, options?: UseMediaControlsOptions): UseMediaControlsReturn