How to remove a WebRTC track/sender/transceiver from renegotiated SDP?

I have a web app that uses WebRTC to connect to peers, which behaves something like Skype. the onnegotiationneeded event is triggered by adding a DataChannel. The peers are to remain persistently connected, and users can use the DataChannel to signal a “call”. When the signal for a call is accepted by whichever peer it was sent to, the app gets a reference to a local video/audio MediaStream and adds it to the connection using the addTrack method on both sides. When the call is complete, the tracks are removed on both ends via removeTrack. This causes the onnegotiationneeded to be fired again, and the web app will renegotiate the connection with the added tracks.

This is where the problem arises. Everything works great, peers can connect initially, call, hangup, call again, hangup, etc. The problem is that each successive call to addTrack is adding a new Transceiver/Sender/Track which gets appended to the new SDP. Essentially, the SDP eventually becomes very large as a result of carrying the details about now-defunct, previously used transceivers which have a null track.

I’ve been researching a lot, and have come across this list discussion from 2019: https://lists.w3.org/Archives/Public/public-webrtc/2019Feb/0036.html. There is a discussion surrounding the topic, including some points about causing Chrome to crash with a large SDP. The discussion ends with a final message of:

Based on this thread, the issue and PR discussions as well as editor
meetings, we have consensus to remove stopped transceivers
immediately. I will update the PR.

However, this is not the behavior I’m seeing in Firefox. Calling transceiver.stop() does not result in the removal of the transceiver from the next generated SDP, it is still present there. Successive calls will still result in multiple track definitions in the SDP, which continues to grow over time/calls.

I also examined the possibility of simply reusing an existing transceiver if one exists, but I am finding another problem with this approach: replaceTrack does not cause the onTrack event to fire on the receiving end. If I use replaceTrack, the receiver will never know that anything happened. I think replaceTrack is supposed to be used only for replacing tracks in a live context, like the example given in the docs (switching from front camera to back), where the stream is established and ongoing.

My question is this:

What is the proper way to handle repeatedly adding/removing tracks and maintaining a clean, minimal SDP for a persistent WebRTC peer connection in late 2023?