视频优化

本文概述了如何在 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"
      />
      Your browser does not support the video tag.
    </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指定视频的预加载方式。可选值:nonemetadataauto<video preload="none">
playsInline在 iOS 设备上启用内联播放,通常是在 iOS Safari 上实现自动播放的必要条件。<video playsInline>

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

完整的视频属性列表,请参阅 MDN 文档

视频最佳实践

  • 回退内容:使用 <video> 标签时,在标签内包含回退内容,以支持不支持视频播放的浏览器。
  • 字幕或说明:为听障用户添加字幕或说明。使用 <track> 标签为 <video> 元素指定字幕文件来源。
  • 可访问的控制栏:推荐使用标准 HTML5 视频控制栏,以确保键盘导航和屏幕阅读器兼容性。如需更高级的功能,可考虑使用第三方播放器如 react-playervideo.js,它们提供可访问的控制栏和一致的浏览器体验。

<iframe>

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

app/page.jsx
export default function Page() {
  return (
    <iframe
      src="https://www.youtube.com/watch?v=gfU1iZnjRZM"
      frameborder="0"
      allowfullscreen
    />
  )
}

常见 <iframe> 标签属性

属性描述示例值
src嵌入页面的 URL。<iframe src="https://example.com">
width设置 iframe 的宽度。<iframe width="500">
height设置 iframe 的高度。<iframe height="300">
frameborder指定是否在 iframe 周围显示边框。<iframe frameborder="0">
allowfullscreen允许 iframe 内容以全屏模式显示。<iframe allowfullscreen>
sandbox对 iframe 内容启用额外的限制。<iframe sandbox>
loading优化加载行为(例如懒加载)。<iframe loading="lazy">
title为 iframe 提供标题以支持可访问性。<iframe title="Description">

完整的 iframe 属性列表,请参阅 MDN 文档

选择视频嵌入方式

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

  • 自托管或直接视频文件:使用 <video> 标签嵌入自托管视频,适用于需要详细控制播放器功能和外观的场景。这种集成方式允许自定义和控制视频内容。
  • 使用视频托管服务(YouTube、Vimeo 等):对于 YouTube 或 Vimeo 等视频托管服务,使用 <iframe> 标签嵌入它们的播放器。虽然这种方式限制了对播放器的部分控制,但它提供了这些平台的易用性和功能。

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

嵌入外部托管的视频

要嵌入来自外部平台的视频,可以使用 Next.js 获取视频信息,并使用 React Suspense 处理加载时的回退状态。

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

第一步是创建一个服务端组件,生成用于嵌入视频的 iframe。该组件将获取视频的源 URL 并渲染 iframe。

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

  return <iframe src={src} frameborder="0" 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 或视频播放器适应不同屏幕尺寸。
  • 根据网络条件实现视频加载策略,特别是对于数据流量有限的用户。

这种方法提供了更好的用户体验,因为它避免了页面阻塞,用户可以在视频组件流式传输时与页面交互。

为了提供更具吸引力和信息性的加载体验,可以考虑使用加载骨架作为回退 UI。例如,可以显示一个类似于视频播放器的骨架:

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 兼容的可扩展云存储解决方案。以下是使用 Vercel Blob 托管视频的方法:

1. 上传视频到 Vercel Blob

在 Vercel 仪表板中,导航至“存储”选项卡并选择您的 Vercel Blob 存储。在 Blob 表格的右上角,找到并点击“上传”按钮。然后选择要上传的视频文件。上传完成后,视频文件将出现在 Blob 表格中。

或者,您可以使用服务端操作上传视频。详细说明请参阅 Vercel 关于服务端上传的文档。Vercel 还支持客户端上传。此方法可能更适合某些用例。

2. 在 Next.js 中显示视频

视频上传并存储后,可以在 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" />
      Your browser does not support the video tag.
    </video>
  )
}

在此方法中,页面使用视频的 @vercel/blob URL 通过 VideoComponent 显示视频。React Suspense 用于在获取视频 URL 并准备显示视频之前显示回退内容。

为视频添加字幕

如果视频有字幕,可以使用 <track> 元素在 <video> 标签内轻松添加。可以从 Vercel Blob 获取字幕文件,方法与视频文件类似。以下是更新 <VideoComponent> 以包含字幕的方式。

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">
      Your browser does not support the video tag.
    </video>
  );
};

通过这种方式,可以有效地自托管并将视频集成到 Next.js 应用中。

资源

如需了解更多关于视频优化和最佳实践的内容,请参考以下资源:

  • 了解视频格式和编解码器:根据需求选择合适的格式和编解码器,例如 MP4 用于兼容性或 WebM 用于网络优化。详情请参阅 Mozilla 的视频编解码器指南
  • 视频压缩:使用 FFmpeg 等工具有效压缩视频,平衡质量和文件大小。学习压缩技术请访问 FFmpeg 官方网站
  • 分辨率和比特率调整:根据观看平台调整分辨率和比特率,移动设备使用较低的设置。
  • 内容分发网络 (CDN):利用 CDN 提高视频传输速度并管理高流量。使用某些存储解决方案(如 Vercel Blob)时,CDN 功能会自动处理。了解更多关于 CDN 及其优势的内容。

探索以下视频流平台,将视频集成到 Next.js 项目中:

开源 next-video 组件

  • 为 Next.js 提供 <Video> 组件,兼容多种托管服务,包括 Vercel Blob、S3、Backblaze 和 Mux。
  • 详细文档介绍了如何将 next-video.dev 与不同托管服务一起使用。

Cloudinary 集成

Mux Video API

  • Mux 提供了入门模板,用于使用 Mux 和 Next.js 创建视频课程。
  • 了解 Mux 关于为 Next.js 应用嵌入高性能视频的建议。
  • 探索示例项目,演示了 Mux 与 Next.js 的集成。

Fastly