Twilio-video.js: Beta 7 : stop audio/video still not working properly

Created on 23 Apr 2017  路  6Comments  路  Source: twilio/twilio-video.js

I've upgraded to beta 7 and i'm trying to stop audio/video by using the following:
twRoom.localParticipant.tracks.forEach(function(track){
track.stop()
});

the video stopped but the camera light is still on.
In addition, when i try to start again after the stop, the video stream does not pass to the other participant.

Most helpful comment

Hi @theDude30,

Can you include a reproduction example, please? I just ran the following myself in the console (after defining token), and, in each case, the video light went on and off as expected.

// Stopping custom Tracks:
(async () => {
  const tracks = await Twilio.Video.createLocalTracks();
  // ^ Video light goes on.
  const room = await Twilio.Video.connect(token, { tracks });
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
})();
// Stopping custom Tracks, adding a new Track, and stopping that one, too:
(async () => {
  const tracks = await Twilio.Video.createLocalTracks();
  // ^ Video light goes on.
  const room = await Twilio.Video.connect(token, { tracks });
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
  const videoTrack = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(videoTrack);
  videoTrack.stop();
  // ^ Video light goes off.
})();
// Stopping the default, automatically-acquired Tracks:
(async () => {
  const room = await Twilio.Video.connect(token);
  // ^ Video light goes on.
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
})();
// Letting the Room stop the default, automatically-acquired Tracks:
(async () => {
  const room = await Twilio.Video.connect(token);
  // ^ Video light goes on.
  room.disconnect();
  // ^ Video light goes off.
})();

Also, you mention

In addition, when i try to start again after the stop, the video stream does not pass to the other participant.

How are you starting video again? To be clear, once stop-ed, neither a Track nor the underlying MediaStreamTrack can be restarted鈥攕o I take it you are adding another Track? Are you receiving the "trackAdded" event but not the "trackStarted" event at the remote party (and therefore black frames, etc.)? Can you share a reproduction example for this as well? We could add it to our integration tests if it identifies a bug (FWIW, I just re-ran our existing integration tests, including this one, which is very close to the scenario you describe). I also ran this manually, and it worked OK:

(async () => {
  const track1 = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(track1);
  track1.stop();
  // ^ Video light goes off.
  const track2 = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(track2);

  // Then, after some time, cleanup.
  await new Promise(resolve => setTimeout(resolve, 1000));
  room.localParticipant.removeTrack(track1);
  room.localParticipant.removeTrack(track2);
  room.disconnect();
})();

Thanks,
Mark

All 6 comments

Hi @theDude30,

Can you include a reproduction example, please? I just ran the following myself in the console (after defining token), and, in each case, the video light went on and off as expected.

// Stopping custom Tracks:
(async () => {
  const tracks = await Twilio.Video.createLocalTracks();
  // ^ Video light goes on.
  const room = await Twilio.Video.connect(token, { tracks });
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
})();
// Stopping custom Tracks, adding a new Track, and stopping that one, too:
(async () => {
  const tracks = await Twilio.Video.createLocalTracks();
  // ^ Video light goes on.
  const room = await Twilio.Video.connect(token, { tracks });
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
  const videoTrack = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(videoTrack);
  videoTrack.stop();
  // ^ Video light goes off.
})();
// Stopping the default, automatically-acquired Tracks:
(async () => {
  const room = await Twilio.Video.connect(token);
  // ^ Video light goes on.
  room.localParticipant.tracks.forEach(track => track.stop());
  // ^ Video light goes off.
})();
// Letting the Room stop the default, automatically-acquired Tracks:
(async () => {
  const room = await Twilio.Video.connect(token);
  // ^ Video light goes on.
  room.disconnect();
  // ^ Video light goes off.
})();

Also, you mention

In addition, when i try to start again after the stop, the video stream does not pass to the other participant.

How are you starting video again? To be clear, once stop-ed, neither a Track nor the underlying MediaStreamTrack can be restarted鈥攕o I take it you are adding another Track? Are you receiving the "trackAdded" event but not the "trackStarted" event at the remote party (and therefore black frames, etc.)? Can you share a reproduction example for this as well? We could add it to our integration tests if it identifies a bug (FWIW, I just re-ran our existing integration tests, including this one, which is very close to the scenario you describe). I also ran this manually, and it worked OK:

