똑같은 삽질은 2번 하지 말자
React vol.20 video의 자막을 커스텀마이징하기 본문
개요
video에서 caption(자막)이 브라우저, 디바이스에 따라 화면에 표시되는게 제각각이기 때문에 기본 표시를 사용하지 않고 커스텀마이징해서 사용했던 이야기
우선 textTracks라는 Web API를 이용했다.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/textTracks
HTMLMediaElement: textTracks property - Web APIs | MDN
The read-only textTracks property on HTMLMediaElement objects returns a TextTrackList object listing all of the TextTrack objects representing the media element's text tracks, in the same order as in the list of text tracks.
developer.mozilla.org
이를 이용하면 video에 설정되어있는 caption(자막)을 얻을 수 있고 현재 표시중인 자막도 따로 걸러내서 얻을 수 있다.
실제로 개발했던 코드를 베이스로 설명하자면
Player.tsx
import React, { useEffect, useRef } from 'react';
interface PlayerProps {
src: string;
onActiveCueChange?: (activeCue: VTTCue) => void;
}
export default function Player({
src,
onActiveCueChange,
}: PlayerProps) {
const videoRef = useRef<HTMLVideoElement>(null);
...
// 자막을 추출해서 부모로 보내기
useEffect(() => {
const videoElement = videoRef.current;
if (!videoElement) {
return;
}
videoElement.textTracks.addEventListener('change', e => {
if (videoElement.textTracks[0]) {
videoElement.textTracks[0].mode = 'hidden';
videoElement.textTracks[0].oncuechange = e => {
const cue = videoElement.textTracks[0];
if (cue.activeCues && cue.activeCues[0] && cue.activeCues[0] instanceof VTTCue) {
onActiveCueChange?.(cue.activeCues[0]);
}
};
}
});
}, [onActiveCueChange]);
return <video ref={videoRef} playsInline />;
};
- videoElement.textTracks에 change 이벤트를 캐치해서 자막이 셋업되는걸 기다린다.
- videoElement.textTracks[0].mode = 'hidden' 을 해서 기본 자막 표시를 지운다.
- 셋업된 자막에 oncuechange의 이벤트를 등록해서 현재 표시중인 자막이 변경될 때마다 부모에서 변경된 자막을 보낸다.
VideoPlayer.tsx
...생략
export default function VideoPlayer({
videoUrl,
}: VideoPlayerProps) {
;
const [activeCue, setActiveCue] = useState<VTTCue>();
const handleActiveCueChange = useCallback((activeCue: VTTCue) => {
setActiveCue(activeCue);
}, []);
return (
<div className="relative">
<Player
className="h-full w-full"
src={videoUrl.hls}
onActiveCueChange={handleActiveCueChange}
/>
{activeCue && (
<div
className={`absolute inset-x-0 bottom-0 flex items-center justify-center ${
showControls ? (isFullscreen ? 'mb-12 portrait:mb-2' : 'mb-12 md:mb-14') : 'mb-2 md:mb-4'
}`}
>
<p className="rounded-md bg-black/40 p-2 text-sm md:p-4 md:text-2xl">{activeCue.text}</p>
</div>
)}
</div>
);
}
- activeCue.text로 현재 표시해야하는 자막을 얻을 수 있다.
끝
Comments