Back

如何在 React 中嵌入视频

如何在 React 中嵌入视频

在 React 应用中嵌入视频听起来很简单,直到你遇到自动播放失效、iframe 无响应,或者 <embed> 标签根本不起作用。本指南介绍两种最实用的方法:用于自托管文件的原生 HTML5 <video> 元素,以及用于 YouTube、Vimeo 等平台的 <iframe> 嵌入。仅在第三方库确实能带来价值时才会提及,而非默认推荐。

关键要点

  • 自托管文件请使用原生 HTML5 <video> 元素,无需任何库。
  • 对于 YouTube 嵌入,指向 youtube-nocookie.com 的普通 <iframe> 是标准且注重隐私的做法。
  • 自动播放需要 muted 属性才能在 Chrome、Safari 和 Firefox 中可靠工作。
  • playsInline 在 iOS 上至关重要,可避免视频被强制全屏播放。
  • 仅当你需要跨多个平台的统一 API 或高级事件回调时,才考虑使用 ReactPlayer 这样的库。

方法一:在 React 中为自托管文件使用 HTML5 视频

如果你掌控视频文件本身,原生 <video> 元素就是合适的工具,无需任何库。

import myVideo from './assets/demo.mp4';

export default function VideoPlayer() {
  return (
    <video
      width="100%"
      style={{ aspectRatio: '16/9' }}
      controls
      playsInline
      muted
    >
      <source src={myVideo} type="video/mp4" />
      <track
        kind="subtitles"
        src="/captions/demo.en.vtt"
        srcLang="en"
        label="English"
        default
      />
      Your browser does not support the video tag.
    </video>
  );
}

几个值得注意的细节:

  • autoPlay 需要配合 muted 才能在现代浏览器中可靠工作。Chrome、Safari 和 Firefox 默认都会阻止非静音的自动播放。不要想当然地认为不加 muted 也能正常工作。注意在 JSX 中该属性使用驼峰命名 autoPlay,而非 autoplay。浏览器支持情况和自动播放策略可参阅 Can I Use
  • playsInline 在 iOS 上是必需的,可防止视频自动以全屏方式打开。
  • <track> 用于添加字幕或说明。这是处理视频内容无障碍访问的正确方式,但很容易被忽视。
  • <video> 内部的回退文本仅在非常老旧的、不识别该元素的浏览器中显示。但仍然值得保留。

对于像 HLS(.m3u8)这样的自适应流媒体格式,浏览器原生支持情况差异较大。Safari 原生支持 HLS,但 Chrome 和 Firefox 需要借助 hls.js 之类的库来解析和播放流。

在 React 中嵌入 YouTube:使用 iframe

对于 YouTube 或 Vimeo,<iframe> 是标准做法。你并不需要专门的 React 包来实现。

export default function YouTubeEmbed({ videoId }) {
  return (
    <div style={{ aspectRatio: '16/9', width: '100%' }}>
      <iframe
        width="100%"
        height="100%"
        src={`https://www.youtube-nocookie.com/embed/${videoId}`}
        title="YouTube video player"
        allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
        allowFullScreen
        style={{ border: 'none' }}
      />
    </div>
  );
}

关键细节:

  • 使用 youtube-nocookie.com 而非 youtube.com 作为嵌入 URL。这是 YouTube 的隐私增强模式,在用户与播放器交互之前会减少跟踪 cookie 的使用。
  • iframe 必须设置 title 以便屏幕阅读器使用。没有它,辅助技术就无法描述嵌入的内容。
  • 包装层使用 aspectRatio: '16/9',并在 iframe 上设置 width: 100%height: 100%,这是基于现代 CSS 最简洁的响应式方案,无需 padding 技巧。CSS aspect-ratio 属性的浏览器支持情况见 Can I Use
  • 嵌入 URL 格式为 https://www.youtube-nocookie.com/embed/{VIDEO_ID}。视频 ID 即标准 YouTube URL 中 v 查询参数的值(例如 youtube.com/watch?v=VIDEO_ID?v= 后面的部分)。

你可以通过查询字符串传递额外参数:

/embed/VIDEO_ID?controls=1&rel=0

何时使用 React 视频播放器库

对于大多数场景,原生 <video> 元素或普通的 iframe 已经足够。如果你需要通过统一的 API 在单个组件中支持多个平台(YouTube、Vimeo、Wistia、HLS、DASH),或者需要在不同平台间使用 onReadyonProgressonEnded 等事件回调,可以考虑使用 ReactPlayer 这类库。

ReactPlayer 会显著增加打包体积,因此在将其作为依赖引入之前,值得评估你是否真的需要这种灵活性。

结论

从最简单可行的工具开始。对于自托管视频,使用 HTML5 <video> 元素,配合 controlsplaysInline,并在需要自动播放时加上 muted。在 React 中嵌入 YouTube 时,一个指向 youtube-nocookie.com 并带有恰当 title 属性的普通 <iframe> 就足够了。只有当原生方案确实无法满足需求时,才去引入第三方库。

常见问题

现代浏览器会阻止带声音的视频自动播放。要在 Chrome、Safari 和 Firefox 中实现可靠的自动播放,video 元素必须在 autoPlay 之外同时包含 muted 属性。在 iOS 上,还需要 playsInline,否则视频可能拒绝内联播放或被强制全屏。缺少这些属性时,自动播放会静默失败。

只要可能,就使用 youtube-nocookie.com。这是 YouTube 的隐私增强嵌入模式,在用户实际与播放器交互之前不会设置跟踪 cookie。核心播放功能与标准嵌入基本一致,但对隐私合规更友好,并有助于减少站点上的第三方 cookie 警告。

一般情况下并不需要。原生 HTML5 video 元素可处理自托管文件,普通 iframe 即可处理 YouTube 或 Vimeo。仅当你需要跨多个平台的统一 API,或需要 onProgress、onEnded 等一致的事件回调时,才考虑 ReactPlayer。否则,其打包体积成本通常并不划算。

将 video 或 iframe 包裹在一个容器中,容器样式设置 aspectRatio 为 16/9,width 为 100%。然后将内部元素的 width 和 height 都设为 100%。这种现代 CSS 方法取代了旧的 padding-bottom 技巧,无需手动计算即可在各种屏幕尺寸下保持视频比例。

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay