Releases: twilio/twilio-video.js
1.9.0
1.9.0 (May 9, 2018)
New Features
-
Room now emits "reconnecting" and "reconnected" events when the media
connection is disconnected and reconnected. You can use these events to update
your application and warn your users when a reconnection is occurring.
twilio-video.js does not yet support reconnecting the signaling connection;
however, when we do, we will use this same event. We recommend you set the
following event listeners in your application:room.on('reconnecting', error => { // Warn and/or update your application's UI. console.warn('Reconnecting!', error); }); room.on('reconnected', () => { // Log and/or update your application's UI. console.log('Reconnected!'); });
In addition to this change, we've also added a new Room
state
value:
"reconnecting". Roomstate
can now be one of "connected", "reconnecting", or
"disconnected". (JSDK-1855) -
By default, twilio-video.js waits up to 3000 milliseconds to fetch ICE servers
before connecting to a Room; and, if fetching ICE servers takes longer than
3000 milliseconds or otherwise fails, twilio-video.js will fallback to using
hard-coded STUN servers. Now you can configure this timeout with a new
property in ConnectOptions,iceServersTimeout
. You can also disable the
fallback behavior by setting another new property in ConnectOptions,
abortOnIceServersTimeout
, totrue
. Doing so will cause the Promise
returned byconnect
to reject with TwilioError 53500, "Unable to acquire
configuration", if fetching ICE servers times out or otherwise fails.
Bug Fixes
- Fixed a bug where, if the WebSocket connection to Twilio was disconnected (for
example, due to losing internet connectivity), Room would emit a
"disconnected" event without an error. Now, Room will emit a
SignalingConnectionDisconnectedError. - Fixed a bug where twilio-video.js failed to identify a WebSocket timeout in a
timely manner. Now, WebSocket timeouts can be identified in around 30 seconds.
If a WebSocket timeout occurs, for example, due to a WebSocket disconnect,
Room will emit a "disconnected" event with SignalingConnectionTimeoutError. - If an ICE failure occurs, for example due to disconnecting a VPN, but the
signaling connection remains online, twilio-video.js will attempt an ICE
restart to repair the media connection. (JSDK-1810)
1.8.0
1.8.0 (February 9, 2018)
New Features
- Added support for TURN over TLS on port 443.
1.7.0
1.7.0 (January 9, 2018)
New Features
-
Added VP8 simulcast support for Chrome. VP8 simulcast can be enabled in Chrome
using thepreferredVideoCodecs
property in ConnectOptions. For example,connect(token, { preferredVideoCodecs: [ { codec: 'VP8', simulcast: true } ] });
We recommend you only enable this setting in Group Rooms.
-
By default, when you connect to a Group Room, you subscribe to all
RemoteParticipants' Tracks. However, sometimes your device may lack the codec
required to decode a particular Track. For example, an H.264-only Safari
Participant would be unable to decode a VP8 VideoTrack. In these cases, we now
raise a new event, "trackSubscriptionFailed", on the RemoteParticipant who
published the Track you could not subscribe to. For example, the following
coderoom.participants.forEach(handleParticipant); room.on('participantConnected', handleParticipant); function handleParticipant(participant) { participant.on('trackSubscriptionFailed', (error, trackPublication) => console.warn('Failed to subscribe to RemoteTrack %s with name "%s": %s', trackPublication.trackSid, trackPublication.trackName, error.message))); }
will log something like
Failed to subscribe to RemoteTrack MTxxx with name "123": No codec supported
to the console. twilio-video.js will also log these warnings by default.
Please refer to the API docs for more information.
Bug Fixes
- Fixed a memory leak in an internal dependency, SIP.js.
1.6.1
1.6.1 (December 12, 2017)
Bug Fixes
- Fixed a bug where, if you published a LocalDataTrack, unpublished it, and then
published it again, you would be unable tosend
data over it again.
(JSDK-1580) - We've worked around a long-standing issue with Firefox's RTCIceTransport
behavior that required you to always add a LocalAudioTrack. You should now be
able to connect to Rooms with, for example, only a LocalVideoTrack, only a
LocalDataTrack, or no LocalTracks at all. - Binary RemoteDataTrack messages received in Firefox arrived as Blobs instead
of ArrayBuffers (as in Chrome and Safari). We now set the underlying
RTCDataChannel'sbinaryType
to "arraybuffer" in order to ensure consistent
behavior across browsers. (JSDK-1627) - We always stringify
name
s passed via LocalTrackOptions now. (JSDK-1565) - Added a workaround for WebRTC
Issue 8329. This
issue caused Track failures in Chrome whenever participating in Rooms from a
device that supported duplicate codecs (for example, H.264 at two different
profile levels). (JSDK-1645) - Fixed some code that could lead to a renegotiation loop in Firefox.
- Fixed a memory leak in an internal class, PeerConnectionV2.
1.6.0
1.6.0 (October 24, 2017)
New Features
-
Added DataTrack support in Group Rooms. Previously, DataTracks only worked in
Peer-to-peer Rooms. Now they work in both. Consequently, the "experimental"
warning has been removed. -
Added LocalDataTrackOptions. These options allow you to configure the
maxPacketLifeTime
,maxRetransmits
, andordered
properties of a
LocalDataTrack's underlying RTCDataChannel(s). -
Added "trackPublicationFailed" and "trackPublished" events to the
LocalParticipant. Previously, if you failed to publish a LocalTrack when
connecting to a Room, there was no API to discover what went wrong. Now, if
you fail to publish a LocalTrack atconnect
-time—for example, due to a codec
mismatch or an invalid Track name—we will raise a "trackPublicationFailed" on
the LocalParticipant with an informative error. Similarly, if publication
succeeds, we will raise a "trackPublished" event with the resulting
LocalTrackPublication. -
Added a new top-level boolean property,
isSupported
, that indicates whether
or not the browser/environment/platform currently running twilio-video.js
contains the necessary APIs (for example, WebRTC) to participate in video
chats. Depending on how you use twilio-video.js, you can use one of the
methods below to access it:// Option 1: Using `require` const { isSupported } = require('twilio-video'); // Option 2: Using browser global const { isSupported } = Twilio.Video;
1.5.1
1.5.1 (October 13, 2017)
Bug Fixes
- Fixed a bug where we created too many MediaStreams in Firefox, leading to
extremely degraded audio quality. (JSDK-1588)
1.5.0
1.5.0 (October 9, 2017)
New Features
- You can now specify Track names. Refer to the Track name guide below for more
information.
Bug Fixes
- Fixed bug where RemoteTrack's "unsubscribed" event and RemoteParticipant's
"trackUnsubscribed" event fired before the RemoteTrack was removed from the
RemoteParticipant'stracks
collections instead of after.
Track Name Guide
Setting Track names
There are a few different ways you can specify Track names. For example, you can
specify name
as an audio
or video
constraint when calling any of
createLocalTracks
, createLocalAudioTrack
, createLocalVideoTrack
, or
connect
:
createLocalTracks({
audio: { name: 'microphone' },
video: { name: 'camera' }
});
createLocalAudioTrack({ name: 'microphone' });
createLocalVideoTrack({ name: 'camera' });
connect(token, {
audio: { name: 'microphone' },
video: { name: 'camera' }
});
These will create a LocalAudioTrack and a LocalVideoTrack with the names
"microphone" and "camera", respectively. If you have a reference to a
MediaStreamTrack, you can also pass the name
to the LocalAudioTrack or
LocalVideoTrack constructor:
const localAudioTrack = new LocalAudioTrack(mediaStreamTrack1, { name: 'microphone' });
const localVideoTrack = new LocalVideoTrack(mediaStreamTrack2, { name: 'camera' });
Similarly, for LocalDataTracks:
const localDataTrack = new LocalDataTrack({ name: 'data' });
You can even pass these values if you use the MediaStreamTrack override for
publishTrack
. For example:
room.localParticipant.publishTrack(mediaStreamTrack, { name: 'my-track' });
Please keep in mind:
- If you do not specify a Track name, the Track's name will default to the
LocalTrack ID. - A single Participant cannot have two Tracks published with the same name at a
time.
Getting Track names
You can check a LocalTrack or RemoteTrack's name by querying it's name
property. For example,
participant.on('trackSubscribed', track => {
console.log('Subscribed to Track "' + track.name + '"');
});
This can be useful, for example, for distinguishing between a RemoteVideoTrack
named "camera" and a RemoteVideoTrack named "screenshare".
1.4.0
1.4.0 (October 2, 2017)
This release includes a handful of new features as well as some deprecations.
Please refer to the migration guide below for handling the deprecations.
New Features
- Added
publishTrack
,unpublishTrack
, and related methods to
LocalParticipant.addTrack
,removeTrack
and related methods are now
deprecated. Refer to the migration guide below. - Added "trackSubscribed" and "trackUnsubscribed" events. As of now, they are
emitted before and after the "trackAdded" and "trackRemoved" events,
respectively; however, in a future release, they will only be emitted when
a Track which has actually been subscribed to or unsubscribed from. - Added LocalTrackPublication classes. These classes allow you to discover your
Track SID, and, in a future release, will allow you to selectively subscribe
to or unsubscribe from RemoteTracks. It is also recommended that you starting
using Track SIDs instead of Track IDs to correlate Tracks. - Added experimental DataTrack support. You can see a demo of it
here. Refer to the DataTrack
guide below for more information.
Migration Guide
Migrating from addTrack
to publishTrack
addTrack
is deprecated and will be removed in the next major version. Please
migrate to publishTrack
as soon as possible. For the most part, you can treat
the new method as a drop-in replacement for the old one. For example, where you
previously had
// Before
room.localParticipant.addTrack(localTrack);
you can replace it with
// After
room.localParticipant.publishTrack(localTrack);
One short-coming of addTrack
is that it could not tell if it was successful or
not. With publishTrack
, we actually return a Promise for a
LocalTrackPublication. If publishing succeeds, you'll be able to print your
Track SID:
try {
const publication = await room.localParticipant.publishTrack(track);
console.log('Successfully published Track %s', publication.trackSid);
} catch (error) {
console.error('Failed to publish Track!', error.message);
}
Similarly, addTracks
has been replaced by publishTracks
.
Migrating from removeTrack
to unpublishTrack
Like addTrack
and publishTrack
, removeTrack
is deprecated and has been
replaced with unpublishTrack
. For the most part, you can treat the new method
as a drop-in replacement for the old one. The one caveat is that
unpublishTrack
will not automatically stop the Track for you. For example,
where you previously had
// Before
room.localParticipant.removeTrack(localTrack);
you can replace it with
// After
room.localParticipant.unpublishTrack(localTrack);
localTrack.stop();
Of course, you can omit the call to stop
if you do not want to stop the Track.
unpublishTrack
will return the LocalTrackPublication if the Track was
unpublished. For example, you can print the unpublished Track's SID:
const publication = room.localParticipant.unpublishTrack(localTrack);
if (publication) {
console.log('Successfully unpublished Track %s', publication.trackSid);
}
Alternatively, if you already have a reference to a LocalTrackPublication, you
can call unpublish
directly on it.
publication.unpublish();
Similarly, removeTracks
has been replaced by unpublishTracks
.
Migrating from Track IDs to Track SIDs
In some applications, it makes sense to share metadata about a Track.
Previously, the natural way to do this with twilio-video.js was to use the Track
ID; however, in the next major release of twilio-video.js, Track IDs will be
replaced by Track SIDs. SIDs—or "string identifiers"—are identifiers that Twilio
assigns to resources. These identifiers are useful for debugging, sharing
metadata out-of-band, and looking up resources in the REST API. For a long time,
Rooms and Participants have had SIDs, but not Tracks. That changes in this
release.
Whereas before you may have associated metadata with a LocalTrack's ID, you
should now associate that metadata with the LocalTrack's SID, as exposed by the
LocalTrackPublication:
// Before
room.localParticipant.addTrack(localTrack);
console.log('Added LocalTrack %s', localTrack.id);
// After
const publication = await room.localParticipant.publishTrack(localTrack);
console.log('Published LocalTrack %s', publication.trackSid);
Similarly, for a RemoteTrack:
// Before
console.log('Received RemoteTrack %s', remoteTrack.id);
// After
console.log('Received RemoteTrack %s', remoteTrack.sid);
DataTrack
This releases adds experimental support for "DataTracks". DataTracks are a new
kind of Track, similar to AudioTracks and VideoTracks. DataTracks are different,
though, in that they allow you to send and receive arbitrary data within a
Room—not just audio and video. Using DataTracks, you could send mouse events,
transfer files, or implement a simple chat mechanism in your Room. All of this
is supported under-the-hood by WebRTC's RTCDataChannels.
We're calling support for DataTracks "experimental" in this release becase, at
the time of writing, they are currently only supported in Peer-to-Peer (P2P)
Rooms. You will not (yet) be able to connect to Group Rooms with DataTracks. We
plan to add this in a subsequent release. If you want to see a demo of
DataTracks in action, see here.
Constructing a new DataTrack is simple—just call the LocalDataTrack
constructor:
const { LocalDataTrack } = require('twilio');
const localTrack = new LocalDataTrack();
Once you've constructed a DataTrack, you can either connect
to a Room with it
or publish it to a Room:
// Option 1
connect(token, { tracks: [localTrack] });
// Option 2
room.localParticipant.publishTrack(localTrack);
Once you've published the DataTrack to the Room, call send
to transmit
messages:
localTrack.send('cool');
In order to receive a DataTrack, you'll want to iterate over a
RemoteParticipant's Tracks and listen to the "trackAdded" event. Once you
have a DataTrack, attach a listener to the "message" event:
function handleTrack(remoteTrack) {
if (remoteTrack.kind === 'data') {
remoteTrack.on('message', data => {
console.log('Got message "%s" from DataTrack %s', data, remoteTrack.sid);
});
}
}
remoteParticipant.tracks.forEach(handleTrack);
remoteParticipant.on('trackAdded', handleTrack);
You can also listen for the "trackMessage" on the RemoteParticipant:
remoteParticipant.on('trackMessage', (data, remoteTrack) => {
console.log('Got message "%s" from DataTrack "%s"', data, remoteTrack.sid);
});
1.3.0
1.3.0 (September 11, 2017)
New Features
-
twilio-video.js now features an API for setting and updating bandwidth
constraints. When youconnect
to a Room, you can specify an optional
maxAudioBitrate
and an optionalmaxVideoBitrate
, both in bits per second
(bps). These values are set as hints for variable bitrate codecs, but will not
take effect for fixed bitrate codecs.For example, to connect with a maximum audio bitrate of 64 kilobits per
second and a maximum video bitrate of 500 kilobits per second:const room = await connect(token, { maxAudioBitrate: 64000, maxVideoBitrate: 500000 });
You can also update your
maxAudioBitrate
andmaxVideoBitrate
while
participating in a Room. For example, to reset your maximum bitrates for audio
and video, you could set each tonull
:room.localParticipant.setParameters({ maxAudioBitrate: null, maxVideoBitrate: null });
If you want to change only one value—for example, just the maximum video
bitrate—you can omit the other value. For example, to update only the maximum
video bitrate, leaving the maximum audio bitrate unchanged:room.localParticipant.setParameters({ maxVideoBitrate: 1000000 });
-
twilio-video.js now features an API for setting preferred codecs when
publishing Tracks. When youconnect
to a Room, you can specify an optional
preferredAudioCodecs
array and an optionalpreferredVideoCodecs
array.
These are codec "preferences" because they will only be applied if your
browser and the type of Room you are connected to support them. If a
preference cannot be satisfied, we will fallback to the next best codec.For example, to connect with a preferred video codec of H.264:
const room = await connect(token, { preferredVideoCodecs: ['H264'] });
You can also specify more than one preferred codec. For example, to connect
with a preferred audio codec of iSAC, falling back to Opus if iSAC is
unavailable:const room = await connect(token, { preferredAudioCodecs: ['isac', 'opus'] });
Please refer to the API docs for more information on both of these features.
Bug Fixes
- Track's
attach
method now sets theplaysInline
attribute on <audio>
and <video> elements. This is necessary to allow playback in Safari 11
on iOS.
1.2.2
1.2.2 (August 22, 2017)
This is primarily a bug fix release; however, we've also factored out two
dependencies (@twilio/sip.js and @twilio/webrtc) for easier management of the
project.
Bug Fixes
- In Chrome,
Room#getStats()
did not provide valid values for those Participants
with more than one Track of the same kind (audio or video). (JSDK-1329) - Fixed a rare scenario where the SDK could "get stuck" negotiating with the
server. We are evaluating whether or not to patch this behavior server-side
as well, so that older clients can receive the fix, too. (JSDK-1454)