twilio / twilio-video.js

Twilio’s Programmable Video JavaScript SDK
https://www.twilio.com/docs/video/javascript
Other
571 stars 217 forks source link

Client is unable to create or apply a local media description #963

Closed will-ks closed 3 years ago

will-ks commented 4 years ago

Hi all,

For a while now we've been seeing quite a lot of reports of this error:

TwilioError: Client is unable to create or apply a local media description
  at TwilioError(../node_modules/twilio-video/es5/util/twilioerror.js:37:23)
  at new t(../node_modules/twilio-video/es5/util/twilio-video-errors.js:1031:147)
  at ? (../node_modules/twilio-video/es5/signaling/v2/peerconnection.js:519:75)

It seems to have started when we upgraded from twilio-video 2.0.0 to 2.0.1. We're now on 2.3.0 and it's still occurring. It's happening on Edge 80.0.361 and on Chrome 80.0.3987.

I hadn't been able to reproduce it, but today I had it happen on my machine. It caused the call to have no video or audio, although the Twilio room ("RoomSid": "RM5f51ab5a21407e4858f8918b8b3d7d7a") reports tracks added from both participants. When I refreshed the page, everything connected and worked fine.

Console output:

2020-04-21 09:15:29.613Z | WARN in [PeerConnectionV2 #1: 51ada9e3-b3e6-468a-a6c8-5e6185da9dde]: Failed to add RTCIceCandidate "candidate:211156821 1 udp 2122260223 192.168.1.5 64547 typ host generation 0 ufrag HToW network-id 1 network-cost 10": Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
log @ VM207 1.chunk.js:309571
220455:1 Uncaught (in promise) TwilioError: Client is unable to create or apply a local media description
    at MediaClientLocalDescFailedError.TwilioError (http://localhost:3000/static/js/1.chunk.js:313170:23)
    at new MediaClientLocalDescFailedError (http://localhost:3000/static/js/1.chunk.js:312871:147)
    at http://localhost:3000/static/js/1.chunk.js:298596:75
    at async Promise.all (index 0)
    at async Promise.all (index 0)
VM207 1.chunk.js:309571 2020-04-21 09:15:29.805Z | WARN in [PeerConnectionV2 #1: 51ada9e3-b3e6-468a-a6c8-5e6185da9dde]: Failed to add RTCIceCandidate "candidate:2781507712 1 udp 1686052607 83.137.6.171 47887 typ srflx raddr 192.168.1.5 rport 64547 generation 0 ufrag HToW network-id 1 network-cost 10": Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
log @ VM207 1.chunk.js:309571
VM207 1.chunk.js:309571 2020-04-21 09:15:29.806Z | WARN in [PeerConnectionV2 #1: 51ada9e3-b3e6-468a-a6c8-5e6185da9dde]: Failed to add RTCIceCandidate "candidate:1566703641 1 udp 41885695 18.195.48.254 13605 typ relay raddr 83.137.6.171 rport 47887 generation 0 ufrag HToW network-id 1 network-cost 10": Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
log @ VM207 1.chunk.js:309571
VM207 1.chunk.js:309571 2020-04-21 09:15:30.944Z | WARN in [PeerConnectionV2 #1: 51ada9e3-b3e6-468a-a6c8-5e6185da9dde]: Failed to add RTCIceCandidate "candidate:225489308 1 udp 8331007 18.195.48.254 41697 typ relay raddr 83.137.6.171 rport 27802 generation 0 ufrag HToW network-id 1 network-cost 10": Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
log @ VM207 1.chunk.js:309571

Some more room SIDs where the issue occurred:

RMb84cd166ee60d55a607730192b51da36
RM0c6988c2defbee5cd86e94bd1f4d8695
RM4e46d0167e22a65ce68864e9cd0751dd

Software versions:

manjeshbhargav commented 4 years ago

Hi @dambusm ,

I apologize for the delayed response. Can you share the browser console logs for the other Rooms that you have shared in the previous comment? I want to know id you are experiencing any other issues apart from failure to apply RTCIceCandidates.

Thanks,

Manjesh Malavalli JSDK Team

will-ks commented 4 years ago

Hi Manjesh, unfortunately not, those are from our production environment so logging is at a minimum, we just get error reports through Sentry. Before the TwilioError: Client is unable to create or apply a local media description event, the only other Twilio-related breadcrumb is an XMLHttpRequest: POST https://ecs.us1.twilio.com/v2/Configuration [200].

I have 266 Sentry reports of this issue from many different users, if it would help to have more room SIDs let me know and I'll collect them.

manjeshbhargav commented 4 years ago

Hi @dambusm ,

If you can get me those Room SIDs, that would be great. I'm curious to know if your issue is only with RTCIceCandidates, or the SDPs themselves.

Thanks,

Manjesh Malavalli JSDK Team

manjeshbhargav commented 4 years ago

Hi @dambusm ,

I'm still trying to reproduce your issue, but have not been successful so far. I did notice that you are joining the Room with no tracks and publishing audio, video and data tracks one after the other. You can establish media connections faster by passing those tracks in ConnectOptions.tracks. Please let me know if this helps, and if this results in the SDP error not happening anymore.

Thanks,

Manjesh Malavalli JSDK Team

will-ks commented 4 years ago

Sorry for the late response, here are some more room SIDs where the issue occurred:

RMf8a7bb7b638d65a76183f316dc82bcdc
RM5152f033a3e59db3ed426294445b94a2
RMb3671c7e7d7f751038232e23088209d0
RMd1d6b1dd1a1beb84070c4fb23fe44b8e
RM0c21413e97385648de97fa2b76ced032
RMd0ebaae0493364a3d147530aa7e27432
RMb514d6edda81bc72103fde91259ccd09
RM23c7794e7a3d08cd03eb5c887a8b436b
RM45a301fc47b08eae94731f0ad1dfea51
RM3cf797f91d4187dbf06d4634bcbfdcdd
RM143c960dc31c3722319cdc23326b27be
RM63c35fa4dc7179e6bf50e8be324d3c21
RM5a050978215a008c80626f6c2cb1b5d0
RMb84cd166ee60d55a607730192b51da36
RM0efd024a5305f45c0ceac47a9414db2d
RMd3af65af81ed82df15ba5327464e30a1
RM957de7c285423189baa949104fec241c
RM3281cbbfbe921a1285879b48735f6dde
RMba9824fa667e6051203131fc92a39a57
RMd87a525757a649a4eb735bd806c11ea2
RMd1d359bd58e4e5ef35c0d1b59cfcd45f
RM2818a76d6f298ae03d75d1eed87c3539
RM3b5dbffb4a7064eb13bc6210fefcc971
RM4e2f65e9e3a0ea0026769318ab111527
RMef091829ea7f220bf8d802c191f95ce5
RMd0e1dcfd9feadb45fa6fe7a38c5b8ddc
RM8521fe579f3c2f0d1a366142bc1649d0
RM030f38f3d16f45e5816d1b45fd9e5ef7
RM30fac705687f9bc36a99004d7395e69c
RMf9b3972c89a5ecc2a5d7fde225414991
RMbfc1c3ee7e39057e2f3234f0f7964800
RM4f5b33f2b5f684b4ff3502d90b716e13

I will see if we can try changing to initializing the tracks in .connect

jazibjohar commented 4 years ago

I am also seeing this same issue on chrome and firefox. Please see the log below

2020-05-08 05:47:09.165Z | INFO in [connect #1]: Connecting to a Room
log.js?4b71:138 2020-05-08 05:47:09.165Z | DEBUG in [connect #1]: Options: {wsServer: "wss://global.vss.twilio.com/signaling", abortOnIceServersTimeout: false, automaticSubscription: true, dominantSpeaker: false, createLocalTracks: ƒ, …}
log.js?4b71:138 2020-05-08 05:47:09.166Z | INFO in [NTSIceServerSource #1]: Created a new NTSIceServerSource
log.js?4b71:138 2020-05-08 05:47:09.167Z | DEBUG in [NTSIceServerSource #1]: ECS server: https://ecs.us1.twilio.com
log.js?4b71:138 2020-05-08 05:47:09.167Z | INFO in [connect #1]: LocalTracks were not provided, so they will be acquired automatically before connecting to the Room. LocalTracks will be released if connecting to the Room fails or if the Room is disconnected
log.js?4b71:138 2020-05-08 05:47:09.633Z | INFO in [createLocalTracks #1]: Call to getUserMedia successful; got MediaStreamTracks: (2) [MediaStreamTrack, MediaStreamTrack]
log.js?4b71:138 2020-05-08 05:47:09.634Z | DEBUG in [LocalAudioTrack #1: undefined]: Initializing
log.js?4b71:138 2020-05-08 05:47:09.636Z | DEBUG in [LocalVideoTrack #2: undefined]: Initializing
log.js?4b71:138 2020-05-08 05:47:09.637Z | DEBUG in [connect #1]: Creating a new LocalParticipant: LocalParticipantV2 {_events: {…}, _eventsCount: 1, _maxListeners: undefined, …}
log.js?4b71:138 2020-05-08 05:47:09.638Z | INFO in [LocalParticipant #1]: Created a new Participant
log.js?4b71:138 2020-05-08 05:47:09.639Z | INFO in [LocalParticipant #1]: Added a new LocalAudioTrack: 7002d3ae-ed7f-415b-a345-ee243d279304
log.js?4b71:138 2020-05-08 05:47:09.640Z | DEBUG in [LocalParticipant #1]: LocalAudioTrack: LocalAudioTrack {kind: "audio", name: "7002d3ae-ed7f-415b-a345-ee243d279304", mediaStreamTrack: MediaStreamTrack, id: "7002d3ae-ed7f-415b-a345-ee243d279304", …}
log.js?4b71:138 2020-05-08 05:47:09.640Z | INFO in [LocalParticipant #1]: Added a new LocalVideoTrack: c166d842-3601-40c6-b3cf-2c0826bb1d32
log.js?4b71:138 2020-05-08 05:47:09.640Z | DEBUG in [LocalParticipant #1]: LocalVideoTrack: LocalVideoTrack {kind: "video", name: "c166d842-3601-40c6-b3cf-2c0826bb1d32", mediaStreamTrack: MediaStreamTrack, dimensions: {…}, …}
log.js?4b71:138 2020-05-08 05:47:09.641Z | INFO in [connect #1]: Getting ICE servers
log.js?4b71:138 2020-05-08 05:47:09.641Z | DEBUG in [connect #1]: Options: {wsServer: "wss://global.vss.twilio.com/signaling", abortOnIceServersTimeout: false, automaticSubscription: true, dominantSpeaker: false, createLocalTracks: ƒ, …}
log.js?4b71:138 2020-05-08 05:47:09.641Z | INFO in [NTSIceServerSource #1]: Starting
log.js?4b71:138 2020-05-08 05:47:09.641Z | DEBUG in [NTSIceServerSource #1]: Getting ECS configuration
log.js?4b71:138 2020-05-08 05:47:09.645Z | DEBUG in [LocalAudioTrack #1: 7002d3ae-ed7f-415b-a345-ee243d279304]: Started
log.js?4b71:138 2020-05-08 05:47:10.193Z | INFO in [NTSIceServerSource #1]: Got ICE servers: [{"urls":"turn:global.turn.twilio.com:3478?transport=udp","username":"d833c87ec72341b93c3a7017e01cf41db0530b995ad9472696d98afd0fff8fd7","credential":"wTd2hnB/Kx9mtEaW7+c0+GL9bNMupV2rF/G8pAmz8JY="},{"urls":"turns:global.turn.twilio.com:443?transport=tcp","username":"d833c87ec72341b93c3a7017e01cf41db0530b995ad9472696d98afd0fff8fd7","credential":"wTd2hnB/Kx9mtEaW7+c0+GL9bNMupV2rF/G8pAmz8JY="}]
log.js?4b71:138 2020-05-08 05:47:10.194Z | INFO in [NTSIceServerSource #1]: Getting ICE servers again in 14400 seconds
log.js?4b71:138 2020-05-08 05:47:10.194Z | INFO in [connect #1]: Got ICE servers
log.js?4b71:138 2020-05-08 05:47:10.194Z | DEBUG in [connect #1]: ICE servers: (2) [{…}, {…}]
log.js?4b71:138 2020-05-08 05:47:10.194Z | DEBUG in [connect #1]: Creating a new RoomSignaling
log.js?4b71:138 2020-05-08 05:47:10.194Z | DEBUG in [connect #1]: RoomSignaling params: {token: "eyJhbGciOiJIUzI1NiIsImN0eSI6InR3aWxpby1mcGE7dj0xIi…zgifQ.N1mGpCpXOzDsEIYl1dPUbfEqqghoq87vcpPZ-A0fPy0"}
log.js?4b71:138 2020-05-08 05:47:10.208Z | INFO in [NTSIceServerSource #1]: Stopping
log.js?4b71:138 2020-05-08 05:47:10.208Z | DEBUG in [NTSIceServerSource #1]: Stopped
log.js?4b71:138 2020-05-08 05:47:10.211Z | INFO in [connect #1]: The automatically acquired LocalTracks will now be stopped
log.js?4b71:138 2020-05-08 05:47:10.211Z | INFO in [LocalAudioTrack #1: 7002d3ae-ed7f-415b-a345-ee243d279304]: Stopping
log.js?4b71:138 2020-05-08 05:47:10.212Z | DEBUG in [LocalAudioTrack #1: 7002d3ae-ed7f-415b-a345-ee243d279304]: Ended
log.js?4b71:138 2020-05-08 05:47:10.213Z | INFO in [LocalVideoTrack #2: c166d842-3601-40c6-b3cf-2c0826bb1d32]: Stopping
log.js?4b71:138 2020-05-08 05:47:10.214Z | DEBUG in [LocalVideoTrack #2: c166d842-3601-40c6-b3cf-2c0826bb1d32]: Ended
log.js?4b71:138 2020-05-08 05:47:10.214Z | INFO in [connect #1]: Error while connecting to a Room: TwilioError: Client is unable to create or apply a local media description
    at MediaClientLocalDescFailedError.TwilioError (webpack-internal:///SAu+:37:23)
    at new MediaClientLocalDescFailedError (webpack-internal:///5wwa:1031:147)
    at eval (webpack-internal:///d6fC:975:15)
    at invokeCallback (webpack-internal:///E2g8:407:15)
    at publish (webpack-internal:///E2g8:390:7)
    at publishRejection (webpack-internal:///E2g8:331:3)
    at MutationObserver.flush (webpack-internal:///E2g8:127:5)

Browser(s): Chrome 81.0.4044.129 Operating System: MacOS 10.15.4 twilio-video.js:2.4.0 Third-party libraries (e.g., Angular, React, etc.): React 16.13, Webpack 4

sboudouk commented 4 years ago

Have the same issues as @jazibjohar and @dambusm here.

I tried downgrading to 1.X but it does not help. 2.0 and 2.4 give me the same results.

hthetiot commented 4 years ago

We also have the same issue with cordova-plugin-iosrtc when using Twilio-Video.js that result into black video on iOS side.

See dedicated cordova-plugin-iosrtc issue here: https://github.com/cordova-rtc/cordova-plugin-iosrtc/issues/497

Notice that using following libraries / webrtc solutions instead of Twilio-video.js work perfectly with cordova-plugin-iosrtc.

Therefor I strongly beleive the issue is in Twilio-Video.js itself.

Example Source:

<!DOCTYPE HTML>
<html>
    <head>
        <title>
            Twilio Video Room
        </title>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: wss://* https://* 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *">
    </head>
    <body>
        <div id="local-media"></div>
        <div id="remote-media"></div>
        <script type="text/javascript" src="cordova.js"></script>
        <!--<script src="https://media.twiliocdn.com/sdk/js/video/releases/2.4.0/twilio-video.js"></script>-->
        <script type="text/javascript">

        function connect() {
            const TWILIO_ROOM = 'test'
            const TWILIO_TOKEN = '<YOUR_TOKEN>';

            // We load twilio-video after cordova-plugin-iosrtc
            // because twilio-video reference WebRTC globals and keep reference
            loadScript('https://media.twiliocdn.com/sdk/js/video/releases/2.4.0/twilio-video.js').then(function () {
                joinRoom({
                    token: TWILIO_TOKEN,
                    room: TWILIO_ROOM
                });
            });
        }

        var scriptUrls = [];
        function loadScript(scriptUrl) {

            if (scriptUrls[scriptUrl]) {
                return Promise.resolve(scriptUrl);
            }

            return new Promise(function(resolve, reject) {
                // load adapter.js
                var script = document.createElement("script");
                script.type = "text/javascript";
                script.src = scriptUrl;
                script.async = false;
                document.getElementsByTagName("head")[0].appendChild(script);
                script.onload = function() {
                    scriptUrls[scriptUrl] = true;
                    console.debug('loadScript.loaded', script.src);
                    resolve(scriptUrl);
                };
            });
        }

        function joinRoom(result) {

            const Video = Twilio.Video;
            Video.createLocalTracks().then(localTracks => {
                const localMediaContainer = document.getElementById('local-media');

                Array.from(localTracks.values()).forEach(function (track) {
                    localMediaContainer.appendChild(track.attach());
                });

                return localTracks;
            }).then(function (localTracks) {

                Video.connect(result.token, {
                    name: result.room,
                    //sdpSemantics: 'plan-b',
                    //bundlePolicy: 'max-compat',
                    tracks: localTracks,
                }).then(room => {
                    console.log(`Successfully joined a Room: ${room}`);

                    // Attach the Tracks of the Room's Participants.
                    var remoteMediaContainer = document.getElementById('remote-media');
                        room.participants.forEach(function(participant) {
                        console.log("Already in Room: '" + participant.identity + "'");
                        participantConnected(participant, remoteMediaContainer);
                    });

                    room.on('participantConnected', participant => {
                        console.log(`A remote Participant connected: ${participant}`);
                        participantConnected(participant);
                    });

                    room.on('participantDisconnected', participant => {
                        console.log(`A remote Participant connected: ${participant}`);
                        participantDisconnected(participant);
                    });

                }, error => {
                    console.error(`Unable to connect to Room: ${error.message}`);
                });

                function participantConnected(participant) {
                    console.log('Participant "%s" connected', participant.identity);
                    const div = document.createElement('div');
                    div.id = participant.sid;
                    participant.on('trackSubscribed', (track) => {
                        trackSubscribed(div, track)
                    });
                    participant.on('trackUnsubscribed', trackUnsubscribed);
                    participant.tracks.forEach(publication => {
                        if (publication.isSubscribed) {
                            trackSubscribed(div, publication.track);
                        }
                    });

                    document.getElementById('remote-media').appendChild(div);
                }

                function participantDisconnected(participant) {
                    console.log('Participant "%s" disconnected', participant.identity);

                    var div = document.getElementById(participant.sid)
                    if (div) {
                        div.remove();
                    }
                }

                function trackSubscribed(div, track) {
                    div.appendChild(track.attach());
                }

                function trackUnsubscribed(track) {
                    track.detach().forEach(element => element.remove());
                }
            });
        }

        // Detect if current enviroment is cordova
        var isCordova = !document.URL.includes('http');

        // Regular Browser, no cordova
        if (!isCordova) {
            connect();

        // Handle Cordova and enable cordova.plugins.iosrtc
        } else {

            document.addEventListener('deviceready', function () {
                // Note: This allow this sample to run on any Browser
                if (cordova && cordova.plugins && cordova.plugins.iosrtc) {

                    // Expose WebRTC and GetUserMedia SHIM as Globals (Optional)
                    // Alternatively WebRTC API will be inside cordova.plugins.iosrtc namespace
                    cordova.plugins.iosrtc.registerGlobals();

                    // Enable iosrtc debug (Optional)
                    cordova.plugins.iosrtc.debug.enable('*', true);
                }

                connect();
            }, false);
        }
        </script>
    </body>
</html>

Video is received on Chrome from iOS but iOS does not receive/display Chrome video.

Image from iOS

Cordova-plugin-iosrtc Logs Capture via Safari Remote Debug.

Screen Shot 2020-05-26 at 8 35 42 PM

Note: the error Unhandled Promise Rejection: TwilioError: Client is unable to create or apply a local media description was fixed (https://github.com/cordova-rtc/cordova-plugin-iosrtc/commit/403284a0909cbc62edd9e47689fd2dadccc1a636) due following error that is now fixed on iosrtc but still result in black remote video: unnamed

manjeshbhargav commented 4 years ago

Hi @hthetiot ,

We currently do not support cordova. Please take a look at the currently supported browsers.

Thanks,

Manjesh Malavalli JSDK Team

hthetiot commented 4 years ago

Hi @hthetiot ,

We currently do not support cordova. Please take a look at the currently supported browsers.

Thanks,

Manjesh Malavalli JSDK Team

@manjeshbhargav You do now via Cordova-plugin-iosrtc@6.0.12 that I maintain ;) https://github.com/cordova-rtc/cordova-plugin-iosrtc/issues/497#issuecomment-639494815

dandoyon commented 4 years ago

Just throwing this out there, but we found that using require to load twilio seemed to be the issue and instead we are using old-school use of sdk.

PimentaLucas commented 4 years ago

Hello @dandoyon , could you explain better how you fixed this issue? I'm getting this same error in my project.

Thanks in advice

abeythomas-bhs commented 4 years ago

Facing this issue in safari/ chrome in both ios and android as well still. Any workaround please?

grant-with commented 3 years ago

I've been able to reproduce this consistently when I have a tab open and connected to a Room, then I put my laptop to sleep (or otherwise disconnect), and wake it up again. Upon returning, any attempt to publish a track results in this error.

What's interesting is the disconnected event doesn't fire in the Room, only this warning is logged after I activate sleep:

2020-11-09 14:57:35.775Z | WARN in [TwilioConnection #1: wss://global.vss.twilio.com/signaling]: Closed: 1006 - 

Without a disconnect event it's hard to anticipate this situation.

Update: it also doesn't appear to be possible to catch this error to handle it. It appears to be thrown from a separate task.

Here's the code I have which is triggering the problem after I come back from sleep:

      console.debug('Publishing video');
      const vidOpts = previousDeviceIdRef.current
        ? {
            deviceId: { exact: previousDeviceIdRef.current },
          }
        : {};
      try {
        const track = await getLocalVideoTrack(vidOpts);
        await localParticipant?.publishTrack(track, { priority: 'low' });
        console.debug('Video published');
      } catch (err) {
        console.error('Error publishing video:', err);
        debugger;
      } finally {
        console.debug('finally');
      }

What's bizarre to me is that none of the blocks shown here finish and log. try, catch, even finally - the code never reaches the end. Maybe I'm missing something, but I'm not even sure how you do that.

grant-with commented 3 years ago

Another note on this: since the error is thrown in a Promise, it doesn't seem possible for the user to catch it and handle it today.

Uncaught (in promise) TwilioError: Client is unable to create or apply a local media description
    at t (.../static/js/2.0db8700d.chunk.js:2:1975484)
    at new t (.../static/js/2.0db8700d.chunk.js:2:317184)
    at .../static/js/2.0db8700d.chunk.js:2:1954937

Now, the only way I know you could possibly run code in a try/catch/finally block and have none of the branches return - would be to never resolve a Promise. That might be what's happening here.

publishTrack is already returning a Promise (which I am awaiting). What might need to happen is some internal SDK refactoring to ensure it's really awaiting all subsequent effects and bubbling up their thrown errors to the caller. It looks like (perhaps due to some event-based logic) you are triggering a side-effect out-of-band with the original function invocation, which results in an error being emitted to nowhere.

From looking at the code I see a few ways this might happen. The main issue is that the publishTrack promise is dependent upon an event updated firing on trackSignaling. So the first potential issue is that if that event never fires, it will never resolve.

Digging in further, there is at least one branch within the Promise which will neither call resolve nor reject, thus suspending it forever:

https://github.com/twilio/twilio-video.js/blob/master/lib/localparticipant.js#L297

That appears to be the only branch that would do that, and I'm guessing the condition is unlikely or maybe impossible in practical use, so probably a red herring. I would guess the main problem is that the error we're talking about (unable to create or apply ...) is preventing the updated event from firing and stalling out publishTrack.

Potential high-level solution: in addition to subscribing to updated on trackSignaling, register a timeout (it can be reasonably long) to reject the promise with a timeout error. This is a pretty reasonable thing to do and will help clean up in a disaster situation such as we're seeing right now.

From there, you could figure out how to ensure that the error in question is correctly propagated back to the caller of publishTrack.

Personally, I will be wrapping my invocation of publishTrack in a timeout of my own just to mitigate this, for now. I'd recommend others try it as well - if I find a more reliable way to detect the error I will post it here.

will-ks commented 3 years ago

I just did a fresh checkout of the twilio-video.js master and tried to build it, and the mocha tests are failing with the 'Client is unable to create or apply a local media description' error, consistently.

  3202 passing (10s)
  2 failing

  1) PeerConnectionV2 .connectionState equals "failed" when IceConnectionMonitor detects failures, also emits "connectionStateChanged":
     Uncaught TwilioError: Client is unable to create or apply a local media description
      at new TwilioError (lib/util/twilioerror.js:9:274)
      at new MediaClientLocalDescFailedError (lib/util/twilio-video-errors.js:9:19652)
      at lib/signaling/v2/peerconnection.js:9:35408

  2) PeerConnectionV2 "after each" hook for "equals "failed" when IceConnectionMonitor detects failures, also emits "connectionStateChanged"":
     TypeError: IceConnectionMonitor.prototype.start.restore is not a function
      at Context.<anonymous> (test/unit/spec/signaling/v2/peerconnection.js:36:42)
      at processImmediate (node:internal/timers:463:21)
makarandp0 commented 3 years ago

Hey @dambusm, Thank you for writing about these error - Can you please share the version of browser and os that you see these unit test failures on? I am not seeing this on MacOS 10.14.6 + Chrome 86/87.

Thanks, Makarand

will-ks commented 3 years ago

Hi @makarandp0, I am running MacOS 10.15.7. As far as I can tell, the error occurs when the unit tests are running in Node (v15.3), not in browser. Specifically, the build script fails during running the 'cover' script.

"cover": "istanbul cover node_modules/mocha/bin/_mocha -- ./test/unit/index.js"

Running just the mocha tests with npm run test:unit gives the same result. I haven't tried running the integration tests in a real browser yet.

maximilianvp commented 3 years ago

This fixes it for us: https://github.com/twilio/twilio-video.js/pull/1405

makarandp0 commented 3 years ago

Hey @maximilianvp - Thank you for putting up this Pull request. But I am very curious about why this change fixes anything.

Looks like Promise.all does take iterable as an input, and sure enough I see that following code works fine. I tried on chrome, firefox and safari.

Promise.all((new Map()).values()).then(()=> console.log('yep')) 

Are you using some pollyfill that overrides Promise apis ?

Thanks, Makarand

cammil commented 3 years ago

I'm getting this error too. Is there any information I can post here that might help to debug it?

a-type commented 3 years ago

I never provided a workaround code sample (posting as @grant-with) - here's what I'd recommend for catching this error and recovering from it (perhaps prompt the user to turn on their device again or refresh the page).

const timeout = setTimeout(() => {
  console.error('Track publish timed out!');
  showErrorToUser(); // you decide what to do if publishing times out
}, 10000); // 10 second timeout on publish
const stopTimeout = () => clearTimeout(timeout);
await localParticipant.publishTrack(track).finally(stopTimeout);
console.log('Track was published successfully');

Because there is no way to otherwise catch and handle this error and the publishTrack() promise never resolves (as I mentioned in my last comment), a "race" with a timeout is the only feasible solution I can think of until this bug is fixed. Fortunately it's not that hard to implement as shown. UX suffers a bit because the user will have to wait 10 seconds to be informed that there is a problem, but you can tune that value how you like. Be warned that if you set it too low, a legitimate track publication could 'time out' on a slow network connection or device.

makarandp0 commented 3 years ago

Hello @cammil & @maximilianvp

We heard report that some developers resolved this issue by removing "es6-promise-promise".

Can you please see if that works for you as well?

@maximilianvp, I suspect issue with promise polly fill since you mentioned this:

This fixes it for us: #1405

Thanks, Makarand

a-type commented 3 years ago

We experience this problem and are not using a specific Promise polyfill - we build our app from one of the Twilio starter kits based on Create React App.

makarandp0 commented 3 years ago

Hello @a-type

I think there are couple of different issues that are cross posted here. I do not think promise polyfill apply to your case. I think in your case you are seeing a race condition where a track is published after the room lost network connection, then the promise returned by publishTrack never resolves. Thank you for posting the workaround - it does make sense to me.

Unfortunately, I have not been able to reproduce your scenario. I turn off network and publish a track and then after a while re-enabled network, I see the publish track promise resolve eventually. I do not to see "client is unable to create or apply local media description" on my console.

Can you provide more detailed steps for reproducing the issue where promise does not resolve.

Thanks, Makarand

a-type commented 3 years ago

Thanks for the response. The track publish occurs after the computer goes to sleep and comes back. This is reproduced at least on a 2019 Macbook.

yulllll commented 3 years ago

Hello, I found the reason of problem in webrtc-adapter dependency. Fixed in version https://github.com/webrtcHacks/adapter/releases/tag/v7.7.1

makarandp0 commented 3 years ago

Thank you @yulllll for posting the workaround.

Hey @a-type, Unfortunately, I still couldn't reproduce the track publish issue you mentioned. I bet it involves a specific timing publishing a track after computer comes back from sleep. If you encounter this issue again - Please post console logs - hopefully that would give us clues on why track publish promise stays unresolved.

This old thread has been reused for many different issues, and it's getting very confusing. I am going to close this thread. Please open a new issue if your issue is still not resolved with the workarounds posted here and here.

Thanks, Makarand

cindyloo commented 2 years ago

1504

cindyloo commented 2 years ago

https://github.com/twilio/twilio-video.js/issues/1856