Twilio-video.js: Chrome not displaying remoteVideo from ios safari

Created on 27 Mar 2020  Â·  42Comments  Â·  Source: twilio/twilio-video.js

  • [X] I have verified that the issue occurs with the latest twilio-video.js release and is not marked as a known issue in the CHANGELOG.md.
  • [X] I reviewed the Common Issues and open GitHub issues and verified that this report represents a potentially new issue.
  • [ ] I verified that the Quickstart application works in my environment.
  • [X] I am not sharing any Personally Identifiable Information (PII)
    or sensitive account information (API keys, credentials, etc.) when reporting this issue.

This works just fine on chrome to chrome. After spending a long time hunting I was finally able to get ios safari to display the remote video of chrome, but I cannot seem to figure out why chrome can't display safari's remote video.

From what the logs are showing, the remoteVideo track coming over from Safari is null and its width and height it set to 0. I'm assuming this means that it never subscribed?

Any help would be greatly appreciated, and if there is more information I can provide please let me know.

Code to reproduce the issue:

localTrackOptions: CreateLocalTracksOptions = {
  audio: true,
  video: { width: 1920, height: 1080, frameRate: 24 }
};

async ngOnInit() {
  this.accessToken = await this.videoService.getTwilioAccessToken();
  this.localMediaTracks = await createLocalTracks(this.localTrackOptions);
  this.startVideo();
}

async startVideo() {
  this.activeRoom = await connect(this.accessToken, { name: 'my-name', tracks: this.localMediaTracks });
  console.log(`Connected to Room: ${this.activeRoom.name} `);

  this.activeRoom.localParticipant.on('trackPublicationFailed', (error, localTrack) => {
    console.warn('Failed to publish LocalTrack "%s": %s', localTrack.name, error.message);
  });

  this.activeRoom.on('trackSubscriptionFailed', (error, remoteTrackPublication, remoteParticipant) => {
    console.warn('Failed to subscribe to RemoteTrack "%s" from RemoteParticipant "%s": %s"',
      remoteTrackPublication.trackName, remoteParticipant.identity, error.message);
  });

  this.activeRoom.localParticipant.videoTracks.forEach((track, trackID) => {
    console.log('track: %o', track);
    const localMediaHtml = document.getElementById('localMedia');
    localMediaHtml.appendChild(this.localMediaTracks[1].attach());
  });

  // Log any Participants already connected to the Room
  this.activeRoom.participants.forEach(participant => {
    console.log(`Participant "${participant.identity}" is connected to the Room`);
    this.participantConnected(participant);
  });

  this.activeRoom.on('participantConnected', (participant) => {
    this.participantConnected(participant);
  });
}

participantConnected(participant) {
  participant.tracks.forEach(publication => {
    this.trackPublished(publication, participant);
  });

  participant.on('trackPublished', publication => {
    this.trackPublished(publication, participant);
  });

  participant.on('trackUnpublished', publication => {
    console.log(`RemoteParticipant ${participant.identity} unpublished a RemoteTrack: ${publication} `);
  });
}

trackPublished(publication, participant) {
  console.log(`RemoteParticipant ${participant.identity} published a RemoteTrack: ${publication} `);
  if (publication.isSubscribed) {
    this.addTrack(publication.track);
  }
  publication.on('subscribed', track => {
    console.log(`LocalParticipant subscribed to a RemoteTrack: ${track} `);
    this.addTrack(track);
  });

  publication.on('unsubscribed', track => {
    console.log(`LocalParticipant unsubscribed from a RemoteTrack: ${track} `);
  });
}

addTrack(track) {
  if (track.kind === 'audio' || track.kind === 'video') {
    const remoteMediaHtml = document.getElementById('remoteMedia');
    remoteMediaHtml.appendChild(track.attach());
  } else if (track.kind === 'data') {
    track.on('message', data => {
      console.log(data);
    });
  }
} 

Expected behavior:
Should be able to see the remote video and hear the remote audio on both Chrome and Safari

Actual behavior:
Can see the Chrome's remote video on ios safari but cannot see Safari's remote video on Chrome
Can hear Safari's remote audio on Chrome

Screen Shot 2020-03-26 at 9 27 06 PM

I also have these in my polyfills.ts

import 'zone.js/dist/zone';  // Included with Angular CLI.
import 'zone.js/dist/zone-patch-user-media';
import 'zone.js/dist/webapis-rtc-peer-connection';

