simple-peer icon indicating copy to clipboard operation
simple-peer copied to clipboard

Allow connection between Peers even if one is sending an empty or no stream object

Open marduzca opened this issue 4 years ago • 18 comments

Currently my connection between peers only work if for instance both send the same type of stream (e.g. video). In a case scenario in which a main user wants to broadcast its video to others, you don't want the others to have to send video back, at least you would want to be able to return an empty stream to not saturate the bandwidth with unnecessary data. Maybe you can already do this somehow, but at least in my case it didn't work with any of the ways I tried. Thank you!

marduzca avatar Aug 14 '20 08:08 marduzca

Just don't specify stream on one of the sides. Send-only and receive-only connections are quite popular with WebRTC and are supported by simple-peer, so it should just work.

In case it doesn't, you need to debug why that happens exactly and where. It sounds very suspicious if it works with streams both ways, but doesn't with one-way.

nazar-pc avatar Aug 14 '20 09:08 nazar-pc

I somehow constantly get an error if I do that On the side of the broadcaster I get two signals returned from the client that just joined and following error:

index.js:17 Uncaught Error: [object RTCErrorEvent]
    at makeError (index.js:17)
    at RTCDataChannel._channel.onerror (index.js:490)

Any idea what could be wrong?

marduzca avatar Aug 14 '20 11:08 marduzca

Did you try send something bigger than 16kiB over data channel as a single message?

nazar-pc avatar Aug 14 '20 11:08 nazar-pc

Also you probably want to catch that and see what that error event actually is

nazar-pc avatar Aug 14 '20 11:08 nazar-pc

To the first question: I only send a video stream from one side and nothing from the other. I don't even use the data channel

I'm trying to catch the error but I cannot find where it is exactly triggered. Any recommendations where to put it?

To give you some context: The host (broadcaster) wait for clients. When a client connects, it creates the following peer:

const peer = new Peer({
     initiator: true,
     trickle: false,
 });

And sends a signal to the broadcaster. Then the broadcaster receives the signal and creates following peer:

const peer = new Peer({
     initiator: false,
     trickle: false,
     stream: stream
 });

That triggers the double response message and the error I posted earlier.

marduzca avatar Aug 14 '20 13:08 marduzca

Can you please try #722 if it helps?

@t-mullen are there any edge cases when only non-initiator has a stream?

nazar-pc avatar Aug 14 '20 13:08 nazar-pc

You mean to try by making the same changes to the source code?

I now noticed that even if I return an audio stream instead of video I get the same error. Weird.

marduzca avatar Aug 14 '20 14:08 marduzca

Do you mind posting all the signals that are passed into peer.signal()?

t-mullen avatar Aug 14 '20 16:08 t-mullen

Sorry for taking so long for answering, totally forgot I had this issue open..

At the end I managed to make it work. It seems to be possible to have the stream coming only from one side, but only if that peer is the initiator. If the initiator doesn't add the stream to the signal, but the other peer returns one, I run into the previously mentioned problem.

marduzca avatar Sep 16 '20 15:09 marduzca

I have the same problem. Is there any way to start the stream negotiation from a non-initiator? Right now I have solved it by sending a signal to the initiator as to start negotiating but that ads an extra signal that I'm trying to omit.

cliqer avatar Nov 14 '20 13:11 cliqer

I had the same problem as well. When I am adding only Audio on initiator and want to add Audio and Video on non-initiator it does not work. The Offer and Answer had no m=Video section.

But now the Clue! After that, the non-initiater got a new Signal :{ transceiverRequest: Object { kind: "video" } type: "transceiverRequest"} When I am sending this also back to the Initiator. A new offer is generated. With both m=Video and m=Audio. I also tried it with no Stream in initiator. Then the non-initiator will emit twice the "transceiverRequest" with Audio and Video.

Is this the right behavior?

StefanErler avatar Nov 22 '20 20:11 StefanErler

I'm having the same issue, I would like to have one person streaming and the others one viewing the stream, so, the viewer in my case is the initiator, and the streamer is the other peer. When the viewer attempt to connect, it sends the signal but I always get this error from the streamer point of view:

bubbles: false cancelBubble: false cancelable: false code: "ERR_DATA_CHANNEL" composed: false currentTarget: RTCDataChannel {label: "6c5b4f48db1f5e8a9b18c6675c03cd594f4c78ad", ordered: true, maxPacketLifeTime: null, maxRetransmits: null, protocol: "", …} defaultPrevented: false error: RTCError: Transport channel closed eventPhase: 0 isTrusted: true path: [] returnValue: true srcElement: RTCDataChannel {label: "6c5b4f48db1f5e8a9b18c6675c03cd594f4c78ad", ordered: true, maxPacketLifeTime: null, maxRetransmits: null, protocol: "", …} target: RTCDataChannel {label: "6c5b4f48db1f5e8a9b18c6675c03cd594f4c78ad", ordered: true, maxPacketLifeTime: null, maxRetransmits: null, protocol: "", …} timeStamp: 66782.35999995377 type: "error" __proto__: RTCErrorEvent

So I'm not sure if the streamer need to be the initiator and the viewer the other peer. As I understand this is how @marduzca solved de issue.

ajmc90 avatar Nov 27 '20 18:11 ajmc90

I am experiencing the same issue. Setting up a peer with { stream, initiator: true } seems to work, but when answering an offer with a stream without { initiator: true }, the video stream is not working (but the peers are connected and data can be send).

stefanvanherwijnen avatar Dec 07 '20 17:12 stefanvanherwijnen

@stefanvanherwijnen I solved the issue with the solution that @marduzca commented on Sep 16. If one peer have a stream and the other does't not have it, the initiator should be the one that have the stream on it. Hope this help. I did this change and now no errors appears and everything is working good. But I think this is an issue, maybe in the next update someone fix it.

ajmc90 avatar Dec 07 '20 17:12 ajmc90

@ajmc90 Yes, doing it as you explain indeed works, but that's not really a solution. This way one first needs to negotiate which peer contains the stream before connecting them, which I believe shouldn't be required (?). Anyway, it doesn't seem like the issue has been confirmed yet so I thought I'd chip in.

@t-mullen Is there any data I can provide for debugging?

stefanvanherwijnen avatar Dec 07 '20 17:12 stefanvanherwijnen

I was having trouble getting one-way streams working in Safari, and I discovered that I needed to call videoElement.play() to get the video to start playing. Previously I was setting autoplay to true on the video element, but the video only played when the video stream was being sent by both peers.

DePasqualeOrg avatar Aug 29 '22 07:08 DePasqualeOrg

I'm having this kind of problem still. I couldn't get the listener side to work without giving any stream object. When I use an audio tag to provide the media stream, it works on a PC but not with Chrome on iPhone. When I switch back to an audio stream from the microphone, it works.

hankphung avatar Jun 21 '23 08:06 hankphung

I found the solution: when initializing SimplePeer, the initiator can offer not to receive Audio/Video from the other side:

 const peer = new SimplePeer({ initiator: true , offerOptions: { offerToReceiveAudio: false }, trickle: false, realAudioStream });

And receiver:

const peer = new SimplePeer({ initiator: false , trickle: false });
end

hankphung avatar Jun 21 '23 13:06 hankphung