next-video Video berikutnya adalah komponen React untuk menambahkan video ke aplikasi selanjutnya.js Anda. Ini memperpanjang elemen <video> dan aplikasi Anda berikutnya dengan fitur untuk optimasi video otomatis.
import Video from 'next-video' ;
import getStarted from '/videos/get-started.mp4' ;
export default function Page ( ) {
return < Video src = { getStarted } /> ;
} Dalam akar proyek Next.js Anda, jalankan:
npx -y next-video initIni akan (dengan dorongan):
next-video sebagai ketergantungannext.config.js Anda/videos di proyek Anda yang merupakan tempat Anda akan meletakkan semua file sumber video. Ini juga akan memperbarui file .gitignore Anda untuk mengabaikan file video di direktori /videos . Video, terutama ukuran yang masuk akal, tidak boleh disimpan/dilacak oleh Git. Atau, jika Anda ingin menyimpan file asli, Anda dapat menghapus garis Gitignore yang ditambahkan dan menginstal GIT-LFS.
Vercel merekomendasikan penggunaan platform konten khusus untuk video karena file video besar dan dapat menyebabkan penggunaan bandwidth yang berlebihan. Secara default, Next-Video menggunakan MUX (API video untuk pengembang), yang dibangun oleh para pencipta video.js, kekuatan aplikasi streaming populer seperti Patreon, dan yang pemantauan kinerja videonya digunakan pada acara langsung terbesar di dunia.
.env.local (atau bagaimanapun Anda mengekspor variabel env lokal) # .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
Jika Anda menggunakan modul 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
Jika Anda menggunakan modul ES:
import { withNextVideo } from 'next-video/process' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; tsconfig.json Ini hanya diperlukan jika Anda menggunakan TypeScript, dan memastikan impor file video Anda tidak meneriaki Anda untuk tipe yang hilang. video.d.ts seharusnya dibuat di root proyek Anda saat Anda menjalankan npx next-video init , jika tidak Anda dapat membuatnya secara manual:
// video.d.ts
/// <reference types="next-video/video-types/global" /> Kemudian tambahkan file itu ke array include di tsconfig.json .
{
// ...
"include" : [ "video.d.ts" , "next-env.d.ts" , /* ... */ ]
// ...
} Tambahkan video secara lokal ke direktori /videos kemudian jalankan npx next-video sync . Video akan diunggah secara otomatis ke penyimpanan jarak jauh dan dioptimalkan. Anda akan melihat file /videos/[file-name].json media.json juga dibuat. Ini digunakan untuk memetakan file video lokal Anda ke aset video baru yang di-hosting. File JSON ini harus diperiksa ke dalam git.
npx next-video sync
Anda juga dapat menambahkan next-video sync -w ke skrip DEV untuk secara otomatis menyinkronkan video karena mereka ditambahkan ke /videos saat server dev sedang berjalan.
// package.json
"scripts" : {
"dev" : "next dev & npx next-video sync -w" ,
} , Sekarang Anda dapat menggunakan komponen <Video> di aplikasi Anda. Katakanlah Anda telah menambahkan file yang disebut awesome-video.mp4 ke /videos
import Video from 'next-video' ;
import awesomeVideo from '/videos/awesome-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
} Saat video sedang diunggah dan diproses, <Video> akan mencoba memutar file lokal. Ini hanya terjadi selama pengembangan lokal karena file lokal tidak pernah diunggah ke repo git Anda.
Untuk video yang sudah di -host dari jarak jauh (misalnya pada AWS S3), impor URL jarak jauh dan segarkan halaman. Ini membuat file JSON lokal di folder /videos dan skrip sinkronisasi akan mulai mengunggah video.
import Video from 'next-video' ;
import awesomeVideo from 'https://www.mydomain.com/remote-video.mp4' ;
export default function Page ( ) {
return < Video src = { awesomeVideo } /> ;
}Jika video yang di -host adalah file tunggal seperti MP4, file akan secara otomatis dioptimalkan untuk pengiriman dan kompatibilitas yang lebih baik.
Dalam beberapa kasus Anda mungkin tidak memiliki URL video jarak jauh yang tersedia pada saat impor.
Itu dapat diselesaikan dengan membuat titik akhir API baru di aplikasi Next.js Anda untuk /api/video dengan kode berikut.
Aplikasi Router (Next.js> = 13)
// app/api/video/route.js
export { GET } from 'next-video/request-handler' ;Router halaman (next.js)
// pages/api/video/[[...handler]].js
export { default } from 'next-video/request-handler' ; Kemudian atur atribut src ke URL video jarak jauh, segarkan halaman dan video akan mulai diproses.
import Video from 'next-video' ;
export default function Page ( ) {
return < Video src = "https://www.mydomain.com/remote-video.mp4" /> ;
} Anda dapat mengubah tema pemain dengan meneruskan prop theme ke komponen <Video> .
Lihat Player.Style untuk lebih banyak tema.
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 } /> ;
} Karena v1.1.0 Anda dapat mengimpor komponen pemain secara langsung dan menggunakannya tanpa fitur unggahan dan pemrosesan.
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..."
/> ;
}Anda dapat menambahkan poster khusus dan blurdataurl ke video dengan meneruskannya sebagai alat peraga.
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 }
/> ;
}Ini adalah solusi yang baik tetapi tidak akan memberikan tingkat optimisasi yang sama dengan poster otomatis dan blurdataurl oleh penyedia default.
Untuk mendapatkan tingkat optimasi yang sama, Anda dapat menggunakan elemen poster berlapis.
Tambahkan elemen gambar poster slotted (seperti next/image ) ke video dengan meneruskannya sebagai seorang anak dengan atribut slot="poster" .
Sekarang gambar Anda akan mendapatkan semua manfaat dari komponen gambar yang digunakan dan akan ditempatkan dengan baik di belakang kontrol pemutar 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 >
) ;
} Anda dapat menyesuaikan pemain dengan meneruskan komponen pemain kustom ke as prop.
Komponen Pemain Kustom menerima alat peraga berikut:
asset : Aset yang diproses, berisi metadata aset yang bermanfaat dan status unggah.src : URL sumber video string jika aset sudah siap.poster : URL Sumber Gambar String Jika aset siap.blurDataURL : URL sumber gambar string base64 yang dapat digunakan sebagai placeholder. 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 }
/> ;
} Anda dapat menggunakan komponen <BackgroundVideo> untuk menambahkan video sebagai latar belakang tanpa kontrol pemain. Ini menghemat sekitar 50% dari ukuran pemain JS dan dioptimalkan untuk penggunaan video latar belakang.
Komponen <BackgroundVideo> adalah pemain kustom seperti yang Anda lihat di bagian sebelumnya.
Parameter kueri thumbnailTime dalam contoh di bawah ini digunakan untuk menghasilkan gambar poster dan mengacaukan gambar pada waktu yang ditentukan dalam video (terbatas untuk penggunaan dengan penyedia 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 >
) ;
} Anda dapat memilih antara penyedia yang berbeda untuk pemrosesan dan hosting video. Penyedia default adalah Mux. Untuk mengubah penyedia, Anda dapat menambahkan opsi provider di konfigurasi Video Berikutnya. Beberapa penyedia memerlukan konfigurasi tambahan yang dapat diteruskan di properti 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' }
}
} ) ;Penyedia yang didukung dengan variabel lingkungan yang diperlukan:
| Penyedia | Lingkungan Vars | Konfigurasi Penyedia | Tautan harga |
|---|---|---|---|
mux (default) | MUX_TOKEN_IDMUX_TOKEN_SECRET | Harga | |
vercel-blob | BLOB_READ_WRITE_TOKEN | Harga | |
backblaze | BACKBLAZE_ACCESS_KEY_IDBACKBLAZE_SECRET_ACCESS_KEY | endpointbucket (opsional) | Harga |
amazon-s3 | AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY | endpointbucket (opsional) | Harga |
cloudflare-r2 | R2_ACCESS_KEY_IDR2_SECRET_ACCESS_KEYR2_CF_API_TOKEN (opsional saat set bucketUrlPublic ) | bucket (opsional)bucketUrlPublic (opsional saat R2_CF_API_TOKEN set) | Harga |
| Mux (default) | Vercel Blob | Backblaze | Amazon S3 | Cloudflare R2 | |
|---|---|---|---|---|---|
| Penyimpanan Off-Repo | ✅ | ✅ | ✅ | ✅ | ✅ |
| Pengiriman melalui CDN | ✅ | ✅ | - | - | ✅ |
| Pemain BYO | ✅ | ✅ | ✅ | ✅ | ✅ |
| Dikompresi untuk streaming | ✅ | - | - | - | |
| Beradaptasi dengan jaringan lambat (HLS) | ✅ | - | - | - | |
| Poster Placeholder Otomatis | ✅ | - | - | - | |
| Timeline mengarahkan thumbnail | ✅ | - | - | - | |
| Streaming format sumber apa pun | ✅ | * | * | * | * |
| AI Captions & Subtitle | ✅ | - | - | - | |
| Analisis video | ✅ | - | - | - | |
| Harga | Berbasis menit | Berbasis GB | Berbasis GB | Berbasis GB | Berbasis GB |
*File MP4 yang kompatibel dengan web diperlukan untuk penyedia hosting tanpa pemrosesan video
Secara default metadata aset disimpan dalam file JSON di direktori /videos . Jika Anda ingin menyimpan metadata dalam database atau di tempat lain, Anda dapat menyesuaikan kait penyimpanan dalam file konfigurasi Video Next-Video yang terpisah.
Contoh konfigurasi di bawah ini menunjukkan kait penyimpanan default untuk penyimpanan file JSON.
Kait ini dapat disesuaikan agar sesuai dengan kebutuhan Anda dengan mengubah tubuh loadAsset , saveAsset , dan 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 ) ) ;
}
} ) ; Kemudian impor fungsi withNextVideo di file next.config.mjs Anda.
// next.config.mjs
import { withNextVideo } from './next-video.mjs' ;
/** @type {import('next').NextConfig} */
const nextConfig = { } ;
export default withNextVideo ( nextConfig ) ; Terakhir mengimpor fungsi GET and POST , atau handler di rute API Anda sesuai keinginan Anda. Penangan mengharapkan kueri url atau parameter tubuh dengan URL sumber video.
Ini adalah contoh paling minim untuk penangan, biasanya Anda akan menambahkan lebih banyak penanganan kesalahan dan validasi, otentikasi dan otorisasi.
Aplikasi Router (Next.js> = 13)
// app/api/video/route.js
export { GET , POST } from '@/next-video' ;Router halaman (next.js)
// pages/api/video/[[...handler]].js
export { handler as default } from '@/next-video' ; Pemain default dibangun dengan media Chrome.
<video> asli.<mux-video> .<hls-video> .<dash-video> . Komponen <Video> menerima semua alat peraga dari elemen <video> dan alat peraga tambahan berikut:
src (Aset | String): Objek aset video (impor) atau URL sumber.poster (StaticImagedata | String): Gambar placeholder untuk video. (Auto yang dihasilkan untuk video MUX)blurDataURL (String): URL sumber gambar base64 yang dapat digunakan sebagai penampung. (Auto yang dihasilkan untuk video MUX)theme (Komponen Bereaksi): Komponen tema pemain. Lihat Player.Style untuk lebih banyak tema.as (reaksi komponen): komponen pemain kustom. Lihat Pemain Kustom.transform (fungsi): Fungsi khusus untuk mengubah objek aset (SRC dan poster).loader (fungsi): Fungsi khusus yang digunakan untuk menyelesaikan URL video berbasis string (bukan impor). Komponen <Video> dengan sumber video MUX menerima alat peraga tambahan berikut:
startTime (Nomor): Waktu mulai video dalam hitungan detik.streamType ("On-Demand" | "Live"): Jenis aliran video. Default adalah "on-demand".customDomain (String): Menetapkan domain khusus untuk digunakan untuk video MUX.beaconCollectionDomain (String): Menetapkan domain khusus untuk digunakan untuk pengumpulan data MUX. Catatan: Harus diatur sebelum PlaybackID untuk diterapkan pada pemantauan data MUX.envKey (String): Ini adalah kunci lingkungan untuk data MUX. Jika Anda menggunakan video mux, ini secara otomatis diatur untuk Anda. Jika Anda menggunakan penyedia yang berbeda, Anda dapat mengatur ini ke kunci Anda sendiri.disableTracking (Boolean): Menonaktifkan pelacakan data MUX dari pemutaran video.disableCookies (Boolean): Menonaktifkan cookie yang digunakan oleh data MUX.preferPlayback ("MSE" | "Native"): Tentukan jika <mux-video> harus mencoba menggunakan ekstensi sumber media atau pemutaran asli (jika tersedia). Jika tidak ada nilai yang disediakan, <mux-video> akan memilih berdasarkan apa yang dianggap optimal untuk lingkungan konten dan pemutaran.maxResolution ("720p" | "1080p" | "1440p" | "2160p"): Tentukan resolusi maksimum yang ingin Anda kirim untuk video ini.minResolution ("480p" | "540p" | "720p" | "1080p" | "1440p" | "2160p"): Tentukan resolusi minimum yang ingin Anda kirim untuk video ini.programStartTime (Nomor): Terapkan klip instan berbasis PDT ke awal aliran media.programEndTime (Nomor): Terapkan klip instan berbasis PDT ke akhir aliran media.assetStartTime (NUMBER): Menerapkan klip instan berbasis waktu media ke awal aliran media.assetEndTime (NUMBER): Menerapkan klip instan berbasis timeline ke akhir aliran media.renditionOrder (String): Ubah urutan rendisi disediakan di daftar putar SRC. Dapat memengaruhi beban segmen awal. Saat ini hanya mendukung "desc" untuk pesanan menurun.metadataVideoId (String): Ini adalah ID sewenang -wenang yang dikirim ke data MUX yang harus dipetakan kembali ke catatan video ini di database Anda.metadataTitle (String): Ini adalah judul sewenang -wenang untuk video Anda yang akan diteruskan sebagai metadata ke dalam data MUX. Menambahkan judul akan memberi Anda konteks yang berguna di dasbor data MUX Anda. (opsional, tetapi didorong)metadataViewerUserId (String): Jika Anda memiliki pengguna yang masuk, ini harus berupa nilai ID anonim yang memetakan kembali ke pengguna dalam database Anda yang akan dikirim ke data MUX. Berhati -hatilah untuk tidak mengekspos informasi yang dapat diidentifikasi pribadi seperti nama, nama pengguna atau alamat email. (opsional, tetapi didorong)metadata* (String): Sintaks metadata* ini dapat digunakan untuk melewati bidang metadata data MUX sewenang -wenang.playbackToken (String): Token pemutaran untuk menandatangani URL src .thumbnailToken (String): Token untuk menandatangani URL poster .storyboardToken (String): Token untuk menandatangani URL Storyboard.drmToken (String): Token untuk menandatangani lisensi DRM dan URL terkait.targetLiveWindow (NUMBER): Offset yang mewakili rentang yang dapat dicari untuk konten langsung, di mana Infinity berarti seluruh konten langsung dicari (alias "DVR standar"). Digunakan bersama dengan streamType untuk menentukan UI/kontrol apa yang akan ditampilkan.liveEdgeOffset (Nomor): Waktu pemutaran paling awal yang akan diperlakukan sebagai bermain "di The Live Edge" untuk konten langsung.debug (BOOLEAN): Memungkinkan mode debug untuk mesin pemutaran yang mendasarinya (saat ini HLS.JS) dan Embed MUX, memberikan informasi tambahan di konsol. {
"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-* "
}
]
}Konfigurasikan ember untuk akses publik:
bucket di konfigurasi penyedia dan pastikan dikonfigurasi untuk akses publikbucketUrlPublicBerikan kunci API CloudFlare:
R2_CF_API_TOKENJika Anda ingin mengembangkan hal ini secara lokal, Anda dapat mengkloning dan menautkan pengisap ini. Ketahuilah ... ini bukan waktu yang tepat sekarang.
cd ke reponpm install && npm run buildcd ../ (atau kembali ke mana pun Anda ingin membuat aplikasi uji)npx create-next-appcd your-next-appnpx link ../next-video (atau di mana pun Anda mengkloning repo ini)