VideoRoom: No JSEP offer received after publisher leaves and rejoins/join when reusing single subscriber PeerConnection (C++)

Hi all,

I’m using the VideoRoom plugin with a custom C++ client (libwebrtc based) application. I’m handling subscriptions using a single subscriber handle and a single RTCPeerConnection, and performing renegotiation whenever new publishers join.

Work Flow:
- I join the room.
- I subscribe to the existing publishers successfully.
- When new publishers join:
- I send a subscribe request.
- Janus sends a JSEP offer.
- I generate an answer.
- Media works correctly.

This works perfectly until a remote publisher leaves.

Problem Scenario

  1. A remote publisher leaves the room.

  2. I receive the leaving event.

  3. I clean up the related remote track/transceiver locally.

  4. I keep using the same subscriber handle and same PeerConnection (no detach, no recreation).

After this, when a new publisher joins:

  • I send a subscribe request.

  • Janus responds with the following event:

  • messageBuffer:{
    “janus”: “event”,
    “session_id”: 5436466648193382,
    “transaction”: “subscribe-276006”,
    “sender”: 2510429578947704,
    “plugindata”: {
    “plugin”: “janus.plugin.videoroom”,
    “data”: {
    “videoroom”: “updating”,
    “room”: 5678
    }
    }
    }

  1. The "Videoroom": "updating" state is received.
  2. No JSEP offer is sent by Janus after this.
  3. Therefore renegotiation cannot proceed.
  4. I am unable to subscribe to any new publishers after the participant leaves.

Questions

  1. After receiving a leaving event, is additional renegotiation required before subscribing to new publishers?

  2. Does the "updating" state mean Janus expects the client to send a new offer instead?

  3. Is reusing a single subscriber PeerConnection for dynamic subscriptions officially supported?

  4. Is it recommended to detach the subscriber handle and create a new one after a publisher leaves?

  5. Could this be related to transceiver/m-line reuse or direction state issues?

Note: I am using same RTCPeerConnection and single subscriber handle.

VideoRoom handles are invalidated after they leave a room. You need to create a new one.

Edit: apologies, I misread the post. I thought you meant you had the subscriber handle leave and then renegotiate. For the use case where publishers leave, you’ll receive an event about that, allowing you to update the subscriber WebRTC connection if required with a renegotiation. No need to rejoin. See the existing multistream VideoRoom demo to see how that works.

I don’t think that’s needed, our demo doesn’t do that. We only do that in response to SDP updates, for subscribers.

Apologies, if my previous explanation may have missed some details — let me clarify the sequence more precisely.

I’m using the VideoRoom plugin of Janus Gateway with a custom C++ (libwebrtc-based) Application. I use:

  • A single subscriber handle.

  • A single RTCPeerConnection.

  • Renegotiation for dynamic subscriptions.


Work Flow

  1. When I join the room initially as a subscriber using join request.

· To get the publishers list in that room ,I joined as an dummy publisher.

· I subscribe to existing publishers in that room successfully, if present, while joining the room,

· Janus responds with an event “attached” to the subscribed publishers

· This “attached” event contains streams and offer.

· I generate an answer for the offer received from Janus .

· I send that answer to janus .

· Janus sends and event for that answer (started : “OK”)

· Media flows correctly.

  1. When a new publisher joins:

· I receive the publishers event (with feed ID, display name, and tracks).

· I send a subscribe request for that publisher’s feed.

· Janus sends an event “updated” which contains streams and JSEP offer for that publisher’s feed.

· I generate an answer for the offer received from Janus .

· I send that answer to janus .

· Janus sends and event for that answer (started : “OK”)

· Media flows correctly.

This works perfectly for the new publishers joining the room subsequently until any of the publisher leaves the room.


Problem Scenario

When a remote publisher leaves:

  1. I receive the leaving event(with feed ID, display name)

  2. After receiving the leaving event, I explicitly unsubscribed the publisher using ‘update’ request containing “unsubscribe” message.

  3. Janus sends an event “updated” for the update request.

  4. I clean up the stored publisher id and its associated tracks .

  5. I continue using the same subscriber handle and same RTCPeerConnection (no detach, no recreation).

Now when a new remote publisher joins:

  1. I receive the publishers event (with feed ID, display name, and tracks).

  2. I send a subscribe request for that new feed.

  3. Janus responds with the given below message

Janus responds with:

{
“janus”: “event”,

“plugindata”: {
“plugin”: “janus.plugin.videoroom”,
“data”: {
“videoroom”: “updating”,
“room”: 5678
}
}
}

I receive “videoroom”: “updating”.

However:

  • No JSEP offer is received from Janus after this.

  • Renegotiation does not proceed.

  • I cannot subscribe to any new publishers after one leaves.(i.e whenever I subscribe. It sends the “updating” event).


Important Clarification

I do receive the correct publishers event when the new remote publisher joins (with feed and track details).

The issue is that when I send subscribe for that feed, Janus goes into “updating” state but does not send an SDP offer — whereas I expect a new offer for renegotiation.


Questions

  1. After receiving a leaving event, is there an additional renegotiation required before subscribing to new remote publisher?

  2. Does “videoroom”: “updating” indicate that Janus expects the subscriber to generate an offer instead?

  3. Is reusing a single subscriber RTCPeerConnection for dynamic subscriptions officially supported?

  4. Could this be related to transceiver/m-line reuse or direction state mismatches?

  5. Is it expected that subscriber-side transceivers should NOT be manually cleaned up on leaving events?

  6. Do I need to send any response for the updating event received after the new publisher joins the room and I send subscribe request.

I’m trying to understand whether this behavior is expected or if I’m breaking the negotiation flow somewhere.

Any clarification would be greatly appreciated.

Note: The entire logic is developed in C++.

Thanks in advance.

As I said in my previous response, you have a better chance of figuring out what’s wrong by trying to replicate the same scenario using the mvideoroomtest.html/.js demo in the browser. Use the webrtc-internals (for WebRTC) and logs (for the API exchanges) to see what’s happening there, and see where it differs from what you’re doing. It definitely works there, so good chances are you’re doing something wrong somewhere.