{"id":13459769,"url":"https://github.com/muxinc/next-video","last_synced_at":"2025-04-10T20:53:30.930Z","repository":{"id":188589978,"uuid":"670732586","full_name":"muxinc/next-video","owner":"muxinc","description":"The easiest way to add video in your Nextjs app.","archived":false,"fork":false,"pushed_at":"2025-04-10T13:35:17.000Z","size":34568,"stargazers_count":996,"open_issues_count":15,"forks_count":43,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-04-10T14:53:30.953Z","etag":null,"topics":["hacktoberfest","next","nextjs","react","react-video","video","video-player","video-processing","video-streaming"],"latest_commit_sha":null,"homepage":"https://next-video.dev","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/muxinc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-25T17:53:12.000Z","updated_at":"2025-04-10T13:35:21.000Z","dependencies_parsed_at":"2023-10-17T01:42:05.176Z","dependency_job_id":"62d2dd7c-2042-4508-8572-92ab61eaa729","html_url":"https://github.com/muxinc/next-video","commit_stats":{"total_commits":264,"total_committers":12,"mean_commits":22.0,"dds":0.6060606060606061,"last_synced_commit":"4bd2678d79c6a5e51e1c98e40a18b6d83d2e7811"},"previous_names":["muxinc/next-video"],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muxinc%2Fnext-video","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muxinc%2Fnext-video/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muxinc%2Fnext-video/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/muxinc%2Fnext-video/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/muxinc","download_url":"https://codeload.github.com/muxinc/next-video/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248243206,"owners_count":21071054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","next","nextjs","react","react-video","video","video-player","video-processing","video-streaming"],"created_at":"2024-07-31T10:00:28.700Z","updated_at":"2025-04-10T20:53:30.917Z","avatar_url":"https://github.com/muxinc.png","language":"TypeScript","funding_links":[],"categories":["Tools","TypeScript"],"sub_categories":[],"readme":"# `next-video`\n\n[![npm version](https://img.shields.io/npm/v/next-video?style=flat-square\u0026color=informational)](http://npmjs.org/next-video)\n[![NPM Downloads](https://img.shields.io/npm/dm/next-video?style=flat-square\u0026color=informational\u0026label=npm)](https://www.npmjs.com/package/next-video)\n[![size](https://img.shields.io/bundlephobia/minzip/next-video?label=size\u0026style=flat-square)](https://bundlephobia.com/result?p=next-video)\n\nNext video is a react component for adding video to your [next.js](https://github.com/vercel/next.js) application. It extends both the `\u003cvideo\u003e` element and your Next app with features for automatic video optimization.\n\n- **Smart storage:** Store large video files outside of your git repo\n- **Auto optimized**: Optimize video files and deliver via CDN for better playback performance and quality\n- **Customizable UI:** Choose from themes or build your own player controls\n- **Posters \u0026 Previews:** Zero-config placeholder images and timeline hover thumbnails\n- **Wider compatibility:** Use videos that aren’t supported natively by all browsers\n- **Analytics built-in (optional):** See how often videos get watched and track video performance\n- **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\n\n```tsx\nimport Video from 'next-video';\nimport getStarted from '/videos/get-started.mp4';\n\nexport default function Page() {\n  return \u003cVideo src={getStarted} /\u003e;\n}\n```\n\n## Setup\n\n### Automatic Setup\n\nIn the root of your Next.js project, run:\n\n```bash\nnpx -y next-video init\n```\n\nThis will (with prompting):\n\n- install `next-video` as a dependency\n- update your `next.config.js` file\n- if you're using TypeScript, add types for your video file imports\n- create a `/videos` directory in your project which is where you will put all video source files.\n\nIt 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/).\n\n### Remote storage and optimization\n\nVercel [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) (a [video API](https://www.mux.com/video-api) for developers), 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.\n\n- [Sign up for Mux](https://dashboard.mux.com/signup?utm_source=next-video.dev)\n- [Create an access token](https://dashboard.mux.com/settings/access-tokens#create)\n- Add environment variables to `.env.local` (or however you export local env variables)\n\n```bash\n# .env.local\nMUX_TOKEN_ID=[YOUR_TOKEN_ID]\nMUX_TOKEN_SECRET=[YOUR_TOKEN_SECRET]\n```\n\n### Manual Setup\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eClick to see the manual init steps.\u003c/strong\u003e\u003c/summary\u003e\n\n#### Install the package\n\n```bash\ncd your-next-app\n\n# If your project is using NPM (the default for Next.js)\nnpm install next-video\n\n# If your project is using Yarn\nyarn add next-video\n\n# If your project is using pnpm\npnpm add next-video\n```\n\n#### Add Next Video to your Next.js config\n\n**`next.config.js`**\n\nIf you're using CommonJS modules:\n\n```js\nconst { withNextVideo } = require('next-video/process');\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {}; // Your current Next Config object\n\nmodule.exports = withNextVideo(nextConfig);\n```\n\n**`next.config.mjs`**\n\nIf you're using ES modules:\n\n```js\nimport { withNextVideo } from 'next-video/process';\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withNextVideo(nextConfig);\n```\n\n#### Add video import types to `tsconfig.json`\n\nThis 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:\n\n```ts\n// video.d.ts\n/// \u003creference types=\"next-video/video-types/global\" /\u003e\n```\n\nThen add that file to the `include` array in `tsconfig.json`.\n\n```js\n{\n  // ...\n  \"include\": [\"video.d.ts\", \"next-env.d.ts\", /* ... */ ]\n  // ...\n}\n```\n\n\u003c/details\u003e\n\n## Usage\n\n### Local videos ([Demo](https://next-video-demo.vercel.app/))\n\nAdd 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.\n\n```\nnpx next-video sync\n```\n\nYou 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.\n\n```js\n// package.json\n\"scripts\": {\n  \"dev\": \"next dev \u0026 npx next-video sync -w\",\n},\n```\n\nNow you can use the `\u003cVideo\u003e` component in your application. Let's say you've added a file called `awesome-video.mp4` to `/videos`\n\n```tsx\nimport Video from 'next-video';\nimport awesomeVideo from '/videos/awesome-video.mp4';\n\nexport default function Page() {\n  return \u003cVideo src={awesomeVideo} /\u003e;\n}\n```\n\nWhile a video is being uploaded and processed, `\u003cVideo\u003e` will attempt to play the local file. This only happens during local development because the local file is never uploaded to your git repo.\n\n### Remote videos\n\nFor videos that are already hosted remotely (for example on AWS S3), import the remote URL and refresh the page.\nThis creates a local JSON file in the `/videos` folder and the sync script will start uploading the video.\n\n```tsx\nimport Video from 'next-video';\nimport awesomeVideo from 'https://www.mydomain.com/remote-video.mp4';\n\nexport default function Page() {\n  return \u003cVideo src={awesomeVideo} /\u003e;\n}\n```\n\nIf the hosted video is a single file like an MP4, the file will be automatically optimized for better deliverability and compatibility.\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003eRemote videos with string source URL\u003c/strong\u003e\u003c/summary\u003e\n\nIn some cases you might not have the remote video URL's available at the time of import.\n\nThat can be solved by creating a new API endpoint in your Next.js app for `/api/video` with the following code.\n\n**App router (Next.js \u003e=13)**\n\n```js\n// app/api/video/route.js\nexport { GET } from 'next-video/request-handler';\n```\n\n**Pages router (Next.js)**\n\n```js\n// pages/api/video/[[...handler]].js\nexport { default } from 'next-video/request-handler';\n```\n\nThen set the `src` attribute to the URL of the remote video, refresh the page and the video will start processing.\n\n```tsx\nimport Video from 'next-video';\n\nexport default function Page() {\n  return \u003cVideo src=\"https://www.mydomain.com/remote-video.mp4\" /\u003e;\n}\n```\n\n\u003c/details\u003e\n\n### Change player theme ([Demo](https://next-video-demo.vercel.app/custom-theme))\n\nYou can change the player theme by passing the `theme` prop to the `\u003cVideo\u003e` component.  \nSee [player.style](https://player.style/) for more themes.\n\n```tsx\nimport Video from 'next-video';\nimport Instaplay from 'player.style/instaplay/react';\nimport awesomeVideo from '/videos/awesome-video.mp4';\n\nexport default function Page() {\n  return \u003cVideo src={awesomeVideo} theme={Instaplay} /\u003e;\n}\n```\n\n### Player only ([Demo](https://next-video-demo.vercel.app/hls-source))\n\nSince [`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.\n\n```tsx\nimport Player from 'next-video/player';\n// or\nimport BackgroundPlayer from 'next-video/background-player';\n\nexport default function Page() {\n  return (\n    \u003cPlayer\n      src=\"https://www.mydomain.com/remote-video.mp4\"\n      poster=\"https://www.mydomain.com/remote-poster.webp\"\n      blurDataURL=\"data:image/webp;base64,UklGRlA...\"\n    /\u003e\n  );\n}\n```\n\n### Custom poster and blurDataURL\n\nYou can add a custom poster and blurDataURL to the video by passing them as props.\n\n```tsx\nimport Video from 'next-video';\nimport awesomeVideo from '/videos/awesome-video.mp4';\nimport awesomePoster from '../public/images/awesome-poster.jpg';\n\nexport default function Page() {\n  return (\n    \u003cVideo src={awesomeVideo} poster={awesomePoster.src} blurDataURL={awesomePoster.blurDataURL} /\u003e\n  );\n}\n```\n\nThis is a good solution but it will not provide the same level of optimization\nas the automatic poster and blurDataURL by the default provider.\n\nTo get the same level of optimization you can use a slotted poster element.\n\n### Slotted poster image element ([Demo](https://next-video-demo.vercel.app/slotted-poster))\n\nAdd a slotted poster image element\n(like [`next/image`](https://nextjs.org/docs/app/api-reference/components/image))\nto the video by passing it as a child with a `slot=\"poster\"` attribute.\n\nNow your image will get all the benefits of the used image component\nand it will be nicely placed behind the video player controls.\n\n```tsx\nimport Image from 'next/image';\nimport Video from 'next-video';\nimport awesomeVideo from '/videos/awesome-video.mp4';\nimport awesomePoster from '../public/images/awesome-poster.jpg';\n\nexport default function Page() {\n  return (\n    \u003cVideo src={awesomeVideo}\u003e\n      \u003cImage\n        slot=\"poster\"\n        src={awesomePoster}\n        placeholder=\"blur\"\n        alt=\"Some peeps doing something awesome\"\n      /\u003e\n    \u003c/Video\u003e\n  );\n}\n```\n\n### Custom Player ([Demo](https://next-video-demo.vercel.app/custom-player))\n\nYou can customize the player by passing a custom player component to the `as` prop.  \nThe custom player component accepts the following props:\n\n- `asset`: The asset that is processed, contains useful asset metadata and upload status.\n- `src`: A string video source URL if the asset is ready.\n- `poster`: A string image source URL if the asset is ready.\n- `blurDataURL`: A string base64 image source URL that can be used as a placeholder.\n\n#### Example ([react-player](https://github.com/cookpete/react-player))\n\n```tsx\nimport Video from 'next-video';\nimport ReactPlayer from './player';\nimport awesomeVideo from '/videos/awesome-video.mp4';\n\nexport default function Page() {\n  return \u003cVideo as={ReactPlayer} src={awesomeVideo} /\u003e;\n}\n```\n\n```tsx\n// player.tsx\n'use client';\n\nimport type { PlayerProps } from 'next-video';\nimport ReactPlayer from 'react-player';\n\nexport default function Player(props: PlayerProps) {\n  let { asset, src, poster, blurDataURL, thumbnailTime, ...rest } = props;\n  let config = { file: { attributes: { poster } } };\n\n  return \u003cReactPlayer url={src} config={config} width=\"100%\" height=\"100%\" {...rest} /\u003e;\n}\n```\n\n#### Example ([mux-player](https://www.mux.com/docs/guides/mux-player-web?utm_source=next-video.dev))\n\n```tsx\nimport Video from 'next-video';\nimport MuxPlayer from './player';\nimport awesomeVideo from '/videos/awesome-video.mp4';\n\nexport default function Page() {\n  return \u003cVideo as={MuxPlayer} src={awesomeVideo} /\u003e;\n}\n```\n\n```tsx\n// player.tsx\n'use client';\n\nimport type { PlayerProps } from 'next-video';\nimport MuxPlayer from '@mux/mux-player-react';\n\nexport default function Player(props: PlayerProps) {\n  let { asset, src, poster, blurDataURL, theme, ...rest } = props;\n  const playbackId = asset?.providerMetadata?.mux?.playbackId;\n\n  return \u003cMuxPlayer playbackId={playbackId} {...rest} /\u003e\n}\n```\n\n\n### Background Video ([Demo](https://next-video-demo.vercel.app/background-video))\n\nYou can use a `\u003cBackgroundVideo\u003e` component to add a video as a background with\nno player controls. This saves about 50% of the JS player size and is optimized\nfor background video usage.\n\nThe `\u003cBackgroundVideo\u003e` component is a custom player like you saw in the previous section.\n\nThe `thumbnailTime` query parameter in the example below is used to generate\na poster image and blur up image at the specified time in the video\n(limited to usage with the `mux` provider).\n\n```tsx\nimport BackgroundVideo from 'next-video/background-video';\nimport getStarted from '/videos/country-clouds.mp4?thumbnailTime=0';\n\nexport default function Page() {\n  return (\n    \u003cBackgroundVideo src={getStarted}\u003e\n      \u003ch1\u003enext-video\u003c/h1\u003e\n      \u003cp\u003e\n        A React component for adding video to your Next.js application. It extends both the video\n        element and your Next app with features for automatic video optimization.\n      \u003c/p\u003e\n    \u003c/BackgroundVideo\u003e\n  );\n}\n```\n\n### Hosting \u0026 Processing Providers\n\nYou can choose between different providers for video processing and hosting.\nThe default provider is [Mux](https://mux.com?utm_source=next-video.dev).\nTo change the provider you can add a `provider` option in the next-video config.\nSome providers require additional configuration which can be passed in the `providerConfig` property.\n\n```js\n// next.config.js\nconst { withNextVideo } = require('next-video/process');\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nmodule.exports = withNextVideo(nextConfig, {\n  provider: 'backblaze',\n  providerConfig: {\n    backblaze: { endpoint: 'https://s3.us-west-000.backblazeb2.com' },\n  },\n});\n```\n\nSupported providers with their required environment variables:\n\n| Provider                                                     | Environment vars                                                                                          | Provider config                                                                                                                                   | Pricing link                                                             |\n| ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |\n| [`mux`](https://mux.com?utm_source=next-video.dev) (default) | `MUX_TOKEN_ID`\u003cbr/\u003e`MUX_TOKEN_SECRET`                                                                     | [`videoQuality`](https://www.mux.com/docs/guides/use-video-quality-levels?utm_source=next-video.dev): `'basic' \\| 'plus' \\| 'premium'` (optional) | [Pricing](https://www.mux.com/pricing/video?utm_source=next-video.dev)   |\n| [`vercel-blob`](https://vercel.com/docs/storage/vercel-blob) | `BLOB_READ_WRITE_TOKEN`                                                                                   |                                                                                                                                                   | [Pricing](https://vercel.com/docs/storage/vercel-blob/usage-and-pricing) |\n| [`backblaze`](https://www.backblaze.com/cloud-storage)       | `BACKBLAZE_ACCESS_KEY_ID`\u003cbr/\u003e`BACKBLAZE_SECRET_ACCESS_KEY`                                               | `endpoint`\u003cbr/\u003e`bucket` (optional)                                                                                                                | [Pricing](https://www.backblaze.com/cloud-storage/pricing)               |\n| [`amazon-s3`](https://aws.amazon.com/s3)                     | `AWS_ACCESS_KEY_ID`\u003cbr/\u003e`AWS_SECRET_ACCESS_KEY`                                                           | `endpoint`\u003cbr/\u003e`bucket` (optional)                                                                                                                | [Pricing](https://aws.amazon.com/s3/pricing/)                            |\n| [`cloudflare-r2`](https://developers.cloudflare.com/r2/)     | `R2_ACCESS_KEY_ID`\u003cbr/\u003e`R2_SECRET_ACCESS_KEY`\u003cbr/\u003e`R2_CF_API_TOKEN` (optional when `bucketUrlPublic` set) | `bucket` (optional)\u003cbr/\u003e`bucketUrlPublic` (optional when `R2_CF_API_TOKEN` set)                                                                   | [Pricing](https://developers.cloudflare.com/r2/pricing/)                 |\n\n#### Provider feature set\n\n|                              | Mux (default) | Vercel Blob | Backblaze | Amazon S3 | Cloudflare R2 |\n| ---------------------------- | ------------- | ----------- | --------- | --------- | ------------- |\n| Off-repo storage             | ✅            | ✅          | ✅        | ✅        | ✅            |\n| Delivery via CDN             | ✅            | ✅          | -         | -         | ✅            |\n| BYO player                   | ✅            | ✅          | ✅        | ✅        | ✅            |\n| Compressed for streaming     | ✅            | -           | -         | -         |               |\n| Adapt to slow networks (HLS) | ✅            | -           | -         | -         |               |\n| Automatic placeholder poster | ✅            | -           | -         | -         |               |\n| Timeline hover thumbnails    | ✅            | -           | -         | -         |               |\n| Stream any source format     | ✅            | \\*          | \\*        | \\*        | \\*            |\n| AI captions \u0026 subtitles      | ✅            | -           | -         | -         |               |\n| Video analytics              | ✅            | -           | -         | -         |               |\n| Pricing                      | Minutes-based | GB-based    | GB-based  | GB-based  | GB-based      |\n\n\\*Web-compatible MP4 files required for hosting providers without video processing\n\n### Asset metadata storage hooks (callbacks)\n\nBy default the asset metadata is stored in a JSON file in the `/videos` directory.\nIf you want to store the metadata in a database or elsewhere you can customize\nthe storage hooks in a separate next-video config file.\n\nThe below example config shows the default storage hooks for the JSON file storage.\n\nThese hooks can be customized to fit your needs by changing the body of the\n`loadAsset`, `saveAsset`, and `updateAsset` functions.\n\n```js\n// next-video.mjs\nimport { NextVideo } from 'next-video/process';\nimport path from 'node:path';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\n\nexport const { GET, POST, handler, withNextVideo } = NextVideo({\n  // Other next-video config options should be added here if using a next-video config file.\n  // folder: 'videos',\n  // path: '/api/video',\n\n  loadAsset: async function (assetPath) {\n    const file = await readFile(assetPath);\n    const asset = JSON.parse(file.toString());\n    return asset;\n  },\n  saveAsset: async function (assetPath, asset) {\n    try {\n      await mkdir(path.dirname(assetPath), { recursive: true });\n      await writeFile(assetPath, JSON.stringify(asset), {\n        flag: 'wx',\n      });\n    } catch (err) {\n      if (err.code === 'EEXIST') {\n        // The file already exists, and that's ok in this case. Ignore the error.\n        return;\n      }\n      throw err;\n    }\n  },\n  updateAsset: async function (assetPath, asset) {\n    await writeFile(assetPath, JSON.stringify(asset));\n  },\n});\n```\n\nThen import the `withNextVideo` function in your `next.config.mjs` file.\n\n```js\n// next.config.mjs\nimport { withNextVideo } from './next-video.mjs';\n\n/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default withNextVideo(nextConfig);\n```\n\nLastly import the `GET` and `POST`, or `handler` functions in your API routes as you see fit.\nThe handlers expect a `url` query or body parameter with the video source URL.\n\nThese are the most minimal examples for the handlers, typically you would add\nmore error handling and validation, authentication and authorization.\n\n**App router (Next.js \u003e=13)**\n\n```js\n// app/api/video/route.js\nexport { GET, POST } from '@/next-video';\n```\n\n**Pages router (Next.js)**\n\n```js\n// pages/api/video/[[...handler]].js\nexport { handler as default } from '@/next-video';\n```\n\n## Default Player\n\nThe default player is built with [Media Chrome](https://github.com/muxinc/media-chrome).\n\n- The default theme is [Sutro](https://player.style/themes/sutro) by Mux.\n- The video engine changes automatically based on the source format:\n  - Video files (like MP4, MP3, WEBM) that are progressively downloaded are played with the native `\u003cvideo\u003e` element.\n  - Mux videos are played with [`\u003cmux-video\u003e`](https://github.com/muxinc/elements/tree/main/packages/mux-video).\n  - HLS streams are played with [`\u003chls-video\u003e`](https://github.com/muxinc/media-elements/tree/main/packages/hls-video-element).\n  - DASH streams are played with [`\u003cdash-video\u003e`](https://github.com/muxinc/media-elements/tree/main/packages/dash-video-element).\n\n### Props\n\nThe `\u003cVideo\u003e` component accepts all the props of the `\u003cvideo\u003e` element and the following additional props:\n\n- `src` (Asset | string): The video asset object (import) or source URL.\n- `poster` (StaticImageData | string): A placeholder image for the video. (Auto generated for Mux videos)\n- `blurDataURL` (string): A base64 image source URL that can be used as a placeholder. (Auto generated for Mux videos)\n- `theme` (React Component): The player theme component. See [player.style](https://player.style/) for more themes.\n- `as` (React Component): A custom player component. See [Custom player](#custom-player-demo).\n- `transform` (function): A custom function to transform the asset object (src and poster).\n- `loader` (function): A custom function used to resolve string based video URLs (not imports).\n\n#### Mux video props\n\nThe `\u003cVideo\u003e` component with a Mux video source accepts the following additional props:\n\n- `startTime` (number): The start time of the video in seconds.\n- `streamType` (\"on-demand\" | \"live\"): The stream type of the video. Default is \"on-demand\".\n- `customDomain` (string): Assigns a custom domain to be used for Mux Video.\n- `beaconCollectionDomain` (string): Assigns a custom domain to be used for Mux Data collection. NOTE: Must be set before playbackId to apply to Mux Data monitoring.\n- `envKey` (string): This is the environment key for Mux Data. If you use Mux video this is automatically\n  set for you. If you use a different provider you can set this to your own key.\n- `disableTracking` (boolean): Disables Mux data tracking of video playback.\n- `disableCookies` (boolean): Disables cookies used by Mux Data.\n- `preferPlayback` (\"mse\" | \"native\"): Specify if `\u003cmux-video\u003e` should try to use Media Source Extension or native playback (if available). If no value is provided, `\u003cmux-video\u003e` will choose based on what's deemed optimal for content and playback environment.\n- `maxResolution` (\"720p\" | \"1080p\" | \"1440p\" | \"2160p\"): Specify the maximum resolution you want delivered for this video.\n- `minResolution` (\"480p\" | \"540p\" | \"720p\" | \"1080p\" | \"1440p\" | \"2160p\"): Specify the minimum resolution you want delivered for this video.\n- `programStartTime` (number): Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream.\n- `programEndTime` (number): Apply PDT-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the end of the media stream.\n- `assetStartTime` (number): Apply media timeline-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the beginning of the media stream.\n- `assetEndTime` (number): Apply media timeline-based [instant clips](https://docs.mux.com/guides/create-instant-clips) to the end of the media stream.\n- `renditionOrder` (string): Change the order in which renditions are provided in the src playlist. Can impact initial segment loads. Currently only support \"desc\" for descending order.\n- `metadataVideoId` (string): This is an arbitrary ID sent to Mux Data that should map back to a record of this video in your database.\n- `metadataVideoTitle` (string): This is an arbitrary title for your video that will be passed in as metadata into Mux Data. Adding a title will give you useful context in your Mux Data dashboard. (optional, but encouraged)\n- `metadataViewerUserId` (string): If you have a logged-in user, this should be an anonymized ID value that maps back to the user in your database that will be sent to Mux Data. Take care to not expose personal identifiable information like names, usernames or email addresses. (optional, but encouraged)\n- `metadata*` (string): This metadata\\* syntax can be used to pass any arbitrary Mux Data metadata fields.\n- `playbackToken` (string): The playback token for signing the `src` URL.\n- `thumbnailToken` (string): The token for signing the `poster` URL.\n- `storyboardToken` (string): The token for signing the storyboard URL.\n- `drmToken` (string): The token for signing DRM license and related URLs.\n- `targetLiveWindow` (number): An offset representing the seekable range for live content, where `Infinity` means the entire live content is seekable (aka \"standard DVR\"). Used along with `streamType` to determine what UI/controls to show.\n- `liveEdgeOffset` (number): The earliest playback time that will be treated as playing \"at the live edge\" for live content.\n- `debug` (boolean): Enables debug mode for the underlying playback engine (currently hls.js) and mux-embed, providing additional information in the console.\n\n\n#### Styling the default player\n\nThe default theme is [Sutro](https://player.style/themes/sutro) which can be styled with CSS variables.\nIf you are looking to completely change the layout and style it's recommended to [change the `theme` prop](#change-player-theme-demo) to a different theme or create a new theme.\n\n**CSS Variables**: The default theme uses CSS variables for many colors, so you can override them in your CSS.\n\n- `--media-primary-color`: The color of the control icons.\n- `--media-secondary-color`: The background color of the control when hovered.\n- `--media-accent-color`: The color of the volume slider and time slider.\n\nFor example:\n\n```tsx\nimport Video from 'next-video';\nimport getStarted from '/videos/get-started.mp4';\n\nexport default function Page() {\n  return \u003cVideo src={getStarted} style={{\n    '--media-primary-color': '#fdaff3',\n    '--media-secondary-color': '#ff0088',\n    '--media-accent-color': '#42ffe0',\n  }} /\u003e;\n}\n```\n\nThis is just the tip of the iceberg. For a full list of CSS variables, check out the [Media Chrome styling docs](https://www.media-chrome.org/docs/en/reference/styling)\n\n\n## Required Permissions for Amazon S3\n\n\u003cdetails\u003e\n\u003csummary\u003eIf you're using Amazon S3 as the provider, you'll need to create a new IAM user with the following permissions:\u003c/summary\u003e\n\n```json\n{\n  \"Version\": \"2012-10-17\",\n  \"Statement\": [\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\"s3:ListAllMyBuckets\", \"s3:CreateBucket\", \"s3:PutBucketOwnershipControls\"],\n      \"Resource\": \"*\"\n    },\n    {\n      \"Effect\": \"Allow\",\n      \"Action\": [\n        \"s3:PutBucketPublicAccessBlock\",\n        \"s3:PutBucketAcl\",\n        \"s3:PutBucketCORS\",\n        \"s3:GetObject\",\n        \"s3:PutObject\",\n        \"s3:PutObjectAcl\",\n        \"s3:ListBucket\"\n      ],\n      \"Resource\": \"arn:aws:s3:::next-videos-*\"\n    }\n  ]\n}\n```\n\n\u003c/details\u003e\n\n## Cloudflare R2 Bucket Public Access\n\n\u003cdetails\u003e\n\u003csummary\u003eBy default, Cloudflare R2 Buckets are not publicly accessible. To enable public access, you must ensure one of the following:\u003c/summary\u003e\n\n1. Configure the Bucket for Public Access:\n\n   - Provide a `bucket` Name in the provider configuration and ensure it is configured for public access\n   - Specify the public URL in the provider configuration under the `bucketUrlPublic` key\n   - For detailed instructions, refer to the Cloudflare documentation:\n     https://developers.cloudflare.com/r2/buckets/public-buckets/\n\n2. Provide a Cloudflare API Key:\n   - You can specify a Cloudflare API Key with R2 Admin read \u0026 write permissions using the environment variable: `R2_CF_API_TOKEN`\n   - This API Key will allow the provider to enable public access for the bucket and retrieve the public URL using the Cloudflare API\n   - You don't need to create a bucket manually\n   - To create an API Token, visit:\n   https://dash.cloudflare.com/?to=/:account/r2/api-tokens\n   \u003c/details\u003e\n\n## Roadmap\n\n### v0\n\n- [x] Automatic video optimization\n- [x] Delivery via a CDN\n- [x] Automatically upload and process local source files\n- [x] Automatically process remote hosted source files\n\n### v1\n\n- [x] Customizable player\n- [x] Connectors for additional video services\n- [x] AI captions\n\n## Trying it out locally\n\nIf 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.\n\n1. Clone this repo\n1. `cd` into the repo\n1. `npm install \u0026\u0026 npm run build`\n1. `cd ../` (or back to wherever you want to create a test app)\n1. `npx create-next-app`\n1. `cd your-next-app`\n1. `npx link ../next-video` (or wherever you cloned this repo)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuxinc%2Fnext-video","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmuxinc%2Fnext-video","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmuxinc%2Fnext-video/lists"}