next-video Следующее видео представляет собой компонент React для добавления видео в ваше приложение Next.js. Он расширяет как элемент <video> , так и ваше следующее приложение с функциями для автоматической оптимизации видео.
import Video from 'next-video' ;
import getStarted from '/videos/get-started.mp4' ;
export default function Page ( ) {
return < Video src = { getStarted } /> ;
} В корне вашего проекта Next.js запустите:
npx -y next-video initЭто будет (с подсказкой):
next-video как зависимостьnext.config.js/videos в своем проекте, где вы будете размещать все файлы источника видео. Он также обновит ваш файл .gitignore , чтобы игнорировать видеофайлы в каталоге /videos . Видео, особенно любого из разумных размеров, не должны храниться/отслеживать GIT. В качестве альтернативы, если вы хотите сохранить исходные файлы, вы можете удалить добавленные линии Gitignore и установить GIT-LFS.
Vercel рекомендует использовать специальную платформу для видео для видео, потому что видеофайлы большие и могут привести к чрезмерному использованию полосы пропускания. По умолчанию, Next-Video использует MUX (видео API для разработчиков), который создан создателями Video.js, Powers Pospular Streaming Apps, таким как Patreon, и чей мониторинг производительности видео используется на крупнейших живых событиях в мире.
.env.local (или как вы экспортируете локальные переменные 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
Если вы используете модули 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
Если вы используете модули ES:
import { withNextVideo } from 'next-video/process' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; tsconfig.json Это требуется только в том случае, если вы используете TypeScript, и убедитесь, что ваш импорт видеофайла не кричит на вас для пропущенных типов. video.d.ts должен был быть создан в вашем проекте root, когда вы запустили npx next-video init , если нет, вы можете создать его вручную:
// video.d.ts
/// <reference types="next-video/video-types/global" /> Затем добавьте этот файл в include Array в tsconfig.json .
{
// ...
"include" : [ "video.d.ts" , "next-env.d.ts" , /* ... */ ]
// ...
} Добавьте видео локально в каталог /videos , затем запустите npx next-video sync . Видео будет автоматически загружено в удаленное хранилище и оптимизировано. Вы заметите /videos/[file-name].json t-файлы. Они используются для картирования ваших локальных видеофайлов с новыми, удаленными видео-активами. Эти файлы JSON должны быть проверены в GIT.
npx next-video sync
Вы также можете добавить next-video sync -w к сценарию DEV для автоматического синхронизации видео, поскольку они добавляются в /videos во время запуска Dev Server.
// package.json
"scripts" : {
"dev" : "next dev & npx next-video sync -w" ,
} , Теперь вы можете использовать компонент <Video> в вашем приложении. Допустим, вы добавили файл под названием awesome-video.mp4 в /videos
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
} В то время как видео загружается и обрабатывается, <Video> попытается воспроизводить локальный файл. Это происходит только во время локальной разработки, потому что локальный файл никогда не загружается в ваш git Repo.
Для видео, которые уже размещены удаленно (например, на AWS S3), импортируйте удаленный URL и обновите страницу. Это создает локальный файл JSON в папке /videos , и сценарий синхронизации начнет загружать видео.
import Video from 'next-video' ;
import awesomeVideo from 'https://www.mydomain.com/remote-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
}Если размещенное видео представляет собой единый файл, подобный MP4, файл будет автоматически оптимизирован для лучшей доставки и совместимости.
В некоторых случаях у вас может не быть удаленного видео URL, доступного во время импорта.
Это может быть решено путем создания новой конечной точки API в вашем приложении Next.js для /api/video со следующим кодом.
Маршрутизатор приложения (next.js> = 13)
// app/api/video/route.js
export { GET } from 'next-video/request-handler' ;Страницы маршрутизатор (next.js)
// pages/api/video/[[...handler]].js
export { default } from 'next-video/request-handler' ; Затем установите атрибут src на URL -адрес удаленного видео, обновите страницу, и видео начнет обработку.
import Video from 'next-video' ;
export default function Page ( ) {
return < Video src = "https://www.mydomain.com/remote-video.mp4" /> ;
} Вы можете изменить тему игрока, передавая theme опор в компонент <Video> .
Смотрите Player.style для большего количества тем.
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 } /> ;
} Поскольку v1.1.0 вы можете импортировать компонент игрока напрямую и использовать его без каких -либо функций загрузки и обработки.
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..."
/> ;
}Вы можете добавить пользовательский плакат и Blurdataurl в видео, передавая их в качестве реквизита.
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 }
/> ;
}Это хорошее решение, но оно не обеспечит такой же уровень оптимизации, что и автоматический постер и Blurdataurl поставщиком по умолчанию.
Чтобы получить тот же уровень оптимизации, вы можете использовать прорезированный элемент плаката.
Добавьте в видео элемент изображения плаката (например, next/image ), передав его в детстве с атрибутом slot="poster" .
Теперь ваше изображение получит все преимущества компонента подержанного изображения, и оно будет хорошо размещено за элементами управления видеоплеером.
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 >
) ;
} Вы можете настроить игрока, передавая пользовательский компонент игрока в as Prop.
Пользовательский компонент игрока принимает следующий реквизит:
asset : обработанный актив содержит полезные метаданные актива и статус загрузки.src : URL -адрес источника видео в строке, если актив готов.poster : URL -адрес источника изображения, если актив готов.blurDataURL : URL -адрес источника изображения Blurdataurl: string Base64, который можно использовать в качестве заполнителя. 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 }
/> ;
} Вы можете использовать компонент <BackgroundVideo> для добавления видео в качестве фона без элементов управления игроком. Это экономит около 50% размера игрока JS и оптимизировано для использования фонового видео.
Компонент <BackgroundVideo> - это пользовательский игрок, как вы видели в предыдущем разделе.
Параметр запроса thumbnailTime в приведенном ниже примере используется для генерации изображения плаката и размытия изображения в указанное время в видео (ограничено использованием с поставщиком 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 >
) ;
} Вы можете выбрать между разными поставщиками для обработки видео и хостинга. Поставщик по умолчанию - MUX. Чтобы изменить поставщика, вы можете добавить опцию provider в следующую конфигурацию. Некоторые поставщики требуют дополнительной конфигурации, которая может быть передана в свойство 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' }
}
} ) ;Поддерживаемые поставщики с их необходимыми переменными среды:
| Поставщик | Среда вар | Поставщик конфигурация | Ценовая ссылка |
|---|---|---|---|
mux (по умолчанию) | MUX_TOKEN_IDMUX_TOKEN_SECRET | Ценообразование | |
vercel-blob | BLOB_READ_WRITE_TOKEN | Ценообразование | |
backblaze | BACKBLAZE_ACCESS_KEY_IDBACKBLAZE_SECRET_ACCESS_KEY | endpointbucket (необязательно) | Ценообразование |
amazon-s3 | AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY | endpointbucket (необязательно) | Ценообразование |
cloudflare-r2 | R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_CF_API_TOKEN (необязательно, когда набор bucketUrlPublic ) | bucket (необязательно)bucketUrlPublic (необязательно, когда R2_CF_API_TOKEN set) | Ценообразование |
| MUX (по умолчанию) | Verce Blob | Бэкблоз | Amazon S3 | Cloudflare R2 | |
|---|---|---|---|---|---|
| Вне повторного хранилища | ✅ | ✅ | ✅ | ✅ | ✅ |
| Доставка через CDN | ✅ | ✅ | - | - | ✅ |
| BYO Player | ✅ | ✅ | ✅ | ✅ | ✅ |
| Сжат для потоковой передачи | ✅ | - | - | - | |
| Адаптироваться к медленным сетям (HLS) | ✅ | - | - | - | |
| Автоматический плакат заполнителей | ✅ | - | - | - | |
| Временная шкала парят миниатюры | ✅ | - | - | - | |
| Стройте любой формат источника | ✅ | * | * | * | * |
| Подписи и субтитры ИИ | ✅ | - | - | - | |
| Видео аналитика | ✅ | - | - | - | |
| Ценообразование | Протокол | ГБ на основе | ГБ на основе | ГБ на основе | ГБ на основе |
*Веб-совместимые файлы MP4, необходимые для хостинговых поставщиков без обработки видео
По умолчанию метаданные актива хранятся в файле JSON в каталоге /videos . Если вы хотите сохранить метаданные в базе данных или в другом месте, вы можете настроить крючки для хранения в отдельном файле конфигурации следующего видео.
В приведенном ниже примере конфигурации показаны крючки для хранения по умолчанию для хранилища файлов JSON.
Эти крючки могут быть настроены в соответствии с вашими потребностями, изменяя корпус функций loadAsset , saveAsset и 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 ) ) ;
}
} ) ; Затем импортируйте функцию withNextVideo в вашем файле next.config.mjs .
// next.config.mjs
import { withNextVideo } from './next-video.mjs' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; Наконец, импортируйте функции GET и POST или handler в ваших маршрутах API, как вы считаете нужным. Хандлеры ожидают url -запроса или параметра тела с URL -адресом видео источника.
Это самые минимальные примеры для обработчиков, как правило, вы добавляете больше обработки и проверки ошибок, аутентификации и авторизации.
Маршрутизатор приложения (next.js> = 13)
// app/api/video/route.js
export { GET , POST } from '@/next-video' ;Страницы маршрутизатор (next.js)
// pages/api/video/[[...handler]].js
export { handler as default } from '@/next-video' ; Игрок по умолчанию построен со СМИ Chrome.
<video> .<mux-video> .<hls-video> .<dash-video> . Компонент <Video> принимает все реквизиты элемента <video> и следующие дополнительные реквизиты:
src (Asset | String): объект Video Asset (импорт) или URL -адрес.poster (Staticimagedata | String): изображение заполнителя для видео. (Авто генерируется для видео MUX)blurDataURL (String): URL источника изображения BASE64, который можно использовать в качестве заполнителя. (Авто генерируется для видео MUX)theme (React Component): компонент темы игрока. Смотрите Player.style для большего количества тем.as (React Component): пользовательский компонент игрока. Смотрите пользовательский игрок.transform (функция): пользовательская функция для преобразования объекта актива (SRC и плаката).loader (Function): пользовательская функция, используемая для разрешения видео URL -адреса на основе строкости (не импорт). Компонент <Video> с источником видео MUX принимает следующие дополнительные реквизиты:
startTime (номер): время начала видео за секунды.streamType ("по требованию" | "Live"): тип потока видео. По умолчанию «по требованию».customDomain (String): назначает пользовательский домен, который будет использоваться для видео MUX.beaconCollectionDomain (String): назначает пользовательский домен, который будет использоваться для сбора данных MUX. Примечание. Должен быть установлен перед PlaybackID, чтобы применить к мониторингу данных MUX.envKey (String): Это ключ среды для данных MUX. Если вы используете Mux Video, это автоматически установлено для вас. Если вы используете другого поставщика, вы можете установить это на свой собственный ключ.disableTracking (Boolean): отключает отслеживание данных MUX воспроизведения видео.disableCookies (логическое): отключает файлы cookie, используемые данными MUX.preferPlayback ("mse" | "Native"): укажите, следует ли <mux-video> попытаться использовать расширение источника медиа или нативное воспроизведение (если таковые имеются). Если значение не предоставляется, <mux-video> выберет на основе того, что считается оптимальным для контента и среды воспроизведения.maxResolution ("720p" | "1080p" | "1440p" | "2160p"): укажите максимальное разрешение, которое вы хотите доставить для этого видео.minResolution ("480p" | "540p" | "720p" | "1080p" | "1440p" | "2160p"): Укажите минимальное разрешение, которое вы хотите доставить для этого видео.programStartTime (номер): примените мгновенные клипы на основе PDT к началу медиа-потока.programEndTime (номер): примените мгновенные клипы на основе PDT к концу медиа-потока.assetStartTime (номер): примените мгновенные клипы на основе сроков медиа-шкалы к началу медиа-потока.assetEndTime (номер): примените мгновенные клипы на основе сроков медиа-шкалы к концу медиа-потока.renditionOrder (String): Измените порядок, в котором представлены в списке воспроизведения SRC. Может повлиять на начальные нагрузки сегмента. В настоящее время поддерживает только «desc» для убывающего порядка.metadataVideoId (String): Это произвольный идентификатор, отправленный в данные MUX, который должен отобразить запись этого видео в вашей базе данных.metadataTitle (String): Это произвольное название для вашего видео, которое будет передано в виде метаданных в данные MUX. Добавление заголовка даст вам полезный контекст на вашей панели данных MUX Data. (необязательно, но поощряется)metadataViewerUserId (String): Если у вас есть пользователь, зарегистрированный, это должно быть анонимное значение идентификатора, которое отображается с пользователем в вашей базе данных, которое будет отправлено в данные MUX. Позаботьтесь о том, чтобы не разоблачить личную идентифицируемую информацию, такую как имена, имена пользователей или адреса электронной почты. (необязательно, но поощряется)metadata* (строка): этот синтаксис метаданных* можно использовать для прохождения любых произвольных полей метаданных данных MUX.playbackToken (String): токен воспроизведения для подписания URL src .thumbnailToken (String): токен для подписания URL -адреса poster .storyboardToken (String): токен для подписания URL -адреса раскадровки.drmToken (String): токен для подписания лицензии DRM и связанных с ними URL.targetLiveWindow (номер): смещение, представляющее диапазон, который можно найти для живого контента, где Infinity означает, что весь живой контент является поиском (он же «стандартный DVR»). Используется вместе с streamType , чтобы определить, какой пользовательский интерфейс/элемент управления показывать.liveEdgeOffset (номер): самое раннее время воспроизведения, которое будет рассматриваться как игра «на живом краю» для живого контента.debug (Boolean): разрешает режим отладки для базового двигателя воспроизведения (в настоящее время HLS.JS) и MUX-Embed, предоставляя дополнительную информацию в консоли. {
"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-* "
}
]
}Настройте ведро для публичного доступа:
bucket в конфигурации поставщика и убедитесь, что оно настроено для публичного доступаbucketUrlPublicПредоставьте ключ API CloudFlare:
R2_CF_API_TOKENЕсли вы хотите развиваться на этой штуке, вы можете клонировать и связать эту присоску. Просто знай ... сейчас не прекрасное время.
cd в репоnpm install && npm run buildcd ../ (или обратно, где вы хотите создать тестовое приложение)npx create-next-appcd your-next-appnpx link ../next-video (или везде, где вы клонировали это репо)