简介/指南/视频

视频使用与优化指南

本文概述了如何在 Next.js 应用中使用视频,展示如何存储和展示视频文件而不影响性能。

使用 <video><iframe>

可以通过 HTML <video> 标签嵌入直接视频文件,或使用 <iframe> 嵌入外部平台托管的视频。

<video>

HTML <video> 标签可嵌入自托管或直接提供的视频内容,允许完全控制播放和外观。

app/ui/video.jsx
export function Video() {
  return (
    <video width="320" height="240" controls preload="none">
      <source src="/path/to/video.mp4" type="video/mp4" />
      <track
        src="/path/to/captions.vtt"
        kind="subtitles"
        srcLang="en"
        label="English"
      />
      您的浏览器不支持 video 标签
    </video>
  )
}

<video> 标签常用属性

属性描述示例值
src指定视频文件源地址<video src="/path/to/video.mp4" />
width设置视频播放器宽度<video width="320" />
height设置视频播放器高度<video height="240" />
controls显示默认播放控制条<video controls />
autoPlay页面加载时自动播放视频。注意:不同浏览器的自动播放策略不同<video autoPlay />
loop循环播放视频<video loop />
muted默认静音。常与 autoPlay 配合使用<video muted />
preload指定视频预加载方式。可选值:none, metadata, auto<video preload="none" />
playsInline在 iOS 设备上启用内联播放,通常需要此属性才能在 iOS Safari 上实现自动播放<video playsInline />

须知:使用 autoPlay 属性时,建议同时添加 muted 属性以确保在多数浏览器中自动播放,并添加 playsInline 属性以保证 iOS 设备兼容性。

完整视频属性列表请参考 MDN 文档

视频最佳实践

  • 回退内容:在 <video> 标签内添加回退内容,供不支持视频播放的浏览器显示
  • 字幕支持:为听障用户添加字幕。使用 <track> 标签为视频指定字幕文件
  • 无障碍控制:推荐使用标准 HTML5 视频控制条以确保键盘导航和屏幕阅读器兼容性。如需高级功能,可考虑 react-playervideo.js 等第三方播放器

<iframe>

HTML <iframe> 标签可嵌入 YouTube 或 Vimeo 等外部平台的视频。

app/page.jsx
export default function Page() {
  return (
    <iframe src="https://www.youtube.com/embed/19g66ezsKAg" allowFullScreen />
  )
}

<iframe> 标签常用属性

属性描述示例值
src嵌入页面的 URL<iframe src="https://example.com" />
width设置 iframe 宽度<iframe width="500" />
height设置 iframe 高度<iframe height="300" />
allowFullScreen允许 iframe 内容全屏显示<iframe allowFullScreen />
sandbox对 iframe 内容启用额外限制<iframe sandbox />
loading优化加载行为(如懒加载)<iframe loading="lazy" />
title为 iframe 提供标题以支持无障碍访问<iframe title="描述文字" />

完整 iframe 属性列表请参考 MDN 文档

视频嵌入方式选择

在 Next.js 应用中嵌入视频有两种方式:

  • 自托管或直接视频文件:使用 <video> 标签嵌入,适用于需要精细控制播放器功能和外观的场景
  • 使用视频托管服务(YouTube、Vimeo 等):通过 <iframe> 标签嵌入平台提供的播放器,虽然控制有限但使用简便

根据应用需求和目标用户体验选择合适的嵌入方式。

嵌入外部托管视频

可通过 Next.js 获取视频信息,并使用 React Suspense 处理加载状态。

1. 创建视频嵌入服务端组件

首先创建服务端组件生成视频嵌入 iframe。

app/ui/video-component.jsx
export default async function VideoComponent() {
  const src = await getVideoSrc()

  return <iframe src={src} allowFullScreen />
}

2. 使用 React Suspense 流式传输

创建服务端组件后,使用 React Suspense 进行流式传输

app/page.jsx
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'

export default function Page() {
  return (
    <section>
      <Suspense fallback={<p>加载视频中...</p>}>
        <VideoComponent />
      </Suspense>
      {/* 页面其他内容 */}
    </section>
  )
}

须知:嵌入外部平台视频时需考虑:

  • 确保视频嵌入响应式。使用 CSS 使 iframe 适配不同屏幕尺寸
  • 根据网络条件实现视频加载策略,特别是对有限数据计划的用户

为提升加载体验,可使用骨架屏替代简单加载提示:

app/page.jsx
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'
import VideoSkeleton from '../ui/VideoSkeleton.jsx'

export default function Page() {
  return (
    <section>
      <Suspense fallback={<VideoSkeleton />}>
        <VideoComponent />
      </Suspense>
      {/* 页面其他内容 */}
    </section>
  )
}

自托管视频

自托管视频的优势包括:

  • 完全控制与独立性:直接管理视频内容,不受外部平台限制
  • 满足特定需求定制:适合动态背景视频等独特需求
  • 性能与可扩展性:选择高性能、可扩展的存储方案以应对流量增长
  • 成本与集成:平衡存储带宽成本与 Next.js 框架集成需求

使用 Vercel Blob 托管视频

Vercel Blob 提供与 Next.js 完美配合的云存储方案。

1. 上传视频到 Vercel Blob

在 Vercel 仪表板的「存储」选项卡中选择 Vercel Blob 存储。点击右上角「上传」按钮选择视频文件。上传完成后视频将出现在 Blob 表格中。

也可通过服务端上传客户端上传实现。

2. 在 Next.js 中展示视频

上传后可通过 <video> 标签和 React Suspense 展示:

app/page.jsx
import { Suspense } from 'react'
import { list } from '@vercel/blob'

export default function Page() {
  return (
    <Suspense fallback={<p>加载视频中...</p>}>
      <VideoComponent fileName="my-video.mp4" />
    </Suspense>
  )
}

async function VideoComponent({ fileName }) {
  const { blobs } = await list({
    prefix: fileName,
    limit: 1,
  })
  const { url } = blobs[0]

  return (
    <video controls preload="none" aria-label="视频播放器">
      <source src={url} type="video/mp4" />
      您的浏览器不支持 video 标签
    </video>
  )
}

添加字幕

通过 <track> 元素添加字幕文件:

app/page.jsx
async function VideoComponent({ fileName }) {
  const { blobs } = await list({
    prefix: fileName,
    limit: 2,
  })
  const { url } = blobs[0]
  const { url: captionsUrl } = blobs[1]

  return (
    <video controls preload="none" aria-label="视频播放器">
      <source src={url} type="video/mp4" />
      <track src={captionsUrl} kind="subtitles" srcLang="en" label="English" />
      您的浏览器不支持 video 标签
    </video>
  )
}

资源推荐

视频格式与编解码器

选择适合的视频格式和编解码器(如兼容性强的 MP4 或为网页优化的 WebM),详见 Mozilla 编解码器指南

视频压缩

使用 FFmpeg 等工具平衡画质与文件大小,参考 FFmpeg 官网

分辨率与比特率

根据观看平台调整分辨率与比特率,移动设备使用较低设置。

内容分发网络 (CDN)

使用 CDN 提升视频传输速度。部分存储方案(如 Vercel Blob)已自动集成 CDN 功能,详见 Vercel 边缘网络

开源 next-video 组件

  • 提供适用于 Next.js 的 <Video> 组件,支持 Vercel Blob、S3、Backblaze 和 Mux 等多种服务
  • 详细文档见 next-video.dev

Cloudinary 集成

Mux 视频 API

Fastly

了解如何集成 Fastly 的 视频点播 和流媒体解决方案到 Next.js。

ImageKit.io 集成