Getting MediaStreamError { name: "AbortError", message: "Starting video failed", constraint: "", stack: "" } on one PC, but not on another
Asked Answered
T

3

3

I'm getting MediaStreamError { name: "AbortError", message: "Starting video failed", constraint: "", stack: "" } on my desktop PC, but not on my notebook PC. Note: both PCs run Windows 10 and use identical code base.

The app works great on my notebook using Firefox (with USB 2.0 HD UVC Webcam), but on my desktop PC, whether using Firefox, Edge, or Chrome, I still get the error. My desktop PC camera is Logitech (Logitech HD WebCam C270), and I saw on another post for the same error Firefox 54 (ubuntu 14.04): Twilio video failed getUserMedia that someone else (@Roger Walsh) also had the same error using a Logitech camera.

Here is the code: Front-end (Angular View)

<div class="camera">
  <video #videoRef id="video" [(ngModel)]="video" (canplay)="setVideo()" name="video" ngDefaultControl>Video stream not available.</video>
  <button #startbuttonRef id="startbutton" [(ngModel)]="startbutton" (click)="takePicture()" name="startbutton" ngDefaultControl>Take photo</button>
</div>

<canvas #canvasRef id="canvas" [(ngModel)]="canvas" name="canvas" ngDefaultControl style="display:none"></canvas>
<div class="output">
  <img #photoRef id="photo" [(ngModel)]="photo" name="photo" ngDefaultControl alt="The screen capture will appear in this box.">
</div>

Front-end (Angular Component)

import { Component, Input, OnInit, forwardRef, ViewChild, ElementRef } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-capture-image',
  templateUrl: './capture-image.component.html',
  styleUrls: ['./capture-image.component.scss'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => CaptureImageComponent),
      multi: true
    }
  ]
})
export class CaptureImageComponent implements OnInit {
  @ViewChild('videoRef') videoRef: ElementRef;
  @ViewChild('canvasRef') canvasRef: ElementRef;
  @ViewChild('photoRef') photoRef: ElementRef;
  @ViewChild('startbuttonRef') startbuttonRef: ElementRef;
  streaming = false;
  width = 320;
  height = 0;

  constructor(private http: HttpClient) { }

  ngOnInit() {
    navigator.mediaDevices.getUserMedia({video: true, audio: false})
      .then((stream) => {
        this.videoRef.nativeElement.srcObject = stream;
        this.videoRef.nativeElement.play();
      })
      .catch(function(err) {
        console.log(err);
      });
      this.clearPhoto();
  }


  setVideo() {
    if (!this.streaming) {
      this.height = this.videoRef.nativeElement.videoHeight/ (this.videoRef.nativeElement.videoWidth/this.width);
      this.videoRef.nativeElement.width = this.width;
      this.videoRef.nativeElement.height = this.height;
      this.canvasRef.nativeElement.width = this.width;
      this.canvasRef.nativeElement.height = this.height;
      this.streaming = true; 
    }
  }

  clearPhoto() {
    let context = this.canvasRef.nativeElement.getContext('2d');
    context.fillStyle = "#AAA";
    context.fillRect(0,0,this.canvasRef.nativeElement.width, this.canvasRef.nativeElement.height);

    var data = this.canvasRef.nativeElement.toDataURL('image/png');
    this.photoRef.nativeElement.src = data;
  }

  takePicture() {
    let context: CanvasRenderingContext2D  = this.canvasRef.nativeElement.getContext('2d');

    if (this.width && this.height) {
      this.canvasRef.nativeElement.width = this.width;
      this.canvasRef.nativeElement.height = this.height;
      context.drawImage(this.videoRef.nativeElement, 0, 0, this.width, this.height);

      let fd = new FormData();

      this.canvasRef.nativeElement.toBlob((blob) => {
        let url = URL.createObjectURL(blob);
        this.photoRef.nativeElement.onload = function() {
          URL.revokeObjectURL(url);
        };
        this.photoRef.nativeElement.src = url;

        fd.append('image', blob, "myPicture");
        fd.append('timeStamp', Date.now().toString());
        console.log("Uploading: " + JSON.stringify(fd));
        try {
            this.http.post("http://localhost:3000/selection/test-photo",fd)
            .subscribe(
              (res) => {
                console.log("Successful result: " + JSON.stringify(res))},
              (err) => {
                console.log("Subscribe error: " + JSON.stringify(err))} 
          );
        }
        catch(e) {
          console.log("Caught error: " + e);
        }

      }, 'image/png')

    } else {
      this.clearPhoto();
    }
  }

}

