Nico
Nico

Reputation: 326

2019s way of accessing navigator.mediaDevices.getUserMedia()

I am currently developing an angular7-app, created it the standard way through CLI and started coding. Now I would like to record some audio which is no difficult thing in modern browsers. I am using the built-in browser functionalities of getUserMedia(). Now comes the problem: zone.js catches all calls to the then() callback and does not allow to execute the custom code inside.

BUT: There is the patch delivered with zone.js, so that this special callback is called: https://github.com/angular/zone.js/blob/master/dist/zone-patch-user-media.js

Unfortunately, this refers to a depreciated implementation of getUserMedia() (https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia). So this script does not work. I tried changing it but nothing works. The patch is called because console.log() is displayed and in the debugger, I can go through the function. I assume, that this might be a little change to execute the callback. In the debugger the callback is then again catched by a function in zone.js which, as I assume, should not be called when the patch works. My implementation is the same as here (https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia):

navigator.mediaDevices.getUserMedia(constraints).then(
function(stream) {
    /* use the stream */ 
}).catch(
function(err) { 
    /* handle the error */ 
});

So, what is the current way of getting the callback to work? Or am I getting the concept wrong? Or should I use some library from npm to record the audio?

Upvotes: 2

Views: 3899

Answers (1)

Christian Vincenzo Traina
Christian Vincenzo Traina

Reputation: 10444

As much as I know, zone.js should not cause problems if used with navigator methods, since they're well known and correctly patched. By the way, if you are sure of what you say, you can still use zone.runOutsideAngular to go out from a zone:

constructor(private zone: NgZone) { }

yourMethod() {
  this.zone.runOutsideAngular(() => {
    navigator.mediaDevices.getUserMedia(constraints)
      .then(stream => console.log(stream))
      .catch(err => console.error(err));
  });

}

If then you want to re-enter a zone, you can call:

this.zone.run(() => {
  // again inside a zone
});

But be aware that you need it only if you want to continue an async flow. The sync code will keep being executed inside a zone:

yourMethod() {
  // this is inside a zone

  this.zone.runOutsideAngular(() => {
    navigator.mediaDevices.getUserMedia(constraints)
      .then(stream => {

        // this is outside a zone

        this.zone.run(() => {

           // and again inside a zone

        });
      })
      .catch(err => console.error(err));
  });

 // this is still inside a zone

}

Upvotes: 4

Related Questions