Skip to content

Commit

Permalink
Add documentation page on video optimization (#60574)
Browse files Browse the repository at this point in the history
I've added a new page to the Next.js docs about optimizing videos. It
covers:

- the native video and iframe tag
- displaying externally hosted videos (i.e. from youtube) 
- self hosting strategies and best practices 
- Video optimization techniques

---------

Co-authored-by: Lee Robinson <me@leerob.io>
Co-authored-by: Delba de Oliveira <32464864+delbaoliveira@users.noreply.github.com>
Co-authored-by: Josh Lubawy <jlubawy@gmail.com>
Co-authored-by: Balázs Orbán <info@balazsorban.com>
  • Loading branch information
5 people authored Jan 19, 2024
1 parent 3542280 commit 4a74492
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 0 deletions.
270 changes: 270 additions & 0 deletions docs/02-app/01-building-your-application/06-optimizing/02-videos.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
---
title: Video Optimization
nav_title: Videos
description: Recommendations and best practices for optimizing videos in your Next.js application.
---

# Optimizing videos in Next.js applications

This page outlines how to use videos with Next.js applications, showing how to store and display video files without affecting performance.

## Using `<video>` and `<iframe>`

Videos can be embedded on the page using the HTML **`<video>`** tag for direct video files and **`<iframe>`** for external platform-hosted videos.

### `<video>`

The HTML [`<video>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video) tag can embed self-hosted or directly served video content, allowing full control over the playback and appearance.

```jsx filename="app/ui/video.jsx"
export function Video() {
return (
<video width="320" height="240" controls preload="none">
<source src="/path/to/video.mp4" type="video/mp4" />
<track
src="/path/to/captions.vtt"
kind="subtitles"
srclang="en"
label="English"
/>
Your browser does not support the video tag.
</video>
)
}
```

### Common `<video>` tag attributes

| Attribute | Description | Example Value |
| ------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `src` | Specifies the source of the video file. | `<video src="/path/to/video.mp4"></video>` |
| `width` | Sets the width of the video player. | `<video width="320"></video>` |
| `height` | Sets the height of the video player. | `<video height="240"></video>` |
| `controls` | If present, it displays the default set of playback controls. | `<video controls></video>` |
| `autoplay` | Automatically starts playing the video when the page loads. Note: Autoplay policies vary across browsers. | `<video autoplay></video>` |
| `loop` | Loops the video playback. | `<video loop></video>` |
| `muted` | Mutes the audio by default. Often used with `autoplay`. | `<video muted></video>` |
| `preload` | Specifies how the video is preloaded. Values: `none`, `metadata`, `auto`. | `<video preload="none"></video>` |
| `playsInline` | Enables inline playback on iOS devices, often necessary for autoplay to work on iOS Safari. | `<video playsInline></video>` |

> **Good to know**: When using the `autoplay` attribute, it is important to also include the `muted` attribute to ensure the video plays automatically in most browsers, and the `playsInline` attribute for compatibility with iOS devices.
>
> ```
> <video autoplay muted playsInline></video>
> ```
For a comprehensive list of video attributes, refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/video#attributes).

### Video best practices

- **Fallback Content:** When using the `<video>` tag, include fallback content inside the tag for browsers that do not support video playback.
- **Subtitles or Captions:** Include subtitles or captions for users who are deaf or hard of hearing. Utilize the [`<track>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/track) tag with your `<video>` elements to specify caption file sources.
- **Accessible Controls:** Standard HTML5 video controls are recommended for keyboard navigation and screen reader compatibility. For advanced needs, consider third-party players like [react-player](https://github.com/cookpete/react-player) or [video.js](https://videojs.com/), which offer accessible controls and consistent browser experience.

### `<iframe>`

The HTML `<iframe>` tag allows you to embed videos from external platforms like YouTube or Vimeo.

```jsx filename="app/page.jsx"
export default function Page() {
return (
<iframe
src="https://www.youtube.com/watch?v=gfU1iZnjRZM"
frameborder="0"
allowfullscreen
/>
)
}
```

### Common `<iframe>` tag attributes

| Attribute | Description | Example Value |
| ----------------- | ---------------------------------------------------------------------- | --------------------------------------------- |
| `src` | The URL of the page to embed. | `<iframe src="https://example.com"></iframe>` |
| `width` | Sets the width of the iframe. | `<iframe width="500"></iframe>` |
| `height` | Sets the height of the iframe. | `<iframe height="300"></iframe>` |
| `frameborder` | Specifies whether or not to display a border around the iframe. | `<iframe frameborder="0"></iframe>` |
| `allowfullscreen` | Allows the iframe content to be displayed in full-screen mode. | `<iframe allowfullscreen></iframe>` |
| `sandbox` | Enables an extra set of restrictions on the content within the iframe. | `<iframe sandbox></iframe>` |
| `loading` | Optimize loading behavior (e.g., lazy loading). | `<iframe loading="lazy"></iframe>` |
| `title` | Provides a title for the iframe to support accessibility. | `<iframe title="Description"></iframe>` |

For a comprehensive list of iframe attributes, refer to the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attributes).

### Choosing a video embedding method

There are two ways you can embed videos in your Next.js application:

- **Self-hosted or direct video files:** Embed self-hosted videos using the `<video>` tag for scenarios requiring detailed control over the player's functionality and appearance. This integration method within Next.js allows for customization and control of your video content.
- **Using video hosting services (YouTube, Vimeo, etc.):** For video hosting services like YouTube or Vimeo, you'll embed their iframe-based players using the `<iframe>` tag. While this method limits some control over the player, it offers ease of use and features provided by these platforms.

Choose the embedding method that aligns with your application's requirements and the user experience you aim to deliver.

### Embedding externally hosted videos

To embed videos from external platforms, you can use Next.js to fetch the video information and React Suspense to handle the fallback state while loading.

1. **Create a Server Component for video embedding**

The first step is to create a [Server Component](https://nextjs.org/docs/app/building-your-application/rendering/server-components) that generates the appropriate iframe for embedding the video. This component will fetch the source URL for the video and render the iframe.

```jsx filename="app/ui/video-component.jsx"
export const async function VideoComponent (){
const src = await getVideoSrc()

return <iframe src={src} frameborder="0" allowfullscreen />
}
```

2. **Stream the video component using React Suspense**

After creating the Server Component to embed the video, the next step is to [stream](https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming) the component using [React Suspense](https://react.dev/reference/react/Suspense).

```jsx filename="app/page.jsx"
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'
export default function Page() {
return (
<section>
<Suspense fallback={<p>Loading video...</p>}>
<VideoComponent />
</Suspense>
{/* Other content of the page */}
</section>
)
}
```

> **Good to know**: When embedding videos from external platforms, consider the following best practices:
>
> - **Responsive embedding**: Ensure the video embeds are responsive. Use CSS to make the iframe or video player adapt to different screen sizes.
> - **Consider data usage**: Implement [strategies for loading videos](https://yoast.com/site-speed-tips-for-faster-video/) based on network conditions, especially for users with limited data plans.

This approach results in a better user experience as it prevents the page from blocking, meaning the user can interact with the page while the video component streams in. For a more engaging and informative loading experience, consider using a loading skeleton as the fallback UI. So instead of showing a simple loading message, you can show a skeleton that resembles the video player like this:

```jsx filename="app/page.jsx"
import { Suspense } from 'react'
import VideoComponent from '../ui/VideoComponent.jsx'
import VideoSkeleton from '../ui/VideoSkeleton.jsx'
export default function Page() {
return (
<section>
<Suspense fallback={<VideoSkeleton />}>
<VideoComponent />
</Suspense>
{/* Other content of the page */}
</section>
)
}
```

## Self-hosted videos

Self-hosting videos may be preferable for several reasons:

- **Complete control and independence**: Self-hosting gives you direct management over your video content, from playback to appearance, ensuring full ownership and control, free from external platform constraints.
- **Customization for specific needs**: Ideal for unique requirements, like dynamic background videos, it allows for tailored customization to align with design and functional needs.
- **Performance and scalability considerations**: Choose storage solutions that are both high-performing and scalable, to support increasing traffic and content size effectively.
- **Cost and integration**: Balance the costs of storage and bandwidth with the need for easy integration into your Next.js framework and broader tech ecosystem.

### Using Vercel Blob for video hosting

[Vercel Blob](https://vercel.com/docs/storage/vercel-blob) offers an efficient way to host videos, providing a scalable cloud storage solution that works well with Next.js. Here's how you can host a video using Vercel Blob:

**1. Uploading a video to Vercel Blob**

In your Vercel dashboard, navigate to the "Storage" tab and select your Vercel Blob database. In the Blob table's upper-right corner, find and click the "Upload" button. Then, choose the video file you wish to upload. After the upload completes, the video file will appear in the Blob table.
Alternatively, you can upload your video using a server action. For detailed instructions, refer to the Vercel documentation on [server-side uploads](https://vercel.com/docs/storage/vercel-blob/server-upload). Vercel also supports [client-side uploads](https://vercel.com/docs/storage/vercel-blob/client-upload). This method may be preferable for certain use cases.
> Good to know: Ensure to [add the necessary hostname](https://vercel.com/docs/storage/vercel-blob/server-upload) to your `next.config.js` to configure the domain from where the video files will be served.
**2. Displaying the video in Next.js**
Once the video is uploaded and stored, you can display it in your Next.js application. Here's an example of how to do this using the `<video>` tag and React Suspense:

```jsx filename="app/page.jsx"
import { Suspense } from 'react';
import { list } from '@vercel/blob';
export default function Page() {
return (
<Suspense fallback={<p>Loading video...</p>}>
<VideoComponent fileName="my-video.mp4" />
</Suspense>
);
};
async function VideoComponent({ fileName }) {
const {blobs} = await list({
prefix: fileName,
limit: 1
});
const { url } = blobs[0];
return (
<video controls preload="none" aria-label="Video player">
<source src={url} type="video/mp4">
Your browser does not support the video tag.
</video>
);
};
```

In this approach, the page uses the video’s `@vercel/blob` URL to display the video using the `VideoComponent`. React Suspense is used to show a fallback until the video URL is fetched and the video is ready to be displayed.

### Adding subtitles to your video

If you have subtitles for your video, you can easily add them using the `<track>` element inside your `<video>` tag. You can fetch the subtitle file from Vercel Blob in a similar way as the video file. Here's how you can update the `<VideoComponent>` to include subtitles.
```jsx filename="app/page.jsx"
async function VideoComponent({ fileName }) {
const {blobs} = await list({
prefix: fileName,
limit: 2
});
const { url } = blobs[0];
const { url: captionsUrl } = blobs[1];
return (
<video controls preload="none" aria-label="Video player">
<source src={url} type="video/mp4">
<track
src={captionsUrl}
kind="subtitles"
srclang="en"
label="English">
Your browser does not support the video tag.
</video>
);
};
```
By following this approach, you can effectively self-host and integrate videos into your Next.js applications.
## Resources
To continue learning more about video optimization and best practices, please refer to the following resources:
- **Understanding video formats and codecs**: Choose the right format and codec, like MP4 for compatibility or WebM for web optimization, for your video needs. For more details, see [Mozilla's guide on video codecs](https://developer.mozilla.org/en-US/docs/Web/Media/Formats/Video_codecs).
- **Video compression**: Use tools like FFmpeg to effectively compress videos, balancing quality with file size. Learn about compression techniques at [FFmpeg's official website](https://www.ffmpeg.org/).
- **Resolution and bitrate adjustment**: Adjust resolution and bitrate based on the viewing platform, with lower settings for mobile devices. For an in-depth understanding, read [DaCast’s guide](https://www.dacast.com/blog/bitrate-vs-resolution/#:~:text=The%20two%20measure%20different%20aspects,yield%20different%20qualities%20of%20video) on bitrate and resolution.
- **Content Delivery Networks (CDNs)**: Utilize a CDN to enhance video delivery speed and manage high traffic. When using some storage solutions, such as Vercel Blob, CDN functionality is automatically handled for you. [Learn more](https://www.maestro.io/blog/video-cdn/) about CDNs and their benefits.
Explore these video streaming platforms for integrating video into your Next.js projects:
- **Open source `next-video` component**
- Provides a `<Video>` component for Next.js, compatible with various hosting services including Vercel Blob, S3, Backblaze, and Mux.
- [Detailed documentation](https://next-video.dev/docs) for using `next-video.dev` with different hosting services.
- **Cloudinary Integration**
- Official [documentation and integration guides](https://support.cloudinary.com/hc/en-us/categories/200477762-Client-Libraries-and-Integration-Guides) for using Cloudinary with Next.js.
- A [specific guide](https://next.cloudinary.dev/nextjs-13) on integrating Cloudinary with Next.js.
- **Mux Video API**
- Mux provides a [starter template](https://github.com/muxinc/video-course-starter-kit) for creating a video course with Mux and Next.js.
- Learn about Mux's recommendations for embedding [high-performance video for your Next.js application](https://www.mux.com/for/nextjs).
- Explore an [example project](https://with-mux-video.vercel.app/) demonstrating Mux with Next.js.
- **Fastly**
- Learn more about integrating Fastly's solutions for [video on demand](https://www.fastly.com/products/streaming-media/video-on-demand) and streaming media into Next.js.

0 comments on commit 4a74492

Please sign in to comment.