Software versions:

  • [ Chrome 80.0.3987.149 - IOS Safari 13.3.1] Browser(s):
  • [ MacOS - Iphone X] Operating System:
  • [2.2.0] twilio-video.js:
  • [Angular 9] Third-party libraries (e.g., Angular, React, etc.):
Safari iOS

Most helpful comment

@makarandp0 & @JoeDenny FWIW, we were able to work around the Safari bug by setting { width: 720, height: 1440 } (portrait mode on an iPhone in our case) as suggested over in https://github.com/twilio/twilio-video-app-react/issues/147#issuecomment-612775837 . Note the strange aspect ratio of 1:2. I wonder if part of the Safari issue is that it needs to have the native resolution of the camera set?

We're going to later see if we can set a {min,ideal,max} for the height and {min,max} for the aspectRatio and no width to see if we can get Safari to pick something reasonable, but we haven't tried this yet.

All 42 comments

Hi @FXschwartz ,

Thanks for writing in with your issue. I'm not sure you need the Safari hack anymore. Can you try running your application without it and let me know?

Thanks,

Manjesh

@manjeshbhargav Appreciate the response!

I should've added that I've tried it with and without the safari hack. I can remove it above to avoid confusion.

I'm experiencing the same problem when it comes to remoteTracks (video and audio) coming from iOS safari (13), into chrome. Not using any polyfills and with default options both when creating localTracks and connecting to room.

Issue not occurring between Firefox and Chrome (where supported)

[ Chrome 80.0.3987.149 - IOS Safari 13.3.1] Browser(s):
[2.2.0] twilio-video.js: (also 2.3.0)

+1 also experiencing the same issue.