(async () => {
  const track1 = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(track1);
  track1.stop();
  // ^ Video light goes off.
  const track2 = await Twilio.Video.createLocalVideoTrack();
  // ^ Video light goes on.
  room.localParticipant.addTrack(track2);

  // Then, after some time, cleanup.
  await new Promise(resolve => setTimeout(resolve, 1000));
  room.localParticipant.removeTrack(track1);
  room.localParticipant.removeTrack(track2);
  room.disconnect();
})();

Thanks,
Mark

Hi,
I managed to resolve all the issues i had:

  • For some reason the "Twilio.Video.Connect" by default starts the audio/video automatically(this happened somewhere between beta 5-7), to disable that i added in the options "{name: room,audio:false,video:false}"
  • When starting audio/video i had modify the current function for this:
    localTracks.forEach(function(track) {
    localMediaContainer.appendChild(track.attach());
    twRoom.localParticipant.addTrack(track);
    });
    (instead of just localMediaContainer.appendChild(track.attach());).

  • when i do stop i had to modify the function to :
    twRoom.localParticipant.tracks.forEach(function(track){
    track.stop();
    twRoom.localParticipant.removeTrack(track);
    });
    (instead of just "track.stop();" i had to add "twRoom.localParticipant.removeTrack(track);")

  • It's hard to keep up with all the changes when there is no proper documentation or even up to date example.

Hi @theDude30,

Glad you were able to resolve them.

  • For some reason the "Twilio.Video.Connect" by default starts the audio/video automatically(this happened somewhere between beta 5-7), to disable that i added in the options "{name: room,audio:false,video:false}"

Actually, this has been the behavior for a long time. Back in 1.0.0-beta1 (when connect was still Client#connect) we had the same behavior. See here in the JSDoc:

By default, this will automatically acquire LocalMedia containing a LocalAudioTrack and LocalVideoTrack before connecting to the Room. The LocalMedia will be stopped when you disconnect from the Room.

Although LocalMedia has since been removed in favor of manipulating Tracks directly, the behavior鈥攁nd the JSDoc in 1.0.0-beta7鈥攊s largely unchanged. You can also disable this behavior by specifying { tracks: [] }.

  • When starting audio/video i had modify the current function for this:
    localTracks.forEach(function(track) {
    localMediaContainer.appendChild(track.attach());
    twRoom.localParticipant.addTrack(track);
    });
    (instead of just localMediaContainer.appendChild(track.attach());).

Ah, yes鈥攜ou must addTrack for each LocalTrack you wish to share.

  • when i do stop i had to modify the function to :
    twRoom.localParticipant.tracks.forEach(function(track){
    track.stop();
    twRoom.localParticipant.removeTrack(track);
    });
    (instead of just "track.stop();" i had to add "twRoom.localParticipant.removeTrack(track);")

Yes, stopping a Track does not force its removal, although by default removing a Track will stop it. So I believe these two lines can be consolidated into

twRoom.localParticipant.removeTrack(track);
  • It's hard to keep up with all the changes when there is no proper documentation or even up to date example.

Were you aware that we publish JSDoc for each release? We call this out in the README.md, although that particular link is old, so we definitely must fix that.

Also, have you seen the TwilioDevEd/video-quickstart-node project? Granted, it is pinned to 1.0.0-beta5 at the time of writing, although it is compatible with 1.0.0-beta7 (as I hope our CHANGELOG.md indicates). Still, we must update this, too.

Are there other examples you've seen that are out-of-date? I feel like we have a number of resources鈥攖he Quickstart project, API docs, CHANGELOG.md鈥攂ut obviously we have a discoverability problem if you are having trouble finding the information you need. We can tweak our README.md and update some of our links, but are there other improvements we could make that would help?

Thank you for the feedback,
Mark

@theDude30,

I will close this issue since you were able to resolve the problems, although I hope we can continue this discussion. If you'd rather followup via email, you can reach me at [email protected].

Best,
Mark

@markandrus I have a similar issue with version 2

Error is: track.stop is not a function and same error with room.localParticipant.removeTrack(track) Error: removeTrack is not a function

Please, can some body help us with it, there are no a clear workaround

Was this page helpful?
0 / 5 - 0 ratings