Jamie
Jamie

Reputation: 4295

getUserMedia API not working for iOS Safari in React

I'm trying to access the camera on iOS through implementing the getUserMedia API in my React App.

I've managed to successfully implement a component that renders and works fine on Chrome however it doesn't seem to work when I navigate to mylocalIP:3000 on iOS Safari. I would be very grateful for any pointers on where my code may be going wrong to not be compatible with iOS. StackBlitz link to the code

const Video: React.FC = (props) => {
    useEffect(() => {
        start()
    })

    const constraints = {
        audio: false,
        video: true
    };

    async function start() {
        const stream = await navigator.mediaDevices.getUserMedia(constraints)
        const video = document.getElementById('video') as HTMLVideoElement;
        video.setAttribute("playsinline", "true");
        video.setAttribute("controls", "true");
        video.srcObject = stream;
    }

    return (
        <video id='video' autoPlay playsInline></video>
    )
}

export default Video

Upvotes: 2

Views: 3580

Answers (1)

Jamie
Jamie

Reputation: 4295

Turns out that getUserMedia needs to be executed in an HTTPS environment.

In Create React App you need to create this HTTPS environment by changing the start script in package.json to "HTTPS=true react-scripts start"

The iOS device will warn that the CRA has an invalid signature, however if you proceed to the site, it will then prompt you for access to the webcam.

UPDATE: In all my CRA projects I use mkcert to install a Certificate Authority, and then generate certificates for webpack to use when compiling the site in CRA.

In CRA project root:

mkcert -install

mkdir .cert && cd $_ && mkcert localhost

printf "\nSSL_CRT_FILE=.cert/localhost.pem\nSSL_KEY_FILE=.cert/localhost-key.pem\nHTTPS=true" >> ../.env

OR if you don't like executing random commands you don't understand:

  1. Create a .cert/ folder in the project root
  2. Change directory into the .cert/ folder in your terminal
  3. Run mkcert localhost
  4. Create a .env file in your project root
  5. Inside this file add the following:
SSL_CRT_FILE=.cert/localhost.pem
SSL_KEY_FILE=.cert/localhost-key.pem
HTTPS=true

Upvotes: 8

Related Questions