+1 also experiencing the same issue. :(

@manjeshbhargav have you a quick patch to resolve it ?

Hi @VincentSim , @FXschwartz , @lmatheus , @anazar ,

I was curious, you said you could hear Safari's remote audio on Chrome. Can you confirm that you are indeed receiving "trackSubscribed" events for Safari's remote video on Chrome?

Thanks,

Manjesh Malavalli
JSDK Team

@manjeshbhargav Are you talking about this line? If so it looks like the 'trackSubscribed' event is getting called for both the video and audio on chrome. Its just the the video is null and the audio is not.

image

@FXschwartz ,

It looks like you are indeed subscribing to the RemoteVideoTrack (the line after you have printed out the RemoteAudioTrack object). What happens if you attach it to a video element and add it to the DOM?

Thanks,

Manjesh Malavalli
JSDK Team

@manjeshbhargav ,

To put simply nothing. There are no errors saying it failed to subscribe, the video just doesn't show up.

Even attached to the DOM the actual track has null for width and height

I had a similar problem. Try restricting your video stream to be 720p.
I.e.
video: { width: 1280, height: 720, frameRate: 24 }

Hey @FXschwartz, sorry this issue is taking long to get to the resolution.

Is there way I can see the repro for this iOS track not showing up on chrome ? If you have your app deployed somewhere that I can try it would be great.

You can email me the details at [email protected]

Thanks,
Makarand

I have not been able to repro this. I see the tracks from my iPad showing up fine on chrome using same video constraints ({ width: 1920, height: 1080, frameRate: 24 }) .

@VincentSim , @FXschwartz , @lmatheus , @anazar - Does this issue repro consistently for you. if so can you please share your repro steps and any sample code.

Thanks,
Makarand

@makarandp0 I really appreciate your help! I do have it hosted somewhere.

I'll send you an email with the information and invite you to the repo if thats ok?

@makarandp0 Do you think you could share your source code as well? It might be something that we could spot pretty quickly that you are doing differently.

@bwilso65 Funny enough your method works. If I change the video stream to be 720p then the video shows up on chrome.

Why would the quality matter? Obviously it would be great if I could have higher then 720p.

@FXschwartz
No idea why it works. I think something in iOS that prevents higher quality streams from being sent.

Not sure if its a Twilio problem or an iOS problem but would be nice to have it resolved in the future.

@makarandp0 I'm curious if this is a device restraint. Do you have an iphone you could test those video params on and see if it works? I don't have an ipad available.

On my application Iphone and Ipad are not working even this video constraints : video: { width: 1280, height: 720, frameRate: 24 }

@FXschwartz @bwilso65 is it possible to have access to your repo to see what is different ?

@VincentSim
I can't disclose my entire repo, but I can share this snippet.

return Twilio.Video.createLocalTracks({ audio: true, video: { name: 'camera', width: { min: 640, ideal: 1280 }, height: { min: 480, ideal: 720 } } });

That seems to work for the majority of devices I've tested on (including iPhone and iPad)

I have tried both configurations and it still doesn't work :(

const { connect, createLocalTracks } = require('twilio-video');

// Option 1
createLocalTracks({
  audio: true,
  video:  { name: 'camera', width: { min: 640, ideal: 1280 }, height: { min: 480, ideal: 720 } },
}).then(localTracks => {
  return connect('$TOKEN', {
    name: 'my-room-name',
    tracks: localTracks,
  });
}).then(room => {
  console.log(`Connected to Room: ${room.name}`);
});

// Option 2
connect('$TOKEN', {
  audio: true,
  name: 'my-room-name',
  video:  { name: 'camera', width: { min: 640, ideal: 1280 }, height: { min: 480, ideal: 720 } },
}).then(room => {
  console.log(`Connected to Room: ${room.name}`);
});

@VincentSim The code I posted above is my entire video code. The only thing that is not in there is the token creation which shouldn't affect this.

atch @FXschwartz i tried to have same code but it still doesn't work.... always a black video div only

Here is my code.. It works perfectly with other devices
```html.erb

<% content_for(:after_js) do %>


<% end %>
```

@VincentSim, I see a problem with your implementation. its calling Video.createLocalTracks twice.

mobile devices allow only one video track at a time, that means when you call createLocalTracks 2nd time, track obtained from 1st call is not valid anymore. To avoid this you can use the tracks obtained from 1st call to preview local tracks.

Video.createLocalTracks({
      audio: true,
      video: { width: 720, height: 480, frameRate: 24 }
    }).then(localTracks => {
      const localMediaContainer = document.getElementById('local-media');
      localMediaContainer.appendChild(track.attach());
      return Video.connect("<%= @token %>", {
        name: 'my-room-name',
        tracks: localTracks
      });
    }).then(room => {
      console.log(`Connected to Room: ${room.name}`);
      room.on('participantConnected', participant => {
        console.log(`A remote Participant connected: ${participant}`);
      });
    }).catch(error => {
      console.error(`Unable to connect to Room: ${error.message}`);
    });

Alright I found the issue :
I was creating one createLocalTracks for the room and a createLocalVideoTrack for the user to see his face...
It works on desktop but on Ipad or Iphone you can't have both.
This code :

Video.createLocalVideoTrack().then(track => {
        const localMediaContainer = document.getElementById('local-media');
        localMediaContainer.appendChild(track.attach());
      });

Should be :

room.localParticipant.videoTracks.forEach(publication => {
        const localMediaContainer = document.getElementById('local-media');
        localMediaContainer.appendChild(publication.track.attach());
      })

@makarandp0 You're the best ! Thanks

@FXschwartz - I was able to reproduce the issue between safari to safari. Looks like a bug in iOS Safari that it it does not send any packets when video constraints are { width: 1280, height: 720, frameRate: 24 }

This simple html repros it w/o using any of the twilio code.
https://makarandp0.github.io/iosSafariVideoConstraintsIssue.html

When loaded on iOS Safari - remote track does not show up (and no packets are sent on the video track), Changing the video constraints fixes the problem.

I have now filed a bug (https://bugs.webkit.org/show_bug.cgi?id=210393) against safari, and will post here when we have some updates.

Thanks,
Makarand

hey @makarandp0 , I am having the same issue displaying remote video track in iOS safari.

Even when I open up your example repo at https://makarandp0.github.io/iosSafariVideoConstraintsIssue.html and change the video constraints the problem persists.

What video constraints are you using to fix the issue?

@JoeDenny, setting video constraints to { width: 1280, height: 720, frameRate: 24 } fixes the issue for me. You might also want to set it to true to see if it works.

@makarandp0 neither of those work for me. Still getting 0 packetsSent and 0 packetsReceived. I'm on an iPhone 8, IOS Safari 13.3.1. Very strange, not sure what the difference could be..

@makarandp0 & @JoeDenny FWIW, we were able to work around the Safari bug by setting { width: 720, height: 1440 } (portrait mode on an iPhone in our case) as suggested over in https://github.com/twilio/twilio-video-app-react/issues/147#issuecomment-612775837 . Note the strange aspect ratio of 1:2. I wonder if part of the Safari issue is that it needs to have the native resolution of the camera set?

We're going to later see if we can set a {min,ideal,max} for the height and {min,max} for the aspectRatio and no width to see if we can get Safari to pick something reasonable, but we haven't tried this yet.

@all, i'm get the same problem. I run example code of quickstart:
'use strict';

var Video = require('twilio-video');

var activeRoom;
var previewTracks;
var identity;
var roomName;

// Attach the Track to the DOM.
function attachTrack(track, container) {
container.appendChild(track.attach());
}

// Attach array of Tracks to the DOM.
function attachTracks(tracks, container) {
tracks.forEach(function(track) {
attachTrack(track, container);
});
}

// Detach given track from the DOM.
function detachTrack(track) {
track.detach().forEach(function(element) {
element.remove();
});
}

// Appends remoteParticipant name to the DOM.
function appendName(identity, container) {
const name = document.createElement('p');
name.id = participantName-${identity};
name.className = 'instructions';
name.textContent = identity;
container.appendChild(name);
}

// Removes remoteParticipant container from the DOM.
function removeName(participant) {
if (participant) {
let { identity } = participant;
const container = document.getElementById(
participantContainer-${identity}
);
container.parentNode.removeChild(container);
}
}

// A new RemoteTrack was published to the Room.
function trackPublished(publication, container) {
if (publication.isSubscribed) {
attachTrack(publication.track, container);
}
publication.on('subscribed', function(track) {
log('Subscribed to ' + publication.kind + ' track');
attachTrack(track, container);
});
publication.on('unsubscribed', detachTrack);
}

// A RemoteTrack was unpublished from the Room.
function trackUnpublished(publication) {
log(publication.kind + ' track was unpublished.');
}

// A new RemoteParticipant joined the Room
function participantConnected(participant, container) {
let selfContainer = document.createElement('div');
selfContainer.id = participantContainer-${participant.identity};

container.appendChild(selfContainer);
appendName(participant.identity, selfContainer);

participant.tracks.forEach(function(publication) {
trackPublished(publication, selfContainer);
});
participant.on('trackPublished', function(publication) {
trackPublished(publication, selfContainer);
});
participant.on('trackUnpublished', trackUnpublished);
}

// Detach the Participant's Tracks from the DOM.
function detachParticipantTracks(participant) {
var tracks = getTracks(participant);
tracks.forEach(detachTrack);
}

// When we are about to transition away from this page, disconnect
// from the room, if joined.
window.addEventListener('beforeunload', leaveRoomIfJoined);

// Obtain a token from the server in order to connect to the Room.
$.getJSON('/token', function(data) {
identity = data.identity;
document.getElementById('room-controls').style.display = 'block';

// Bind button to join Room.
document.getElementById('button-join').onclick = function() {
roomName = document.getElementById('room-name').value;
if (!roomName) {
alert('Please enter a room name.');
return;
}

log("Joining room '" + roomName + "'...");
var connectOptions = {
  name: roomName,
  logLevel: 'debug'
};

if (previewTracks) {
  connectOptions.tracks = previewTracks;
}

// Join the Room with the token from the server and the
// LocalParticipant's Tracks.
Video.connect(data.token, connectOptions).then(roomJoined, function(error) {
  log('Could not connect to Twilio: ' + error.message);
});

};

// Bind button to leave Room.
document.getElementById('button-leave').onclick = function() {
log('Leaving room...');
activeRoom.disconnect();
};
});

// Get the Participant's Tracks.
function getTracks(participant) {
return Array.from(participant.tracks.values()).filter(function(publication) {
return publication.track;
}).map(function(publication) {
return publication.track;
});
}

// Successfully connected!
function roomJoined(room) {
window.room = activeRoom = room;

log("Joined as '" + identity + "'");
document.getElementById('button-join').style.display = 'none';
document.getElementById('button-leave').style.display = 'block';

// Attach LocalParticipant's Tracks, if not already attached.
var previewContainer = document.getElementById('local-media');
if (!previewContainer.querySelector('video')) {
attachTracks(getTracks(room.localParticipant), previewContainer);
}

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

// When a Participant joins the Room, log the event.
room.on('participantConnected', function(participant) {
log("Joining: '" + participant.identity + "'");
participantConnected(participant, remoteMediaContainer);
});

// When a Participant leaves the Room, detach its Tracks.
room.on('participantDisconnected', function(participant) {
log("RemoteParticipant '" + participant.identity + "' left the room");
detachParticipantTracks(participant);
removeName(participant);
});

// Once the LocalParticipant leaves the room, detach the Tracks
// of all Participants, including that of the LocalParticipant.
room.on('disconnected', function() {
log('Left');
if (previewTracks) {
previewTracks.forEach(function(track) {
track.stop();
});
previewTracks = null;
}
detachParticipantTracks(room.localParticipant);
room.participants.forEach(detachParticipantTracks);
room.participants.forEach(removeName);
activeRoom = null;
document.getElementById('button-join').style.display = 'block';
document.getElementById('button-leave').style.display = 'none';
});
}

// Preview LocalParticipant's Tracks.
document.getElementById('button-preview').onclick = function() {
var localTracksPromise = previewTracks
? Promise.resolve(previewTracks)
: Video.createLocalTracks();

localTracksPromise.then(function(tracks) {
window.previewTracks = previewTracks = tracks;
var previewContainer = document.getElementById('local-media');
if (!previewContainer.querySelector('video')) {
attachTracks(tracks, previewContainer);
}
},function(error) {
console.error('Unable to access local media', error);
log('Unable to access Camera and Microphone');
}
);
};

// Activity log.
function log(message) {
var logDiv = document.getElementById('log');
logDiv.innerHTML += '

> ' + message + '

';
logDiv.scrollTop = logDiv.scrollHeight;
}

// Leave Room.
function leaveRoomIfJoined() {
if (activeRoom) {
activeRoom.disconnect();
}

}

send tracks: safari Version 13.1 (all macOS and iOS)
receive tracks: chrome 81 on android (multiples devices, android 4.1 on samsung or greater android version on huawei)
result: only display audio, but not video track
Log: only audio track is subscribed, but not video track.

Having same issue. iOs displays all video properly in Safari. User on Galaxy S10 Chrome cannot see video from iOs but can see video from other Chrome users.

We're going to later see if we can set a {min,ideal,max} for the height and {min,max} for the aspectRatio and no width to see if we can get Safari to pick something reasonable, but we haven't tried this yet.

FWIW, no, this does not work. It looks like you MUST specify a static width and height for Safari; it won't make good choices on its own given a range. We're now looking into whether other options for width and height other than 720x1440 will work (e.g., 640x1280).

UPDATE: No, 640x1280 does not work. It looks like the ONLY values for width and height that work from Safari on iOS right now are 720x1440.

Width and height of 720x1440 also don't seem to work on iPhone. Can someone confirm that still works?

It has been working for us, but it has also historically been the case that iPhones are quite finicky about parameters... it's possible you have another parameter that is causing it to fail too.

Thanks, Nick. Any suggestions on what other parameters potentially should
we look at. We tried several iPhones and some work and some don't.

On Thu, May 21, 2020, 2:47 PM Nick Johnson notifications@github.com wrote:

It has been working for us, but it has also historically been the case
that iPhones are quite finicky about parameters... it's possible you have
another parameter that is causing it to fail too.

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/twilio/twilio-video.js/issues/927#issuecomment-632363585,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/AKTSFBUZ6YYUYNOUKS265LTRSWOQPANCNFSM4LUV5VIQ
.

--
DISCLAIMER ========== This e-mail may contain privileged and confidential
information which is the property of Eyecarelive, Inc. It is intended only
for the use of the individual or entity to which it is addressed. If you
are not the intended recipient, you are not authorized to read, retain,
copy, print, distribute or use this message. If you have received this
communication in error, please notify the sender and delete all copies of
this message. Eyecarelive, inc does not accept any liability for virus
infected mails.

We use frameRate: 24, width: 720, height: 1440, facingMode: { exact: 'user' } and we force h.264 video.

FWIW, we don't / aren't able to test on every iPhone out there, and mostly focus on those already running iOS 13.x

Got video working but audio is still an issue. Audio works fine on Safari on MAc but not on IOS devices. Here's the code.

=========================================================
//camera.ts

private initializeTracks(kind?: MediaDeviceKind, deviceId?: string) {
console.log(deviceId)
if (kind) {
switch (kind) {
case 'audioinput':
return createLocalTracks({ audio: { deviceId }, video: true });
case 'videoinput':
return createLocalTracks({ audio: true, video: { deviceId } });
}
}

    return createLocalTracks({ audio: true, video: true });
}

private async initializeDevice(kind?: MediaDeviceKind, deviceId?: string) {
try {
this.isInitializing = true;

        this.finalizePreview();

        this.localTracks = kind && deviceId
            ? await this.initializeTracks(kind, deviceId)
            : await this.initializeTracks();

        this.videoTrack = this.localTracks.find(t => t.kind === 'video') as LocalVideoTrack;
        this.audioTracks = this.localTracks.find(t => t.kind === 'audio') as LocalAudioTrack;
        const audioElement = this.audioTracks.attach();
        const videoElement = this.videoTrack.attach();
        //videoElement.muted = true;
        videoElement.autoplay = true;
         this.renderer.setAttribute(videoElement, 'muted', 'muted');
        this.renderer.setAttribute(videoElement, 'autoplay', 'autoplay');
         this.renderer.setAttribute(videoElement, 'playsinline', 'true');
        this.renderer.appendChild(this.previewElement.nativeElement, videoElement);
        this.renderer.appendChild(this.audioElement.nativeElement, audioElement)

    } finally {
        this.isInitializing = false;
    }

}

videochat.ts

async joinOrCreateRoom(name: any, tracks: LocalTrack[]) {

    let room: Room = null;
    try {

        const token = await this.getAuthToken(name.encryptedId, name.roomCode);
        room =
            await connect(
                token.twilioToken, {
                    name, 
                    tracks,
                  //  dominantSpeaker: true,
                    preferredVideoCodecs: ['H264'],
                    preferredAudioCodecs: ['opus']

                } as ConnectOptions);
    } catch (error) {
        console.error(`Unable to connect to Room: ${error.message}`);
    } finally {
        if (room) {
            this.roomBroadcast.next(true);
        }
    }

@nicklyra can you please review the code above and see if we are doing anything wrong wrt audio? Thanks

Hi all and @makarandp0 I am also experiencing issue, I have followed the constraints suggestions here but it does not work. Here is me code:
async initRoom () {
const VueThis = this

  const connectOptions = {
    name: this.roomName,
    video: { width: 720, height: 1440, frameRate: 24 },
    audio: true
  }
  // before a user enters a new room,
  // disconnect the user from they joined already
  this.leaveRoomIfJoined()
  // remove any remote track when joining a new room
  this.$refs.remoteTrack.innerHTML = ''
  // get twilio access token for current user
  await this.$store.dispatch('room/generateAccessToken', { roomName: this.roomName, identity: this.currentUserId })
  console.log(this.currentUserId)
  // connect to room
  Twilio.connect(this.accessToken, connectOptions).then(function (room) {
    console.log('Successfully joined a Room: ', room)
    if (VueThis.currentUserRoleId === app.USER_ROLE) {
      VueThis.setRoomMessage('Room successfully created. Waiting for your cast to join.')
    } else {
      VueThis.setRoomMessage('You joined the room.')
    }
    VueThis.loading = false
    VueThis.activeRoom = room

    // Handle the TrackPublications already published by the Participant.
    room.participants.forEach(function (participant) {
      VueThis.participantConnected(participant)
    })

    // Handle the TrackPublications that will be published by the Participant later.
    room.on('participantConnected', function (participant) {
      console.log(participant)
      console.log('participant connected ' + participant.identity)
      VueThis.setRoomMessage(participant.identity + ' joined the room.')
      VueThis.participantConnected(participant)
    })
    // When a Participant leaves the Room, detach its Tracks.
    room.on('participantDisconnected', function (participant) {
      console.log('participant disconnected')
      console.log(participant.identity + 'left')
      VueThis.setRoomMessage(participant.identity + ' left the room.')
    })
    // Handle room completed - triggered by AWS
    room.once('disconnected', async function (myroom, error) {
      VueThis.roomDisconnected(myroom, error)
    })
    // if local preview is not active, create it
    if (!VueThis.localTrack) {
      createLocalVideoTrack({
        audio: true,
        video: { width: 720, height: 1440, frameRate: 24 }
      }).then(track => {
        const localMediaContainer = document.getElementById('localTrack')
        localMediaContainer.appendChild(track.attach())
        VueThis.localTrack = true
        VueThis.localVideoTrack = track
        console.log('this.localVideoTrack')
        console.log(VueThis.localVideoTrack)
      })
    }
  })
}

@tracyarciaga ,

Looks like you are creating two video tracks, one in ConnectOptions and one for your preview. Please refer to this comment for the solution.

Thanks,

Manjesh Malavalli
JSDK Team

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vsrboth picture vsrboth  Â·  3Comments

julien-l picture julien-l  Â·  4Comments

lmatheus picture lmatheus  Â·  5Comments

gregoryjjb picture gregoryjjb  Â·  3Comments

kumail-raza picture kumail-raza  Â·  5Comments