Back-end (Express)

exports.selection_test_photo = [
    (req,res,next) => {
        const photo = new Photo();
        console.log("Entering Post: " + util.inspect(req.file) + "; " + req.body.timeStamp);        
        photo.photo.data = fs.readFileSync(req.file.path);
        photo.photo.contentType = 'image/png';
        photo.timeStamp = {"value": req.body.timeStamp};
        console.log("About to save . . . ");
        photo.save(function(err){
            if (err) {return next(err)};
            res.json({"foo": "bar"});
        });        
    },

];

Has anyone else had this problem? Any ideas? Tks!

Tramontane answered 17/6, 2019 at 23:51 Comment(0)
S
4

https://bugzilla.mozilla.org/show_bug.cgi?id=1588939 Says:

"Evidently two instances of getUserMedia({video:true}) cannot exist at the same time."

Simultaneous answered 8/12, 2019 at 13:41 Comment(0)
T
1

This might be the browser specific issue. please check your web-cam in the browser using some web cam test sites. Following are some example sites which you can use to test:

  1. https://www.onlinemictest.com/webcam-test/
  2. https://webcamtests.com/
  3. https://www.vidyard.com/cam-test/

If it is working, then try adding the following code to the onload event of your page:

navigator.mediaDevices.getUserMedia = navigator.mediaDevices.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia;

It should provide cross browser support as well.

Tout answered 16/9, 2019 at 8:24 Comment(2)
I clicked to allow permission for the camera, but the test sites you provided are still not working. I guess my firewall is blocking? Any ideas?Tramontane
Hey @Tramontane there if this is the case then it might be the issue with the browser version. Try upgrading it to the latest version.Tout
D
1

I ran into this same issue and it turned out to related to FF not working properly. I realize my resolution probably won't solve the OP's code, but this post shows up pretty high in the search results so I thought I would help anyone else out who may end up here (like I did).

I am using a MacBook Pro, CalDigit docking station, Dell ultra-wide monitor with extra USB ports, and a Logitech 1080p camera (exact hardware does not matter so much because others I know have different hardward/setups but the same issue). I have reproduced my issue two different ways. It is sporadic (meaining one config may work one day, but not the next) and only happens in Firefox:

  1. Logitech plugged into Dell via USB -> Dell plugged into docking station via USB -> dock plugged into macbook via thunderbolt
  2. Logitech plugged into dock via USB -> dock plugged into macbook via thunderbolt

Turns out it had to do with how I was requesting the camera from getUserMedia(). For example:

await window.navigator.mediaDevices.getUserMedia({
  audio: {},
  video: {​​​
    deviceId: { exact: 'id of logitech camera' },
    frameRate: { ideal: 30 }, ​​​
    height: { ideal: 2160 },​​​
    width: { ideal: 4096 }
  }
});

That would throw a MediaStreamError with AbortError: Starting video failed:

ERROR-message

When I called it like this, it would succeed:

await window.navigator.mediaDevices.getUserMedia({
  audio: {},
  video: {​​​
    deviceId: { exact: 'id of logitech camera' },
    frameRate: { ideal: 30 }, ​​​
    height: { ideal: 720 },​​​ // drop down to 720p
    width: { ideal: 1280 } // drop down to 1280p
  }
});

It appears Firefox isn't respecting the ideal constraint. Also, something must get messed up between the camera and the machine because I tried 1080p (which my camera supports) and it still failed. I had to drop it this low. Another note (to prove it was related to the FF not handling external hardware correctly), if I called this it would work everytime.

await window.navigator.mediaDevices.getUserMedia({
  audio: {},
  video: {​​​
    deviceId: { exact: 'ID OF MAC BOOK BUILTIN CAMERA' },
    frameRate: { ideal: 30 }, ​​​
    height: { ideal: 2160 },​​​
    width: { ideal: 4096 }
  }
});
Deepseated answered 9/11, 2020 at 20:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.