next-video O próximo vídeo é um componente React para adicionar vídeo ao seu aplicativo Next.js. Ele estende o elemento <video> e seu próximo aplicativo com recursos para otimização automática de vídeo.
import Video from 'next-video' ;
import getStarted from '/videos/get-started.mp4' ;
export default function Page ( ) {
return < Video src = { getStarted } /> ;
} Na raiz do seu projeto Next.js, Run:
npx -y next-video initIsso irá (com promoção):
next-video como uma dependêncianext.config.js/videos em seu projeto, onde você colocará todos os arquivos de origem de vídeo. Ele também atualizará seu arquivo .gitignore para ignorar os arquivos de vídeo no diretório /videos . Os vídeos, particularmente qualquer tamanho razoável, não devem ser armazenados/rastreados pelo Git. Como alternativa, se você quiser armazenar os arquivos originais, poderá remover as linhas Gitignore adicionadas e instalar o Git-LFS.
A Vercel recomenda o uso de uma plataforma de conteúdo dedicada para vídeo, porque os arquivos de vídeo são grandes e podem levar ao uso excessivo de largura de banda. Por padrão, o próximo vídeo usa o MUX (uma API de vídeo para desenvolvedores), que é construída pelos criadores do vídeo.js, alimenta aplicativos populares de streaming como Patreon e cujo monitoramento de desempenho em vídeo é usado nos maiores eventos ao vivo do mundo.
.env.local (ou no entanto você exportar variáveis ENV locais) # .env.local
MUX_TOKEN_ID=[YOUR_TOKEN_ID]
MUX_TOKEN_SECRET=[YOUR_TOKEN_SECRET] cd your-next-app
# If your project is using NPM (the default for Next.js)
npm install next-video
# If your project is using Yarn
yarn add next-video
# If your project is using pnpm
pnpm add next-video next.config.js
Se você estiver usando os módulos Commonjs:
const { withNextVideo } = require ( 'next-video/process' ) ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ; // Your current Next Config object
module . exports = withNextVideo ( nextConfig ) ; next.config.mjs
Se você está usando os módulos ES:
import { withNextVideo } from 'next-video/process' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; tsconfig.json Isso só é necessário se você estiver usando o TypeScript e garante que a sua importação de arquivos de vídeo não grite com você para obter tipos ausentes. video.d.ts deve ter sido criado em seu projeto ROOT quando você executou npx next-video init , se não, você pode criá-lo manualmente:
// video.d.ts
/// <reference types="next-video/video-types/global" /> Em seguida, adicione esse arquivo à matriz include em tsconfig.json .
{
// ...
"include" : [ "video.d.ts" , "next-env.d.ts" , /* ... */ ]
// ...
} Adicione vídeos localmente ao diretório /videos e execute npx next-video sync . Os vídeos serão enviados automaticamente para armazenamento remoto e otimizados. Você notará os arquivos /videos/[file-name].json também são criados. Eles são usados para mapear seus arquivos de vídeo locais para os novos ativos de vídeo hostedosos. Esses arquivos JSON devem ser verificados no Git.
npx next-video sync
Você também pode adicionar next-video sync -w ao script de dev para sincronizar automaticamente vídeos conforme adicionado a /videos enquanto o servidor de desenvolvimento estiver em execução.
// package.json
"scripts" : {
"dev" : "next dev & npx next-video sync -w" ,
} , Agora você pode usar o componente <Video> em seu aplicativo. Digamos que você tenha adicionado um arquivo chamado awesome-video.mp4 para /videos
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
} Enquanto um vídeo estiver sendo carregado e processado, <Video> tentará reproduzir o arquivo local. Isso só acontece durante o desenvolvimento local, porque o arquivo local nunca é enviado para o seu repositório Git.
Para vídeos que já estão hospedados remotamente (por exemplo, no AWS S3), importe o URL remoto e atualize a página. Isso cria um arquivo JSON local na pasta /videos e o script de sincronização começará a fazer o upload do vídeo.
import Video from 'next-video' ;
import awesomeVideo from 'https://www.mydomain.com/remote-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
}Se o vídeo hospedado for um único arquivo como um MP4, o arquivo será otimizado automaticamente para obter uma melhor entrega e compatibilidade.
Em alguns casos, você pode não ter os URLs de vídeo remoto disponíveis no momento da importação.
Isso pode ser resolvido pela criação de um novo endpoint da API em seu aplicativo Next.js para /api/video com o código a seguir.
Roteador de aplicativos (next.js> = 13)
// app/api/video/route.js
export { GET } from 'next-video/request-handler' ;Páginas roteador (Next.js)
// pages/api/video/[[...handler]].js
export { default } from 'next-video/request-handler' ; Em seguida, defina o atributo src para o URL do vídeo remoto, atualize a página e o vídeo começará a processar.
import Video from 'next-video' ;
export default function Page ( ) {
return < Video src = "https://www.mydomain.com/remote-video.mp4" /> ;
} Você pode alterar o tema do jogador, passando o suporte theme para o componente <Video> .
Veja Player.style para obter mais temas.
import Video from 'next-video' ;
import Instaplay from 'player.style/instaplay/react' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } theme = { Instaplay } /> ;
} Como v1.1.0 você pode importar o componente do jogador diretamente e usá -lo sem nenhum recurso de upload e processamento.
import Player from 'next-video/player' ;
// or
import BackgroundPlayer from 'next-video/background-player' ;
export default function Page ( ) {
return < Player
src = "https://www.mydomain.com/remote-video.mp4"
poster = "https://www.mydomain.com/remote-poster.webp"
blurDataURL = "data:image/webp;base64,UklGRlA..."
/> ;
}Você pode adicionar um pôster personalizado e Blurdataurl ao vídeo, passando -os como adereços.
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
import awesomePoster from '../public/images/awesome-poster.jpg' ;
export default function Page ( ) {
return < Video
src = { awesomeVideo }
poster = { awesomePoster . src }
blurDataURL = { awesomePoster . blurDataURL }
/> ;
}Esta é uma boa solução, mas não fornecerá o mesmo nível de otimização que o pôster automático e o BlurDataurl pelo provedor padrão.
Para obter o mesmo nível de otimização, você pode usar um elemento de pôster com fenda.
Adicione um elemento de imagem de pôster com fenda (como next/image ) ao vídeo, passando -o quando criança com um atributo slot="poster" .
Agora, sua imagem obterá todos os benefícios do componente de imagem usada e será bem colocada atrás dos controles do player de vídeo.
import Image from 'next/image' ;
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
import awesomePoster from '../public/images/awesome-poster.jpg' ;
export default function Page ( ) {
return (
< Video src = { awesomeVideo } >
< Image
slot = "poster"
src = { awesomePoster }
placeholder = "blur"
alt = "Some peeps doing something awesome"
/>
</ Video >
) ;
} Você pode personalizar o jogador passando um componente de jogador personalizado para o as Prop.
O componente do player personalizado aceita os seguintes adereços:
asset : o ativo que é processado, contém metadados de ativos úteis e status de upload.src : um URL de origem de vídeo de string se o ativo estiver pronto.poster : Um URL da fonte de imagem da string se o ativo estiver pronto.blurDataURL : um URL de fonte de imagem Base64 String64 que pode ser usado como espaço reservado. import Video from 'next-video' ;
import ReactPlayer from './player' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video as = { ReactPlayer } src = { awesomeVideo } /> ;
} // player.tsx
'use client' ;
import type { PlayerProps } from 'next-video' ;
import ReactPlayer from 'react-player' ;
export default function Player ( props : PlayerProps ) {
let { asset , src , poster , blurDataURL , thumbnailTime , ... rest } = props ;
let config = { file : { attributes : { poster } } } ;
return < ReactPlayer
url = { src }
config = { config }
width = "100%"
height = "100%"
{ ... rest }
/> ;
} Você pode usar um componente <BackgroundVideo> para adicionar um vídeo como um plano de fundo sem controles de jogador. Isso economiza cerca de 50% do tamanho do JS Player e é otimizado para o uso de vídeo em segundo plano.
O componente <BackgroundVideo> é um jogador personalizado como você viu na seção anterior.
O parâmetro de consulta thumbnailTime no exemplo abaixo é usado para gerar uma imagem de pôster e desfocar a imagem no tempo especificado no vídeo (limitado ao uso com o provedor mux ).
import BackgroundVideo from 'next-video/background-video' ;
import getStarted from '/videos/country-clouds.mp4?thumbnailTime=0' ;
export default function Page ( ) {
return (
< BackgroundVideo src = { getStarted } >
< h1 > next-video </ h1 >
< p >
A React component for adding video to your Next.js application.
It extends both the video element and your Next app with features
for automatic video optimization.
</ p >
</ BackgroundVideo >
) ;
} Você pode escolher entre diferentes fornecedores para processamento de vídeo e hospedagem. O provedor padrão é MUX. Para alterar o provedor, você pode adicionar uma opção provider na configuração do próximo vídeo. Alguns provedores exigem configuração adicional que possa ser passada na propriedade providerConfig .
// next.config.js
const { withNextVideo } = require ( 'next-video/process' ) ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
module . exports = withNextVideo ( nextConfig , {
provider : 'backblaze' ,
providerConfig : {
backblaze : { endpoint : 'https://s3.us-west-000.backblazeb2.com' }
}
} ) ;Provedores suportados com suas variáveis de ambiente exigidas:
| Provedor | Ambiente Vars | Config do provedor | Link de preços |
|---|---|---|---|
mux (padrão) | MUX_TOKEN_IDMUX_TOKEN_SECRET | Preço | |
vercel-blob | BLOB_READ_WRITE_TOKEN | Preço | |
backblaze | BACKBLAZE_ACCESS_KEY_IDBACKBLAZE_SECRET_ACCESS_KEY | endpointbucket (opcional) | Preço |
amazon-s3 | AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY | endpointbucket (opcional) | Preço |
cloudflare-r2 | R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_CF_API_TOKEN (opcional quando o conjunto bucketUrlPublic ) | bucket (opcional)bucketUrlPublic (opcional quando R2_CF_API_TOKEN set) | Preço |
| Mux (padrão) | VERCEL BLOB | Backblaze | Amazon S3 | Cloudflare R2 | |
|---|---|---|---|---|---|
| Armazenamento Off-Repo | ✅ | ✅ | ✅ | ✅ | ✅ |
| Entrega via CDN | ✅ | ✅ | - | - | ✅ |
| BYO Player | ✅ | ✅ | ✅ | ✅ | ✅ |
| Comprimido para streaming | ✅ | - | - | - | |
| Adaptar -se às redes lentas (HLS) | ✅ | - | - | - | |
| Pôster automático de espaço reservado | ✅ | - | - | - | |
| Linha do tempo pairam miniaturas | ✅ | - | - | - | |
| Transmitir qualquer formato de origem | ✅ | * | * | * | * |
| Legendas e legendas ai | ✅ | - | - | - | |
| Análise de vídeo | ✅ | - | - | - | |
| Preço | Baseado em minutos | Baseado em GB | Baseado em GB | Baseado em GB | Baseado em GB |
*Arquivos MP4 compatíveis com a Web necessários para provedores de hospedagem sem processamento de vídeo
Por padrão, os metadados do ativo são armazenados em um arquivo json no diretório /videos . Se você deseja armazenar os metadados em um banco de dados ou em outro lugar, poderá personalizar os ganchos de armazenamento em um arquivo de configuração do próximo vídeo separado.
A configuração de exemplo abaixo mostra os ganchos de armazenamento padrão para o armazenamento de arquivos JSON.
Esses ganchos podem ser personalizados para atender às suas necessidades, alterando as funções do corpo das funções loadAsset , saveAsset e updateAsset .
// next-video.mjs
import { NextVideo } from 'next-video/process' ;
import path from 'node:path' ;
import { mkdir , readFile , writeFile } from 'node:fs/promises' ;
export const { GET , POST , handler , withNextVideo } = NextVideo ( {
// Other next-video config options should be added here if using a next-video config file.
// folder: 'videos',
// path: '/api/video',
loadAsset : async function ( assetPath ) {
const file = await readFile ( assetPath ) ;
const asset = JSON . parse ( file . toString ( ) ) ;
return asset ;
} ,
saveAsset : async function ( assetPath , asset ) {
try {
await mkdir ( path . dirname ( assetPath ) , { recursive : true } ) ;
await writeFile ( assetPath , JSON . stringify ( asset ) , {
flag : 'wx' ,
} ) ;
} catch ( err ) {
if ( err . code === 'EEXIST' ) {
// The file already exists, and that's ok in this case. Ignore the error.
return ;
}
throw err ;
}
} ,
updateAsset : async function ( assetPath , asset ) {
await writeFile ( assetPath , JSON . stringify ( asset ) ) ;
}
} ) ; Em seguida, importe a função withNextVideo no seu arquivo next.config.mjs .
// next.config.mjs
import { withNextVideo } from './next-video.mjs' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; Por fim, importe as funções GET and POST , ou handler em suas rotas de API, como você achar melhor. Os manipuladores esperam uma consulta url ou parâmetro corporal com o URL da fonte de vídeo.
Estes são os exemplos mais mínimos para os manipuladores, normalmente você adicionaria mais tratamento de erros e validação, autenticação e autorização.
Roteador de aplicativos (next.js> = 13)
// app/api/video/route.js
export { GET , POST } from '@/next-video' ;Páginas roteador (Next.js)
// pages/api/video/[[...handler]].js
export { handler as default } from '@/next-video' ; O jogador padrão é construído com o Media Chrome.
<video> nativo.<mux-video> .<hls-video> .<dash-video> . O componente <Video> aceita todos os adereços do elemento <video> e os seguintes adereços adicionais:
src (ativo | string): o objeto de ativo de vídeo (importação) ou URL de origem.poster (StaticImagedata | String): Uma imagem de espaço reservado para o vídeo. (Gerado automaticamente para vídeos mux)blurDataURL (String): um URL da fonte de imagem BASE64 que pode ser usado como espaço reservado. (Gerado automaticamente para vídeos mux)theme (componente React): o componente temático do jogador. Veja Player.style para obter mais temas.as (Componente React): um componente de player personalizado. Veja o jogador personalizado.transform (função): uma função personalizada para transformar o objeto de ativo (SRC e o pôster).loader (função): uma função personalizada usada para resolver URLs de vídeo baseados em string (não importações). O componente <Video> com uma fonte de vídeo mux aceita os seguintes adereços adicionais:
startTime (número): a hora de início do vídeo em segundos.streamType ("sob demanda" | "Live"): o tipo de fluxo do vídeo. O padrão está "sob demanda".customDomain (String): atribui um domínio personalizado a ser usado para o vídeo MUX.beaconCollectionDomain (string): atribui um domínio personalizado a ser usado para a coleta de dados MUX. NOTA: Deve ser definido antes do PlaybackId para se aplicar ao MUX Data Monitoring.envKey (String): Esta é a chave do ambiente para os dados MUX. Se você usar o vídeo mux, isso é automaticamente definido para você. Se você usar um provedor diferente, poderá definir isso para sua própria chave.disableTracking (booleano): desativa o rastreamento de dados do MUX da reprodução de vídeo.disableCookies (booleanos): desativa os cookies usados pelos dados MUX.preferPlayback ("mse" | "nativo"): especifique se <mux-video> deve tentar usar a extensão da fonte de mídia ou a reprodução nativa (se disponível). Se nenhum valor for fornecido, <mux-video> escolherá com base no que é considerado ideal para o ambiente de conteúdo e reprodução.maxResolution ("720p" | "1080p" | "1440p" | "2160p"): especifique a resolução máxima que você deseja entregar para este vídeo.minResolution ("480p" | "540p" | "720p" | "1080p" | "1440p" | "2160p"): especifique a resolução mínima que você deseja entregue para este vídeo.programStartTime (número): aplique clipes instantâneos baseados em PDT no início do fluxo de mídia.programEndTime (número): aplique clipes instantâneos baseados em PDT no final do fluxo de mídia.assetStartTime (número): aplique clipes instantâneos baseados em cronogramas de mídia no início do fluxo de mídia.assetEndTime (número): aplique clipes instantâneos baseados em cronograma de mídia até o final do fluxo de mídia.renditionOrder (string): altere a ordem na qual as reproduções são fornecidas na lista de reprodução do SRC. Pode afetar as cargas iniciais do segmento. Atualmente, apenas apoie "DEC" para a ordem descendente.metadataVideoId (String): Este é um ID arbitrário enviado aos dados MUX que devem mapear de volta a um registro deste vídeo no seu banco de dados.metadataTitle (String): Este é um título arbitrário para o seu vídeo que será passado como metadados nos dados mux. A adição de um título fornecerá um contexto útil no seu painel de dados MUX. (opcional, mas encorajado)metadataViewerUserId (String): Se você tiver um usuário conectado, esse deve ser um valor de ID anonimizado que mapeie o usuário no seu banco de dados que será enviado aos dados MUX. Tome cuidado para não expor informações identificáveis pessoais, como nomes, nomes de usuário ou endereços de email. (opcional, mas encorajado)metadata* (String): Esta sintaxe de metadados* pode ser usada para passar por quaisquer campos de metadados de dados mux arbitrários.playbackToken (String): O token de reprodução por assinar o URL src .thumbnailToken (String): O token para assinar o URL poster .storyboardToken (String): O token para assinar o URL do storyboard.drmToken (String): O token para assinar a licença DRM e URLs relacionados.targetLiveWindow (número): um deslocamento que representa o intervalo buscável para conteúdo vivo, onde Infinity significa que todo o conteúdo do vivo é procurado (também conhecido como "DVR padrão"). Usado junto com streamType para determinar o que a interface do usuário/controles para mostrar.liveEdgeOffset (número): o primeiro tempo de reprodução que será tratado como tocando "no The Live Edge" para conteúdo ao vivo.debug (Boolean): Ativa o modo de depuração para o mecanismo de reprodução subjacente (atualmente HLS.JS) e MUX-Enchebed, fornecendo informações adicionais no console. {
"Version" : " 2012-10-17 " ,
"Statement" : [
{
"Effect" : " Allow " ,
"Action" : [
" s3:ListAllMyBuckets " ,
" s3:CreateBucket " ,
" s3:PutBucketOwnershipControls "
],
"Resource" : " * "
},
{
"Effect" : " Allow " ,
"Action" : [
" s3:PutBucketPublicAccessBlock " ,
" s3:PutBucketAcl " ,
" s3:PutBucketCORS " ,
" s3:GetObject " ,
" s3:PutObject " ,
" s3:PutObjectAcl " ,
" s3:ListBucket "
],
"Resource" : " arn:aws:s3:::next-videos-* "
}
]
}Configure o balde para acesso público:
bucket na configuração do provedor e verifique se está configurado para acesso públicobucketUrlPublicForneça uma chave da API CloudFlare:
R2_CF_API_TOKENSe você deseja se desenvolver nessa coisa localmente, pode clonar e vincular esse otário. Apenas saiba ... não é um ótimo momento agora.
cd no reponpm install && npm run buildcd ../ (ou de volta para onde você deseja criar um aplicativo de teste)npx create-next-appcd your-next-appnpx link ../next-video (ou onde você clonou este repo)