Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/muxinc/next-video

The easiest way to add video in your Nextjs app.
https://github.com/muxinc/next-video

hacktoberfest next nextjs react react-video video video-player video-processing video-streaming

Last synced: about 1 month ago
JSON representation

The easiest way to add video in your Nextjs app.

Awesome Lists containing this project

README

        

# `next-video`

[![npm version](https://img.shields.io/npm/v/next-video?style=flat-square&color=informational)](http://npmjs.org/next-video)
[![NPM Downloads](https://img.shields.io/npm/dm/next-video?style=flat-square&color=informational&label=npm)](https://www.npmjs.com/package/next-video)
[![size](https://img.shields.io/bundlephobia/minzip/next-video?label=size&style=flat-square)](https://bundlephobia.com/result?p=next-video)

Next video is a react component for adding video to your [next.js](https://github.com/vercel/next.js) application. It extends both the `` element and your Next app with features for automatic video optimization.

- **Smart storage:** Store large video files outside of your git repo
- **Auto optimized**: Optimize video files and deliver via CDN for better playback performance and quality
- **Customizable UI:** Choose from themes or build your own player controls
- **Posters & Previews:** Zero-config placeholder images and timeline hover thumbnails
- **Wider compatibility:** Use videos that aren’t supported natively by all browsers
- **Analytics built-in (optional):** See how often videos get watched and track video performance
- **AI-powered:** Add [auto-generated captions](https://docs.mux.com/guides/add-autogenerated-captions-and-use-transcripts?utm_source=next-video.dev) to your videos and use transcripts

```tsx
import Video from 'next-video';
import getStarted from '/videos/get-started.mp4';

export default function Page() {
return ;
}
```

## Setup

### Automatic Setup

In the root of your Next.js project, run:

```bash
npx -y next-video init
```

This will (with prompting):

- install `next-video` as a dependency
- update your `next.config.js` file
- if you're using TypeScript, add types for your video file imports
- create a `/videos` directory in your project which is where you will put all video source files.

It will also update your `.gitignore` file to ignore video files in the `/videos` directory. Videos, particularly any of reasonable size, shouldn't be stored/tracked by git. Alternatively, if you'd like to store the original files you can remove the added gitignore lines and install [git-lfs](https://git-lfs.github.com/).

### Remote storage and optimization

Vercel [recommends](https://vercel.com/guides/best-practices-for-hosting-videos-on-vercel-nextjs-mp4-gif) using a dedicated content platform for video because video files are large and can lead to excessive bandwidth usage. By default, next-video uses [Mux](https://mux.com?utm_source=next-video.dev), which is built by the the creators of Video.js, powers popular streaming apps like Patreon, and whose video performance monitoring is used on the largest live events in the world.

- [Sign up for Mux](https://dashboard.mux.com/signup?utm_source=next-video.dev)
- [Create an access token](https://dashboard.mux.com/settings/access-tokens#create)
- Add environment variables to `.env.local` (or however you export local env variables)

```bash
# .env.local
MUX_TOKEN_ID=[YOUR_TOKEN_ID]
MUX_TOKEN_SECRET=[YOUR_TOKEN_SECRET]
```

### Manual Setup

Click to see the manual init steps.

#### Install the package

```bash
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
```

#### Add Next Video to `next.config.js`

```js
/** @type {import('next').NextConfig} */
const { withNextVideo } = require('next-video/process');

const nextConfig = {}; // Your current Next Config object

module.exports = withNextVideo(nextConfig);
```

#### Add video import types to `tsconfig.json`

This is only required if you're using TypeScript, and makes sure your video file imports don't yell at you for missing types. `video.d.ts` should have been created in your project root when you ran `npx next-video init`, if not you can create it manually:

```ts
// video.d.ts
///
```

Then add that file to the `include` array in `tsconfig.json`.

```js
{
// ...
"include": ["video.d.ts", "next-env.d.ts", /* ... */ ]
// ...
}
```

## Usage

### Local videos ([Demo](https://next-video-demo.vercel.app/))

Add videos locally to the `/videos` directory then run `npx next-video sync`. The videos will be automatically uploaded to remote storage and optimized. You'll notice `/videos/[file-name].json` files are also created. These are used to map your local video files to the new, remote-hosted video assets. These json files must be checked into git.

```
npx next-video sync
```

You can also add `next-video sync -w` to the dev script to automatically sync videos as they're added to `/videos` while the dev server is running.

```js
// package.json
"scripts": {
"dev": "next dev & npx next-video sync -w",
},
```

Now you can use the `` component in your application. Let's say you've added a file called `awesome-video.mp4` to `/videos`

```tsx
import Video from 'next-video';
import awesomeVideo from '/videos/awesome-video.mp4';

export default function Page() {
return ;
}
```

While a video is being uploaded and processed, `` will attempt to play the local file. This only happens during local development because the local file is never uploaded to your git repo.

### Remote videos

For videos that are already hosted remotely (for example on AWS S3), import the remote URL and refresh the page.
This creates a local JSON file in the `/videos` folder and the sync script will start uploading the video.

```tsx
import Video from 'next-video';
import awesomeVideo from 'https://www.mydomain.com/remote-video.mp4';

export default function Page() {
return ;
}
```

If the hosted video is a single file like an MP4, the file will be automatically optimized for better deliverability and compatibility.

Remote videos with string source URL

In some cases you might not have the remote video URL's available at the time of import.

That can be solved by creating a new API endpoint in your Next.js app for `/api/video` with the following code.

**App router (Next.js >=13)**

```js
// app/api/video/route.js
export { GET } from 'next-video/request-handler';
```

**Pages router (Next.js)**

```js
// pages/api/video/[[...handler]].js
export { default } from 'next-video/request-handler';
```

Then set the `src` attribute to the URL of the remote video, refresh the page and the video will start processing.

```tsx
import Video from 'next-video';

export default function Page() {
return ;
}
```

### Player only ([Demo](https://next-video-demo.vercel.app/player-only))

Since [`v1.1.0`](https://github.com/muxinc/next-video/releases/tag/v1.1.0) you can import the player component directly and use it without any upload and processing features.

```tsx
import Player from 'next-video/player';
// or
import BackgroundPlayer from 'next-video/background-player';

export default function Page() {
return ;
}
```

### Custom poster and blurDataURL

You can add a custom poster and blurDataURL to the video by passing them as props.

```tsx
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 ;
}
```

This is a good solution but it will not provide the same level of optimization
as the automatic poster and blurDataURL by the default provider.

To get the same level of optimization you can use a slotted poster element.

### Slotted poster image element ([Demo](https://next-video-demo.vercel.app/slotted-poster))

Add a slotted poster image element
(like [`next/image`](https://nextjs.org/docs/app/api-reference/components/image))
to the video by passing it as a child with a `slot="poster"` attribute.

Now your image will get all the benefits of the used image component
and it will be nicely placed behind the video player controls.

```tsx
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 (



);
}
```

### Custom Player ([Demo](https://next-video-demo.vercel.app/custom-player))

You can customize the player by passing a custom player component to the `as` prop.
The custom player component accepts the following props:

- `asset`: The asset that is processed, contains useful asset metadata and upload status.
- `src`: A string video source URL if the asset is ready.
- `poster`: A string image source URL if the asset is ready.
- `blurDataURL`: A string base64 image source URL that can be used as a placeholder.

```tsx
import Video from 'next-video';
import ReactPlayer from './player';
import awesomeVideo from '/videos/awesome-video.mp4';

export default function Page() {
return ;
}
```

```tsx
// 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 ;
}
```

### Background Video ([Demo](https://next-video-demo.vercel.app/background-video))

You can use a `` component to add a video as a background with
no player controls. This saves about 50% of the JS player size and is optimized
for background video usage.

The `` component is a custom player like you saw in the previous section.

The `thumbnailTime` query parameter in the example below is used to generate
a poster image and blur up image at the specified time in the video
(limited to usage with the `mux` provider).

```tsx
import BackgroundVideo from 'next-video/background-video';
import getStarted from '/videos/country-clouds.mp4?thumbnailTime=0';

export default function Page() {
return (

next-video



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.



);
}
```

### Hosting & Processing Providers

You can choose between different providers for video processing and hosting.
The default provider is [Mux](https://mux.com?utm_source=next-video.dev).
To change the provider you can add a `provider` option in the next-video config.
Some providers require additional configuration which can be passed in the `providerConfig` property.

```js
// 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' }
}
});
```

Supported providers with their required environment variables:

| Provider | Environment vars | Provider config | Pricing link |
| ------------------------------------------------------------ | ----------------------------------------------------------- | ---------------------------------- | ------------------------------------------------------------------------ |
| [`mux`](https://mux.com?utm_source=next-video.dev) (default) | `MUX_TOKEN_ID`
`MUX_TOKEN_SECRET` | | [Pricing](https://www.mux.com/pricing/video?utm_source=next-video.dev) |
| [`vercel-blob`](https://vercel.com/docs/storage/vercel-blob) | `BLOB_READ_WRITE_TOKEN` | | [Pricing](https://vercel.com/docs/storage/vercel-blob/usage-and-pricing) |
| [`backblaze`](https://www.backblaze.com/cloud-storage) | `BACKBLAZE_ACCESS_KEY_ID`
`BACKBLAZE_SECRET_ACCESS_KEY` | `endpoint`
`bucket` (optional) | [Pricing](https://www.backblaze.com/cloud-storage/pricing) |
| [`amazon-s3`](https://aws.amazon.com/s3) | `AWS_ACCESS_KEY_ID`
`AWS_SECRET_ACCESS_KEY` | `endpoint`
`bucket` (optional) | [Pricing](https://aws.amazon.com/s3/pricing/) |

#### Provider feature set

| | Mux (default) | Vercel Blob | Backblaze | Amazon S3 |
| ---------------------------- | ------------- | ----------- | --------- | --------- |
| Off-repo storage | ✅ | ✅ | ✅ | ✅ |
| Delivery via CDN | ✅ | ✅ | - | - |
| BYO player | ✅ | ✅ | ✅ | ✅ |
| Compressed for streaming | ✅ | - | - | - |
| Adapt to slow networks (HLS) | ✅ | - | - | - |
| Automatic placeholder poster | ✅ | - | - | - |
| Timeline hover thumbnails | ✅ | - | - | - |
| Stream any source format | ✅ | * | * | * |
| AI captions & subtitles | ✅ | - | - | - |
| Video analytics | ✅ | - | - | - |
| Pricing | Minutes-based | GB-based | GB-based | GB-based |

*Web-compatible MP4 files required for hosting providers without video processing

## Required Permissions for Amazon S3

If you're using Amazon S3 as the provider, you'll need to create a new IAM user with the following permissions:

```json
{
"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-*"
}
]
}
```

## Roadmap

### v0

- [x] Automatic video optimization
- [x] Delivery via a CDN
- [x] Automatically upload and process local source files
- [x] Automatically process remote hosted source files

### v1

- [x] Customizable player
- [x] Connectors for additional video services
- [x] AI captions

## Trying it out locally

If you want to develop on this thing locally, you can clone and link this sucker. Just know...it's not a great time right now.

1. Clone this repo
1. `cd` into the repo
1. `npm install && npm run build`
1. `cd ../` (or back to wherever you want to create a test app)
1. `npx create-next-app`
1. `cd your-next-app`
1. `npx link ../next-video` (or wherever you cloned this repo)