Search code examples
twiliotwilio-functionstwilio-video

Twilio Video - switch media devices option not working


I am using twilio with twilio-video v beta-2 counting on the master branch of this repohttps://github.com/twilio/video-quickstart-js
I got to display the select media and push the devices into it but when I am trying to updateVideoDevice I got an error

updateVideoDevice error TypeError: track must be a LocalAudioTrack, LocalVideoTrack, LocalDataTrack, or MediaStreamTrack
at Object.INVALID_TYPE (index.js:30952)
at Object.validateLocalTrack (index.js:31469)
at LocalParticipant.unpublishTrack (index.js:17047)
at index.js:17096
at Array.reduce (<anonymous>)
at LocalParticipant.unpublishTracks (index.js:17095)
at index.js:36056

my updateVideoDevice function is as the following

function updateVideoDevice(event) {
const select = event.target;
const localParticipant = room.localParticipant;
if (select.value !== '') {
    Video.createLocalVideoTrack({
        deviceId: { exact: select.value }
    }).then(function(localVideoTrack) {
        const tracks = Array.from(localParticipant.videoTracks.values());
        localParticipant.unpublishTracks(tracks);
        log(localParticipant.identity + " removed track: " + tracks[0].kind);
        detachTracks(tracks);

        localParticipant.publishTrack(localVideoTrack);
        log(localParticipant.identity + " added track: " + localVideoTrack.kind);
        const previewContainer = document.getElementById('local-media');
        attachTracks([localVideoTrack], previewContainer);
    })
    .catch(error => {
        console.error('updateVideoDevice error' ,error);
    });
}
}

can any one explain what I am doing wrong?


Solution

  • Twilio developer evangelist here.

    This looks to be a breaking change between Twilio Video JS v1 and v2. In the v2 documentation, calling localParticipant.videoTracks returns a Map of <Track.SID, LocalVideoTrackPublication>. Calling .values() on that map returns an iterator of LocalVideoTrackPublications which is then turned to an array using Array.from.

    The issue is that you then pass that array of LocalVideoTrackPublications to localParticipant.unpublishTracks(tracks); which causes the error because unpublishTracks expects an array of LocalTracks not LocalVideoTrackPublications.

    You could fix this by mapping over the publications and returning the track property:

    const tracks = Array.from(localParticipant.videoTracks.values())
                     .map(publication => publication.track);
    

    Let me know if that helps.