feross / simple-peer

📡 Simple WebRTC video, voice, and data channels
MIT License
7.41k stars 971 forks source link

Uncaught DOMException: Failed to set local answer sdp: Called in wrong state: STATE_INPROGRESS #101

Closed smatthews1999 closed 7 years ago

smatthews1999 commented 7 years ago

I am getting this error (and others) when trying to re-initialize a video chat component. I have tried all manner of clearing the peer connection and reloading it.

Everything works fine on first attempt. Any subsequent attempts fail to load and get errors.

I am also getting errors: Cannot set remote answer in state stable Error: cannot signal after peer is destroyed

My code is as follows (angular 2).

@Component(
  {
    selector: 'vidcall',
    inputs: ['chattingWith'],
    template: `
    <div id="vidiv" #vidiv>
      <video #youvid></video>
      <video #othvid></video>
    </div>  
  `,
    styles: [`
    #vidiv{
      display: flex;     
      justify-content:space-around;
    }
  `]
  })
export class VideoComponent implements OnDestroy {
  @ViewChild('youvid') youvid: any;
  @ViewChild('othvid') othvid: any;
  private chattingWith: UserModel;
  private peer: any;
  private mediaStream: any;

  constructor(private srsvc: SRSvc) { }

  private sizeVid() {
    let w = Math.trunc(window.innerWidth / 3);
    console.log('width ', w);
    this.youvid.nativeElement.width = w;
    this.othvid.nativeElement.width = w;
  }

  @HostListener('window:resize', ['$event'])
  onResize(event) {
    this.sizeVid();
  }

  onVideoInit(init: boolean) { //
    this.sizeVid();
    navigator.mediaDevices.getUserMedia({
      video: true,
      audio: false
    })
      .then(mediaStream => {
        this.mediaStream = mediaStream;

        console.log('create new peer');
        this.peer = new window.SimplePeer(
          {
            initiator: init,
            stream: mediaStream,
            trickle: true
          });

        this.youvid.nativeElement.srcObject = mediaStream;
        this.youvid.nativeElement.play();

        // exchage peer data
        this.peer.on('signal', data => {
          console.log('on signal - initiator:', init);
          this.srsvc.sendPeerData(this.chattingWith.fbid, data); // signalr websocket
        })

        this.peer.on('stream', data => {
          console.log('on stream - initiator:', init);
          this.othvid.nativeElement.srcObject = data;
          this.othvid.nativeElement.play();
        })
        this.peer.on('close', () => {
          console.log('on close - initiator:', init);
          this.peer.destroy();
          this.peer = null;
          this.othvid.nativeElement.srcObject = null;
        })

        this.srsvc.recvPeerObservable.subscribe(resp => {
          console.log('recv peer data siglr - initiator:', init);
          if (this.peer) {
            this.peer.signal(resp.peerData)
          }
        })
      })
      .catch(err => {
        console.log('Simple Peer Error', err.name + ": " + err.message);
      });

  }
  destroy() {
    console.log('destroying peer', this.peer);
    if (this.peer) {
      this.peer.destroy();
      this.peer = null;
    }
    if (this.mediaStream) {
      for (let track of this.mediaStream.getTracks()) {
        track.stop();
      }
    }
    if (this.youvid.nativeElement.srcObject) {
      this.youvid.nativeElement.srcObject = null;
    }
    if (this.othvid.nativeElement.srcObject) {
      this.othvid.nativeElement.srcObject = null;
    }
  }
  ngOnDestroy() {
    this.destroy();
  }
}

I am trying to clear the peer/connection via the "destroy()" method, and it is being run each time this component closes.
Please tell me what I am doing wrong in terms of closing and re-initializing the peer connection. Thanks.

karuppiah7890 commented 7 years ago

Looks like many are having problems with reinitializing the peer object. You still having the problem ?

smatthews1999 commented 7 years ago

Yes I was, but I am no longer using simple-peer, and went with straight Web-RTC. Sorry for not following up.

karuppiah7890 commented 7 years ago

@smatthews1999 Woah! So, you couldn't actually solve the issue and you went on to implement the whole WebRTC stuff ? It's pretty heavy lifting code. But not complex though.

smatthews1999 commented 7 years ago

In all honesty I am not really sure that there was a problem with simplepeer. I didn't understand how WebRTC worked and so I felt I needed to learn it. It could have been that I was just doing it wrong.
I wanted to make use of Edge browsers. I know they don't support data channel but they do support the video/audio stuff.

karuppiah7890 commented 7 years ago

Yeah, I get it. But then, your problem sounded quite simple. Just destroying the current object and reusing the variable name to refer to a new object. So, I don't know if it was really a problem in your code. I am asking because I am planning to use simple-peer, though I recently learned the whole webrtc connection details, but it's some heavy lifting. and I still need to get my head around it, with some more details. And actually, for my use case, there is isn't any need to reconnect, but then, I was just curious and felt that this should be possible, and that I might need it sometime.

smatthews1999 commented 7 years ago

Web RTC is really not so bad.. only slightly more complex than simple-peer. I would probably have no issues using it again. My problem is that it "black-boxed" a lot of what was going on and so I was lost as to how Web RTC worked in the first place. This post was a big help... https://shanetully.com/2014/09/a-dead-simple-webrtc-example/ ...and again, you won't get Edge b/c simple-peer just excludes it.

karuppiah7890 commented 7 years ago

Oh! How does edge get excluded ? I mean, it's all the same APIs, no ?

And thanks for the share. Will check on it the next time I try the whole webrtc code again. For now, I have some idea of what is going on behind the simple-peer API and things are working quite fine.

And I guess I should consider the Edge thingy, though I don't care much about that browser.

smatthews1999 commented 7 years ago

Edge has it's own Object RTC, but it does work with the standard video/audio negotiation and streaming. It does not have the data channels and so simple-peer excludes it. Not sure why.

karuppiah7890 commented 7 years ago

Ah, yeah, I have heard about that somewhere. Edge not having RTCDataChannels. Thanks for the info! :smile:

feross commented 7 years ago

The Edge team is in the process of implementing the so-called WebRTC 1.0 API, in addition to the oRTC APIs they already support.

Once they ship WebRTC 1.0 support, simple-peer should just work with Edge.

You can follow the status here: https://developer.microsoft.com/en-us/microsoft-edge/platform/status/webrtcwebrtcv10api/?q=webrtc

karuppiah7890 commented 7 years ago

:+1:

popkinj commented 7 years ago

I'm struggling with this same issue and haven't found a solution yet.

I have a test page which is similar to this example but I've added two buttons. One starts and streams audio. The other stops it.

If I click start, audio streams successfully. Clicking stop does exactly that. Then when I click start again I get the same error listed above.

Uncaught Error: cannot signal after peer is destroyed

It almost seems that the p.destroy() function is not shutting the connection down completely.

broadcast = function (stream) {
  p = new SimplePeer({
    initiator: true, stream: stream, trickle: false
  });
  p.on("error", function (err) {console.error(err);});
  p.on("signal", function (conn) {
    document.querySelector("#outgoing-connection-string")
      .textContent = JSON.stringify(conn)
  });

  document.querySelector("form#stop-sending-audio").
    .addEventListener("submit", function(event) {
      stream.getAudioTracks()[0].stop() // Stop the microphone
      p.destroy() # Stop the WebRTC connection
  });
};

document.querySelector("form#send-audio").
  .addEventListener("submit", function(event) {
    conditions = {video: false, audio: true}; 
    navigator.getUserMedia(conditions,broadcast,function(){});
}); 

Any thoughts or tips would be greatly appreciated. ☺ And thanks for the library @feross .