Issue when switching cameras on specific android devices "device already in use"

I’ve tested the following code and it works perfectly on every device i’ve used except one Huawei android device. When the camera changes to one of the back ones it throws an error in the console saying the device is already in use, but it’s not in use! I’m literally using the front camera on the website and switching it to the back, nothing else is using the device.

I have 2 questions:

  1. What would be causing it to say the device is in use when it isn’t, and how do we get around this?

  2. The little snippet of code below, OVSession.publish is a promise, yet if i attach a catch() to it it doesn’t catch the promise rejection, instead it just puts an error in the console which isn’t helpful! This is using openvidu browser 2.20.0

this.OVSession.publish(this.OVPublisher).then(()=>{
              console.log("NEW PUBLISHER DONE")
            })

FULL CODE BELOW OF CAMERA SWITCHING

this.OV.getDevices().then((devices)=> {

        console.log("DEVICES",devices)
        let videoDevices = []
        if(this.OVCurrentCamera === 'front'){
          videoDevices = devices.filter(device => device.kind === 'videoinput' && device.label !== 'Snap Camera' && device.label.toLowerCase().indexOf('back') !== -1);
        }else{
          videoDevices = devices.filter(device => device.kind === 'videoinput' && device.label !== 'Snap Camera' && device.label.toLowerCase().indexOf('front') !== -1);
        }

        if(!videoDevices || videoDevices.length === 0){
          console.log("NO VIDEO DEVICES FOUND",videoDevices)
          videoDevices = devices.filter(device => device.kind === 'videoinput' && device.label !== 'Snap Camera');
        }

        if(videoDevices && videoDevices.length > 0){

          console.log("FOUND VIDEO DEVICES",videoDevices)

          // get new device id
          // if we already on front the back device is the last one in the list otherwise the first
          let newDeviceId = this.OVCurrentCamera === 'front' ?  videoDevices[videoDevices.length - 1].deviceId : videoDevices[0].deviceId;


          console.log("NEW DEVICE ID",newDeviceId)

          let newPublisher =  this.OV.initPublisher("publisher-video",{
            videoSource: newDeviceId,
            publishAudio: !this.muted,
            publishVideo: this.camOn,
            frameRate: 24,
            mirror: this.OVCurrentCamera === 'back' // mirror the video if we are switching FROM back - at this point it will be back
          });

          this.OVSession.unpublish(this.OVPublisher).then(() => {
            console.log("OLD PUBLISHER IS GONE")

            this.OVPublisher = newPublisher;

            this.OVCurrentCamera = this.OVCurrentCamera === 'front' ? 'back' : 'front';

            this.OVSession.publish(this.OVPublisher).then(()=>{
              console.log("NEW PUBLISHER DONE")
            })
          }).catch(() => {

            this.toast.error('Failed to switch camera, try again!');
            this.OVCurrentCamera = this.OVCurrentCamera === 'front' ? 'back' : 'front';
          })


        }else{
          this.toast.error('Could Not Load Your Cameras');
        }

      })

I’ve done some looking at this and i think the problem is because this Huawei device as the same id for an audio input and a video input:

kind: audioinput
deviceId: default
label: Default

kind: audioinput
deviceId: b949d225719f0c6d4cf905f7f0a2d19f821365a82a2d8f82bacdfaa4b950cc16
label: Speakerphone

then there are 4 back cameras, here is the one in question:

kind: vudeoinput
deviceId: b949d225719f0c6d4cf905f7f0a2d19f821365a82a2d8f82bacdfaa4b950cc16
label: camera2 0, facing back

Why on earth is it like this? I am using the last video device in the array to connect to which works perfectly on every other phone except this one, it seems like vidu is using Speakerphone as the audio input device by default??

So when i make the initial publisher:

this.OVPublisher = this.OV.initPublisher("publisher-video", {
          videoSource: true,
          audioSource: true,
          publishAudio: true,
          publishVideo: true,
          frameRate: 24,
          mirror: true
          //resolution: '1280x720'
        });

It seems like vidu is probably using the Speakerphone as the audio input device rather than the “default” one that is first. Why would it do that? It is a bit weird that the id is the same as the back camera one as well but that isn’t vidu fault

I don’t know why this is, but the issue was resolved by not initialising the new publisher until the unpublish event was complete

this.OVSession.unpublish(this.OVPublisher).then(() => {
            console.log("OLD PUBLISHER IS GONE")



            let newPublisher =  this.OV.initPublisher("publisher-video",{
              videoSource: newDeviceId,
              publishAudio: !this.muted,
              publishVideo: this.camOn,
              frameRate: 24,
              mirror: this.OVCurrentCamera === 'back' // mirror the video if we are switching FROM back - at this point it will be back
            });

            this.OVPublisher = newPublisher;

            this.OVCurrentCamera = this.OVCurrentCamera === 'front' ? 'back' : 'front';

            //this.OVSession.publish(this.OVPublisher).then(()=>{
            this.OVSession.publish(newPublisher).then(()=>{
              console.log("NEW PUBLISHER DONE")
              newPublisher=null;
            })
          }).catch(() => {

            this.toast.error('Failed to switch camera, try again!');
            this.OVCurrentCamera = this.OVCurrentCamera === 'front' ? 'back' : 'front';
          })
1 Like

Thank you for sharing the solution.

Regards