12k
All articles

如何在 React 中嵌入视频

在 React 中嵌入视频:自托管文件用 HTML5 video,YouTube 用 iframe,包含 autoplay 修复、响应式尺寸和 ReactPlayer 选择。

OpenReplay Team
OpenReplay Team
如何在 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> 就足够了。只有当原生方案确实无法满足需求时,才去引入第三方库。

常见问题

为什么我的视频在 React 中无法自动播放?

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

嵌入时应该使用 youtube.com 还是 youtube-nocookie.com?

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

嵌入视频是否需要 ReactPlayer 这样的库?

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

如何让 React 中嵌入的视频具备响应式?

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

DevTools for the frontend

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.

Star on GitHub12k

We use cookies to improve your experience. By using our site, you accept cookies.