next-video El siguiente video es un componente React para agregar video a su aplicación Next.js. Extiende tanto el elemento <video> como su próxima aplicación con características para la optimización automática de video.
import Video from 'next-video' ;
import getStarted from '/videos/get-started.mp4' ;
export default function Page ( ) {
return < Video src = { getStarted } /> ;
} En la raíz de su próximo proyecto.js, ejecute:
npx -y next-video initEsto lo hará (con la solicitud):
next-video como dependencianext.config.js/videos en su proyecto, que es donde colocará todos los archivos de origen de video. También actualizará su archivo .gitignore para ignorar los archivos de video en el directorio /videos . Los videos, particularmente cualquier tamaño razonable, no deben almacenar/rastrear por Git. Alternativamente, si desea almacenar los archivos originales, puede eliminar las líneas Gitignore agregadas e instalar GIT-LFS.
Vercel recomienda usar una plataforma de contenido dedicada para video porque los archivos de video son grandes y pueden conducir a un uso excesivo de ancho de banda. De forma predeterminada, el próximo video usa MUX (una API de video para desarrolladores), que es construido por los creadores de video.js, potencia aplicaciones de transmisión populares como Patreon y cuyo monitoreo de rendimiento de video se usa en los eventos en vivo más grandes del mundo.
.env.local (o sin embargo, exporte las variables de Env) # .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
Si está utilizando 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
Si estás usando módulos ES:
import { withNextVideo } from 'next-video/process' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; tsconfig.json Esto solo es necesario si está usando TypeScript y se asegura de que las importaciones de su archivo de video no le griten por los tipos faltantes. video.d.ts debería haberse creado en la raíz de su proyecto cuando ejecutó npx next-video init , si no puede crearlo manualmente:
// video.d.ts
/// <reference types="next-video/video-types/global" /> Luego agregue ese archivo a la matriz include en tsconfig.json .
{
// ...
"include" : [ "video.d.ts" , "next-env.d.ts" , /* ... */ ]
// ...
} Agregue videos localmente al directorio /videos y luego ejecute npx next-video sync . Los videos se cargarán automáticamente en almacenamiento remoto y se optimizarán. Notará /videos/[file-name].json Los archivos también se crean. Estos se utilizan para asignar sus archivos de video locales a los nuevos activos de video de alojamiento remoto. Estos archivos JSON deben verificarse en GIT.
npx next-video sync
También puede agregar next-video sync -w al script de desarrollo para sincronizar automáticamente videos a medida que se agregan /videos mientras el servidor Dev se está ejecutando.
// package.json
"scripts" : {
"dev" : "next dev & npx next-video sync -w" ,
} , Ahora puede usar el componente <Video> en su aplicación. Digamos que ha agregado un archivo llamado awesome-video.mp4 a /videos
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
} Mientras se cargue y procesa un video, <Video> intentará reproducir el archivo local. Esto solo sucede durante el desarrollo local porque el archivo local nunca se carga en su repositorio GIT.
Para los videos que ya están alojados de forma remota (por ejemplo en AWS S3), importe la URL remota y actualice la página. Esto crea un archivo JSON local en la carpeta /videos y el script de sincronización comenzará a cargar el video.
import Video from 'next-video' ;
import awesomeVideo from 'https://www.mydomain.com/remote-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
}Si el video alojado es un solo archivo como un MP4, el archivo se optimizará automáticamente para una mejor capacidad de entrega y compatibilidad.
En algunos casos, es posible que no tenga la URL de video remota disponibles en el momento de la importación.
Eso se puede resolver creando un nuevo punto final API en su aplicación Next.js para /api/video con el siguiente código.
Enrutador de aplicaciones (next.js> = 13)
// app/api/video/route.js
export { GET } from 'next-video/request-handler' ;Enrutador de páginas (Next.js)
// pages/api/video/[[...handler]].js
export { default } from 'next-video/request-handler' ; Luego configure el atributo src en la URL del video remoto, actualice la página y el video comenzará a procesarse.
import Video from 'next-video' ;
export default function Page ( ) {
return < Video src = "https://www.mydomain.com/remote-video.mp4" /> ;
} Puede cambiar el tema del reproductor pasando el accesorio theme al componente <Video> .
Ver jugador. Estilo para más 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 } /> ;
} Desde v1.1.0 , puede importar el componente del reproductor directamente y usarlo sin ninguna característica de carga y procesamiento.
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..."
/> ;
}Puede agregar un póster personalizado y blurdataurl al video pasándolos como accesorios.
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 es una buena solución, pero no proporcionará el mismo nivel de optimización que el póster automático y el blurdataurl por el proveedor predeterminado.
Para obtener el mismo nivel de optimización, puede usar un elemento de póster ranurado.
Agregue un elemento de imagen de póster ranurado (como next/image ) al video pasándolo como un niño con un atributo slot="poster" .
Ahora su imagen obtendrá todos los beneficios del componente de imagen usado y se colocará bien detrás de los controles del reproductor de video.
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 >
) ;
} Puede personalizar el reproductor pasando un componente de reproductor personalizado al as AS.
El componente del reproductor personalizado acepta los siguientes accesorios:
asset : el activo que se procesa, contiene metadatos de activo útiles y estado de carga.src : URL de fuente de video de cadena si el activo está listo.poster : una URL de fuente de imagen de cadena si el activo está listo.blurDataURL : una URL de fuente de imagen de String Base64 que puede usarse como marcador de posición. 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 }
/> ;
} Puede usar un componente <BackgroundVideo> para agregar un video como fondo sin controles de reproductor. Esto ahorra alrededor del 50% del tamaño del jugador JS y está optimizado para el uso de videos de fondo.
El componente <BackgroundVideo> es un reproductor personalizado como lo vio en la sección anterior.
El parámetro de consulta thumbnailTime en el siguiente ejemplo se utiliza para generar una imagen de póster y difuminar la imagen en el tiempo especificado en el video (limitado al uso con el proveedor 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 >
) ;
} Puede elegir entre diferentes proveedores para el procesamiento y alojamiento de videos. El proveedor predeterminado es MUX. Para cambiar el proveedor, puede agregar una opción provider en la configuración de próxima video. Algunos proveedores requieren una configuración adicional que se puede aprobar en la propiedad 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' }
}
} ) ;Proveedores admitidos con sus variables de entorno requeridas:
| Proveedor | Entorno vars | Configuración del proveedor | Enlace de precios |
|---|---|---|---|
mux (predeterminado) | MUX_TOKEN_IDMUX_TOKEN_SECRET | Fijación de precios | |
vercel-blob | BLOB_READ_WRITE_TOKEN | Fijación de precios | |
backblaze | BACKBLAZE_ACCESS_KEY_IDBACKBLAZE_SECRET_ACCESS_KEY | endpointbucket (opcional) | Fijación de precios |
amazon-s3 | AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY | endpointbucket (opcional) | Fijación de precios |
cloudflare-r2 | R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_CF_API_TOKEN (opcional cuando bucketUrlPublic Set) | bucket (opcional)bucketUrlPublic (opcional cuando se establece R2_CF_API_TOKEN ) | Fijación de precios |
| Mux (predeterminado) | Mancha de contrelaje | Falso | Amazon S3 | Cloudflare R2 | |
|---|---|---|---|---|---|
| Almacenamiento fuera de REPO | ✅ | ✅ | ✅ | ✅ | ✅ |
| Entrega a través de CDN | ✅ | ✅ | - | - | ✅ |
| BYO Jugador | ✅ | ✅ | ✅ | ✅ | ✅ |
| Comprimido para la transmisión | ✅ | - | - | - | |
| Adaptarse a redes lentas (HLS) | ✅ | - | - | - | |
| Póster automático de marcador de posición | ✅ | - | - | - | |
| Miniaturas de la línea de tiempo de la línea de tiempo | ✅ | - | - | - | |
| Transmitir cualquier formato de fuente | ✅ | * | * | * | * |
| Subtítulos y subtítulos de IA | ✅ | - | - | - | |
| Análisis de video | ✅ | - | - | - | |
| Fijación de precios | Basado en actas | Basado en GB | Basado en GB | Basado en GB | Basado en GB |
*Archivos MP4 compatibles con la web requeridos para alojamiento de proveedores sin procesamiento de video
Por defecto, los metadatos de activos se almacenan en un archivo JSON en el directorio /videos . Si desea almacenar los metadatos en una base de datos o en otro lugar, puede personalizar los ganchos de almacenamiento en un archivo de configuración de próxima video separado.
La configuración de ejemplo a continuación muestra los ganchos de almacenamiento predeterminados para el almacenamiento de archivos JSON.
Estos ganchos se pueden personalizar para satisfacer sus necesidades cambiando el cuerpo de las funciones loadAsset , saveAsset y 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 ) ) ;
}
} ) ; Luego importe la función withNextVideo en su archivo next.config.mjs .
// next.config.mjs
import { withNextVideo } from './next-video.mjs' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; Por último, importe las funciones GET y POST , o handler en sus rutas API como mejor le parezca. Los manejadores esperan una consulta url o parámetro de cuerpo con la URL de la fuente de video.
Estos son los ejemplos más mínimos para los manejadores, generalmente agregaría más manejo y validación de errores, autenticación y autorización.
Enrutador de aplicaciones (next.js> = 13)
// app/api/video/route.js
export { GET , POST } from '@/next-video' ;Enrutador de páginas (Next.js)
// pages/api/video/[[...handler]].js
export { handler as default } from '@/next-video' ; El reproductor predeterminado está construido con Media Chrome.
<video> .<mux-video> .<hls-video> .<dash-video> . El componente <Video> acepta todos los accesorios del elemento <video> y los siguientes accesorios adicionales:
src (Asset | String): el objeto de activo de video (importación) o URL de origen.poster (staticimagedata | cadena): una imagen de marcador de posición para el video. (Auto generado para videos mux)blurDataURL (cadena): una URL de fuente de imagen Base64 que se puede usar como marcador de posición. (Auto generado para videos mux)theme (componente React): el componente del tema del reproductor. Ver jugador. Estilo para más temas.as (componente React): un componente de reproductor personalizado. Ver jugador personalizado.transform (función): una función personalizada para transformar el objeto de activo (SRC y póster).loader (función): una función personalizada utilizada para resolver URL de video basadas en cadenas (no importaciones). El componente <Video> con una fuente de video MUX acepta los siguientes accesorios adicionales:
startTime (número): la hora de inicio del video en segundos.streamType ("bajo demanda" | "Live"): el tipo de transmisión del video. El valor predeterminado es "bajo demanda".customDomain (String): asigna un dominio personalizado que se utilizará para el video MUX.beaconCollectionDomain (String): asigna un dominio personalizado que se utilizará para la recopilación de datos MUX. Nota: Debe establecerse antes de reproducción para aplicar al monitoreo de datos MUX.envKey (String): esta es la clave de entorno para los datos MUX. Si usa el video MUX, esto se establece automáticamente para usted. Si usa un proveedor diferente, puede establecer esto en su propia clave.disableTracking (Boolean): deshabilita el seguimiento de datos MUX de la reproducción de video.disableCookies (booleano): deshabilita las cookies utilizadas por los datos MUX.preferPlayback ("MSE" | "Nativo"): especifique si <mux-video> debería intentar usar la extensión de la fuente de medios o la reproducción nativa (si está disponible). Si no se proporciona ningún valor, <mux-video> elegirá en función de lo que se considera óptimo para el entorno de contenido y reproducción.maxResolution ("720p" | "1080p" | "1440p" | "2160p"): Especifique la resolución máxima que desea entregar para este video.minResolution ("480p" | "540p" | "720p" | "1080p" | "1440p" | "2160p"): Especifique la resolución mínima que desea entregar para este video.programStartTime (número): aplique clips instantáneos basados en PDT al comienzo de la transmisión de medios.programEndTime (número): aplique clips instantáneos basados en PDT al final de la transmisión de medios.assetStartTime (número): aplique clips instantáneos basados en la línea de tiempo de medios al comienzo de la transmisión de medios.assetEndTime (número): aplique clips instantáneos basados en la línea de tiempo de medios al final de la transmisión de medios.renditionOrder (String): Cambie el orden en el que se proporcionan representaciones en la lista de reproducción de SRC. Puede afectar las cargas iniciales del segmento. Actualmente, solo admite "Desc" para el orden descendente.metadataVideoId (cadena): esta es una ID arbitraria enviada a datos MUX que deberían volver a un registro de este video en su base de datos.metadataTitle (cadena): este es un título arbitrario para su video que se pasará como metadatos en datos MUX. Agregar un título le brindará un contexto útil en su panel de datos de MUX. (opcional, pero alentado)metadataViewerUserId (cadena): si tiene un usuario iniciado, este debería ser un valor de identificación anonimizado que se mapea al usuario en su base de datos que se enviará a los datos MUX. Tenga cuidado de no exponer información identificable personal, como nombres, nombres de usuario o direcciones de correo electrónico. (opcional, pero alentado)metadata* (cadena): esta sintaxis de metadatos* se puede usar para pasar los campos de metadatos de datos MUX arbitrarios.playbackToken (cadena): el token de reproducción para firmar la URL src .thumbnailToken (cadena): el token para firmar la URL poster .storyboardToken (cadena): el token para firmar la URL del guión gráfico.drmToken (cadena): el token para firmar la licencia DRM y las URL relacionadas.targetLiveWindow (número): un desplazamiento que representa el rango solicitable para el contenido vivo, donde Infinity significa que todo el contenido en vivo se puede buscar (también conocido como "DVR estándar"). Usado junto con streamType para determinar qué UI/controles mostrar.liveEdgeOffset (número): el primer tiempo de reproducción que se tratará como tocando "en Live Edge" para contenido en vivo.debug (Boolean): habilita el modo de depuración para el motor de reproducción subyacente (actualmente HLS.JS) y MUX-Embed, proporcionando información adicional en la consola. {
"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 el cubo para el acceso público:
bucket en la configuración del proveedor y asegúrese de que esté configurado para el acceso públicobucketUrlPublicProporcione una tecla API de CloudFlare:
R2_CF_API_TOKENSi desea desarrollarse en esto localmente, puede clonar y vincular este tonto. Solo sé ... no es un gran momento en este momento.
cd en el repositorionpm install && npm run buildcd ../ (o de regreso a donde quiera crear una aplicación de prueba)npx create-next-appcd your-next-appnpx link ../next-video (o donde sea que clonara este repositorio)