You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+TypeScript中Video.js 8播放MP4无法传递JWT令牌致未授权

Video.js 8.x 无法触发XHR钩子添加Authorization头的解决方案

使用React+TypeScript开发Video.js播放器时,配置的XHR钩子未触发,无法携带JWT令牌,视频加载提示未授权,但原生XHR方式可以正常播放。涉及版本:video.js@8.21.0、@types/video.js@7.3.58、react@18.3.1。

核心问题原因

  1. Video.js 8.x的XHR钩子配置结构变更:旧版本的html5.xhr.before在8.x中已不再生效,需要改用新的钩子配置路径。
  2. 默认加载策略不走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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 07:03:21