javascriptnext.jsvideocross-origin-embedder-policycross-origin-opener-policy

Playing live video feed from web camera in the browser


I am trying to create an app that will allow somebody to record their video and audio feeds on the browser and play it back to themselves. While recording, I am streaming the video so they can see themselves on the screen.

const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });

streamRef.current = stream;

if (videoRef.current) {
    videoRef.current.srcObject = stream;
}

The code snippet gets the video stream from the media device and adds that to a ref given to a video element.

<video
  ref={videoRef}
  autoPlay
  playsInline
  muted
/>

This set up works well on my local device, however, I have run into issue with the video properly loading in production - the app is built using Next.js and I host it on Vercel.

Instead of displaying the video feed there is simply a black screen, however, after the recording is complete I am still able to view the video and listen to the audio without issue - just the streaming of the video whilst recording that does not work as intended.

On production, I receive an error that the Cross-Origin-Embedder-Policy needs to be set to prevent the frame from being blocked.

COEP status error console error of COEP

However, I have already configured COEP and COOP in the next.config.js file and can confirm that it is present in other requests in the application.

const nextConfig = {
  async headers() {
    return [
      {
        source: "/(.*)",
        headers: [
          {
            key: "Cross-Origin-Opener-Policy",
            value: "same-origin",
          },
          {
            key: "Cross-Origin-Embedder-Policy",
            value: "require-corp",
          },
        ],
      },
    ];
  },
};

module.exports = nextConfig;

COEP and COOP headers set

It feels like I'm missing something extremely fundamental and I have been completely unable to figure out what that is 😅. Any advice on this issue would be greatly appreciated, thank you !

The source code for where I set up the video feed can be found here.

A live working example can be found here, although the feature is behind an authentication wall and will require sign-up.


Solution

  • (1) Try with a middleware.ts file on root of your project:

    import { NextResponse } from 'next/server';
    import type { NextRequest } from 'next/server';
    
    export function middleware(request: NextRequest) {
      const response = NextResponse.next();
    
      response.headers.set('Cross-Origin-Opener-Policy', 'same-origin');
      response.headers.set('Cross-Origin-Embedder-Policy', 'require-corp');
    
      return response;
    }
    

    (2) Use .play() to display camera feed inside the associated <video> tag:

    if (videoRef.current) {
        videoRef.current.srcObject = stream;
        videoRef.current.play(); //# to display the cameara feed
    }