React TypeScript视频播放器字幕点击按钮不显示问题求助
字幕无法显示问题排查请求
将WebDevSimplified的原生JS视频播放器转为React TypeScript项目后,遇到字幕无法显示的问题:点击字幕按钮后,字幕未正常展示。已通过console.log确认字幕状态与videoRef.current.textTracks[0].mode同步(hidden对应false,showing对应true),但问题仍存在,怀疑问题出在Subtitles.vtt文件的路径或格式上。以下是相关代码片段、VTT文件内容及文件结构:
JSContextProvider.tsx
import { useReducer, useEffect, useRef, ReactNode } from 'react'; import { JSContext, ContextProps } from './JSContext'; export type JSReducerState = { captions: boolean; }; const initialState: JSReducerState = { captions: false, }; export type JSReducerAction = | { type: 'SET_CAPTIONS'; payload: boolean }; const reducer = ( state: JSReducerState, action: JSReducerAction ): JSReducerState => { switch (action.type) { case 'SET_CAPTIONS': return { ...state, captions: action.payload }; default: return state; } }; export const JSProvider = ({ children }: { children: ReactNode }) => { const [state, dispatch] = useReducer(reducer, initialState); const videoRef = useRef<HTMLVideoElement | null>(null); const captionsHandler = () => { if (videoRef.current) { const captions = videoRef.current.textTracks[0]; if (!captions) { return; } if (captions.mode === 'hidden') { captions.mode = 'showing'; } else { captions.mode = 'hidden'; } dispatch({ type: 'SET_CAPTIONS', payload: captions.mode === 'showing' }); } }; const handleKeyPress = (e: KeyboardEvent) => { const tagName = document.activeElement?.tagName.toLowerCase(); switch (e.key.toLowerCase()){ case "c": captionsHandler(); break; default: return; } }; const videoKeyDownHandler = (e: React.KeyboardEvent<HTMLVideoElement>) => { handleKeyPress(e as unknown as KeyboardEvent); }; useEffect(() => { window.addEventListener('keydown', handleKeyPress); return () => { window.removeEventListener('keydown', handleKeyPress); }; }, [handleKeyPress]); const contextValue: ContextProps = { state, dispatch, videoRef, captionsHandler, }; return ( <JSContext.Provider value={contextValue}> {children} </JSContext.Provider> ); }; export default JSProvider;
JSContext.ts
import { createContext, createRef } from 'react'; import { JSReducerAction, JSReducerState } from './JSContextProvider'; export type ContextProps = { state: JSReducerState; dispatch: React.Dispatch<JSReducerAction>; videoRef: React.RefObject<HTMLVideoElement | null>; captionsHandler: () => void; }; export const JSContext = createContext<ContextProps>({ state: { captions: false, }, dispatch: () => {}, videoRef: createRef(), captionsHandler: () => {}, });
VideoStyles.module.css
.captionsBtn{ border-bottom: 3px solid rgba(255,255,255,1); filter: brightness(110%) drop-shadow(0 0 5px rgba(255, 255, 255, 0.5)) grayscale(10%); }
VideoPlayer.tsx
import { useJSContext } from '../../../Context/UseJSContext'; import test5 from './Assets/test5.mp4'; import subtitles from './Assets/PreviewImgs/Subtitles.vtt'; import CaptionsBtn from './Btns/CaptionsBtn'; import classes from './VideoStyles.module.css'; const VideoPlayer = () => { const { videoRef, pauseHandler, playHandler, state, videoKeyDownHandler, playPauseHandler, } = useJSContext(); return ( <div className={`${classes.videoContainer}`}> <img className={classes.thumbnailImg} /> <div className={classes.videoControlsContainer}> <div className={classes.controls}> <CaptionsBtn /> </div> </div> <video className={`${state.isTheater === true ? `${classes.theater}` : ''}`} src={test5} ref={videoRef} onPause={pauseHandler} onPlay={playHandler} onEnded={pauseHandler} onKeyDown={videoKeyDownHandler} onClick={() => { playPauseHandler(); }} autoPlay={state.display === 'video'} > <track kind="captions" srcLang="en" src={subtitles} label="English" default /> </video> </div> ); }; export default VideoPlayer;
Subtitles.vtt
WEBVTT 00:00:00.000 --> 00:00:03.000 This is test 5, test 5.
文件结构

排查修正要点:
- VTT文件路径问题:React中不能直接使用相对路径引用静态资源,需像引入视频一样通过
import导入VTT文件,或把VTT放到public目录下使用绝对路径。 - 代码语法错误:原
JSContextProvider.tsx中存在变量名不一致(KSReducerState和JSReducerState混用)、函数定义位置错误(handleKeyPress等函数定义在组件函数外部)的问题,已修正。 - VTT格式优化:去掉了多余的序号和破折号,标准VTT格式中时间线后直接写字幕内容即可。
- track标签完善:添加
label属性让浏览器识别字幕语言,增加default属性确保字幕轨道被正确加载。 - Context类型补全:
JSContext.ts中补充了缺失的ContextProps类型定义,避免TypeScript类型报错。
内容的提问来源于stack exchange,提问作者LAFarmer
相关产品推荐
相关产品推荐

