Capítulo 96 de 456

Videos

Core Idea

Recomendações para embutir vídeo em Next.js sem prejudicar performance: <video> para conteúdo self-hosted/direto, <iframe> para plataformas externas (YouTube, Vimeo), e streaming via Server Component + Suspense para não bloquear a página.

Key Concepts

  • <video>: controle total sobre playback/aparência para conteúdo self-hosted; suporta <track> para legendas.
  • <iframe>: para vídeos hospedados em plataformas externas; menos controle, mais praticidade.
  • autoPlay + muted + playsInline: combinação necessária para autoplay funcionar na maioria dos browsers, especialmente iOS Safari.
  • Server Component + <Suspense>: padrão recomendado pra buscar a URL de embed de um vídeo externo sem bloquear o resto da página — o fetch acontece no Server Component, e o fallback (idealmente um skeleton) é mostrado enquanto resolve.
  • Vercel Blob: solução de hosting sugerida para self-hosted, com CDN automático; usar list() do @vercel/blob para obter a URL do arquivo.
  • Bibliotecas de terceiros: next-video (compatível com Vercel Blob, S3, Backblaze, Mux), Cloudinary (<CldVideoPlayer>), Mux, Fastly, ImageKit (<IKVideo>).

Code Examples

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>
  )
}
  • O que demonstra: vídeo self-hosted com controles, preload="none" e legendas via <track>.
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'

export default function Page() {
  return (
    <section>
      <Suspense fallback={<p>Loading video...</p>}>
        <VideoComponent />
      </Suspense>
    </section>
  )
}
export default async function VideoComponent() {
  const src = await getVideoSrc()
  return <iframe src={src} allowFullScreen />
}
  • O que demonstra: Server Component assíncrono que busca a URL de embed, envolto em <Suspense> para não bloquear a página.
import { list } from '@vercel/blob'

async function VideoComponent({ fileName }) {
  const { blobs } = await list({ prefix: fileName, limit: 1 })
  const { url } = blobs[0]
  return (
    <video controls preload="none" aria-label="Video player">
      <source src={url} type="video/mp4" />
    </video>
  )
}
  • O que demonstra: obter a URL de um vídeo hospedado no Vercel Blob e renderizá-lo.

Reference Tables

Atributo <video>Descrição
controlsExibe controles padrão de playback
autoPlayInicia automaticamente (exige muted na maioria dos browsers)
loopRepete o playback
mutedSilencia áudio por padrão, geralmente com autoPlay
preloadnone / metadata / auto
playsInlineNecessário pra autoplay funcionar em iOS Safari
Atributo <iframe>Descrição
allowFullScreenPermite fullscreen
loadingEx. lazy
sandboxRestrições adicionais de conteúdo

Anti-patterns

  • Usar autoPlay sem muted: a maioria dos browsers bloqueia autoplay com áudio.
  • Fetch de dados de vídeo externo bloqueando a página inteira: use Server Component + <Suspense> em vez de aguardar no componente pai.

Key Takeaways

  1. Escolha <video> para controle total e <iframe> para conveniência de plataformas externas.
  2. Sempre inclua fallback content e <track> para acessibilidade (legendas).
  3. Streaming via Suspense evita que a busca da URL do vídeo bloqueie o resto da página.

Connects To

  • Streaming (ch083): mesmo padrão de Suspense boundary aplicado aqui a componentes de vídeo.
  • Self-Hosting (ch078): contexto mais amplo de hospedar assets próprios.