React+TypeScript中Video.js 8播放MP4无法传递JWT令牌致未授权
使用React+TypeScript开发Video.js播放器时,配置的XHR钩子未触发,无法携带JWT令牌,视频加载提示未授权,但原生XHR方式可以正常播放。涉及版本:video.js@8.21.0、@types/video.js@7.3.58、react@18.3.1。
核心问题原因
- Video.js 8.x的XHR钩子配置结构变更:旧版本的
html5.xhr.before在8.x中已不再生效,需要改用新的钩子配置路径。 - 默认加载策略不走Video.js XHR:对于MP4这类原生支持的格式,浏览器可能直接发起请求,跳过Video.js的XHR加载流程,导致钩子无法触发。
修复步骤
1. 修正XHR钩子配置
将原来的html5.xhr.before替换为html5.xhr.hooks.beforeRequest,这是Video.js 8.x要求的正确配置方式:
const customOptions: PlayerOptions = { ...options, html5: { ...options.html5, // 保留原有html5配置 xhr: { hooks: { beforeRequest: (xhr: XMLHttpRequest) => { console.log('添加Authorization令牌'); xhr.setRequestHeader('Authorization', `Bearer ${jwtToken}`); } } } } };
2. 强制使用Video.js的XHR加载器
为了确保浏览器不会直接加载媒体资源,需要配置强制启用Video.js的XHR加载机制,添加nativeVideoTracks: false和nativeAudioTracks: false到html5配置中:
html5: { ...options.html5, nativeVideoTracks: false, nativeAudioTracks: false, xhr: { hooks: { beforeRequest: (xhr: XMLHttpRequest) => { xhr.setRequestHeader('Authorization', `Bearer ${jwtToken}`); } } } }
3. 处理类型定义不兼容问题
由于使用的@types/video.js版本(7.3.58)与Video.js 8.x不匹配,可能会出现类型报错,可以通过类型断言忽略:
// 对html5配置进行类型断言 html5: { ...options.html5, nativeVideoTracks: false, nativeAudioTracks: false, xhr: { hooks: { beforeRequest: (xhr: XMLHttpRequest) => { xhr.setRequestHeader('Authorization', `Bearer ${jwtToken}`); } } } } as any
修改后的完整VideoPlayerMP4.tsx代码
import React, { useEffect, useRef } from 'react'; import videojs from 'video.js'; import Player from 'video.js/dist/types/player'; import 'video.js/dist/video-js.css'; type PlayerOptions = typeof videojs.options; interface VideoPlayerProps { id?: string; url?: string; options?: PlayerOptions; styles?: string; jwtToken: string; } const VideoPlayerMP4: React.FC<VideoPlayerProps> = ({ url, options, styles, jwtToken, }: VideoPlayerProps) => { const videoRef = useRef<HTMLVideoElement | null>(null); const playerRef = useRef<Player | null>(); useEffect(() => { if (!options?.sources.length || !videoRef.current) return; const customOptions: PlayerOptions = { ...options, html5: { ...options.html5, nativeVideoTracks: false, nativeAudioTracks: false, xhr: { hooks: { beforeRequest: (xhr: XMLHttpRequest) => { console.log('发送视频令牌'); xhr.setRequestHeader('Authorization', `Bearer ${jwtToken}`); } } } } as any // 处理类型不兼容 }; if (!playerRef.current) { const player = videojs(videoRef.current, customOptions, () => { console.log('视频播放器已就绪'); }); playerRef.current = player; player.on('error', (err) => { console.error('播放器错误:', err); }); } else { const currentSrc = playerRef.current.currentSrc(); const newSrc = customOptions.sources[0].src; const player = playerRef.current; if (currentSrc !== newSrc) { player.autoplay(customOptions.autoplay); player.src(customOptions.sources); } } // 清理函数 return () => { if (playerRef.current) { playerRef.current.dispose(); playerRef.current = null; } }; }, [url, options, jwtToken]); return ( <div className={styles}> <video ref={videoRef} className="video-js vjs-theme-city vjs-big-play-centered" style={{ width: '100%', height: '100%' }} ></video> </div> ); }; export default VideoPlayerMP4;
额外说明
- 如果上述配置后仍未触发钩子,可以尝试启用VHS(Video.js HTTP Streaming)加载器来处理MP4,添加
vhs: { overrideNative: true }到html5配置中。 - 确保后端服务器允许携带Authorization头的跨域请求(如果存在跨域场景)。
内容的提问来源于stack exchange,提问作者HP . Htet Phyo Naing
相关产品推荐
相关产品推荐

