Yervand
Yervand

Reputation: 139

NextJS throws error when I add a background video

I want to add background video, format mp4, but NextJS shows error:

./public/video/ocean.mp4 1:0
Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type, currently 
no loaders are configured to process this file. See 
https://webpack.js.org/concepts#loaders

(Source code omitted for this binary file)

import React, {useEffect, useRef} from "react"
import Layout from "../components/webSite/layout";
import backgroundVideo from "../public/video/ocean.mp4"

const Home = () => {
  const videoRef = useRef()

  useEffect(() => {
    setTimeout(()=>{
      videoRef.current.play()
    },5000)
  }, []);

  return <Layout title={"Home"}>
    <video
        ref={videoRef}
        controls
        width="250"
        loop
        muted
        style={{
          position: "relative",
          width: "100%",
          height: "15rem",
          left: 0,
          top: 0,
        }}>
      <source src={backgroundVideo} type="video/mp4"/>
    </video>
  </Layout>
}

export default Home

Upvotes: 13

Views: 15812

Answers (3)

Cobertos
Cobertos

Reputation: 2253

Contrary to the other answers, it is not inefficient to import an .mp4 (using the right loader) and it doesn't require a Next.js-specific plugin.

Using file-loader, webpack will give you a URL as the import of your .mp4. webpack simply copies the .mp4 to the output directory (not in the bundle) and returns a relative URL to that. It will be requested normally when you use it in a <video> element.

To use file-loader for .mp4s, you can add a webpack() callback to your next.config.js like the below.

export default {
webpack(config, { isServer }) {
    const prefix = config.assetPrefix ?? config.basePath ?? '';
    config.module.rules.push({
      test: /\.mp4$/,
      use: [{
        loader: 'file-loader',
        options: {
          publicPath: `${prefix}/_next/static/media/`,
          outputPath: `${dev ? '' : '../'}${isServer ? '../' : ''}static/media/`,
          name: '[name].[hash:8].[ext]',
        },
      }],
    });

    return config;
  },
};

Note: If you're using an older version of Next.js, you may need this outputPath config instead:

outputPath: `${isServer ? '../' : ''}static/media/`,

Then simply import your .mp4 and use it in a <video> element

import myvideo from './myvideo.mp4';
export default function MyVideo(){
  return <video>
    <source src={myvideo} type="video/mp4"/>
  </video>;
}

If you're using TypeScript, you'll also want to add a declaration for the file extensions that you're loading with file-loader. This should go in a .d.ts, Next.js recommends (scroll down to find the info box mentioning it) making videos.d.ts and then adding it to your TS config include property.

// videos.d.ts
declare module '*.mp4' {
  const path: string;
  export default path;
}

References

Upvotes: 12

Rajpreet Singh
Rajpreet Singh

Reputation: 51

If the first answer won't work then try this:

Install a Package called

next-videos 

After Installing go to your next.config.js File in your project and do this:

const withVideos = require('next-videos')
module.exports = withVideos()

Important is that after editing your config file you have to restart the server if you don't it won't work either.

In your File, you have to use require() in your component

For Example like this:

 export default () => (
   <div>
       <video src={(require('./video.mp4'))}/>
   </div>
  )

All Information are used from npm.js website:

https://www.npmjs.com/package/next-videos

Upvotes: 5

Jesper We
Jesper We

Reputation: 6087

Everything that you import in React actually needs a webpack loader that understands the format.

MP4 is not one of those formats. Even if it was, importing an entire video file would be horribly inefficient :-)

Solution: Don't import the video file, instead reference it as an external file that the browser loads over http like any other media file. All files you put in /public can be referenced below the top folder of you web site:

<source src="/video/ocean.mp4" type="video/mp4"/>

Upvotes: 19

Related Questions