# Migrating from 1.x to 2.x

This guide provides an introduction to the 2.x Programmable Video JavaScript SDK
(twilio-video.js) and a set of guidelines to migrate an application from 1.x to
2.x.

## Resources

* [API docs](https://sdk.twilio.com/js/video/releases/2.34.0/docs/)
* [Getting started](/docs/video/javascript-getting-started)
* [QuickStart App](https://github.com/twilio/video-quickstart-js/tree/master)

## New Features

### Track Priority and Network Bandwidth Profiles (Group Rooms only)

In twilio-video.js 2.x, you can now determine how your downlink bandwidth will be distributed
among your subscribed RemoteVideoTracks in a Group Room using the [Network Bandwidth Profile API](/docs/video/tutorials/using-bandwidth-profile-api).
You can also use the [Track Priority API](/docs/video/tutorials/using-track-priority-api)
to prioritize certain VideoTracks over others in order to protect audio and higher priority video
qualities in times of network congestion.

### Reconnection States and Events

In twilio-video.js 1.x, you would be disconnected from the Room if you experienced network
disruption or handoff. twilio-video.js 2.x will instead attempt to re-establish your signaling
and media connections to the Room. You can use the Reconnection States and Events to update your
application's user interface accordingly. For more details, please refer to this [guide](/docs/video/reconnection-states-and-events).

**NOTE:** Please make the following changes to your [AccessToken](/docs/video/tutorials/user-identity-access-tokens) generation logic:

* A valid AccessToken is necessary for reconnection attempts to be successful. Therefore, we
  [recommend](/docs/video/reconnection-states-and-events#preventing-reconnection-failure-due-to-expired-accesstoken)
  that you set its Time-To-Live (TTL) to the maximum allowed session duration, which
  is currently 14,400 seconds (4 hours).
* Ensure that the AccessToken does not contain a configuration profile sid. Configuration profiles
  were deprecated when we [announced](https://www.twilio.com/blog/programmable-video-peer-to-peer-rooms-ga-html#room-based-access-control)
  the general availability of twilio-video.js 1.x. They are not supported in twilio-video.js 2.x.

### Region Selection

In twilio-video.js 2.x, your Participant will connect to the nearest region
as determined by [latency based routing](/docs/video/ip-addresses#signaling-communication).
If you want your signaling traffic to originate and terminate in a specific [region](/docs/video/ip-addresses#signaling-communication),
you can do so using a new ConnectOptions flag `region`:

```js
const { connect } = require('twilio-video');
const room = await connect(token, {
  region: 'de1'
});
```

### Connect without Subscribing to Tracks

In twilio-video.js 2.x, you can choose not to subscribe to any Tracks published by other
Participants in a Group or Small Group Room by setting a new ConnectOptions flag `automaticSubscription`
to `false`:

```js
  const { connect } = require('twilio-video');
  const room = await connect(token, {
    automaticSubscription: false
  });
```

## Object Model

![Diagram of hierarchy of participant, track publications, and room tracks with local and remote audio, video, and data.](https://docs-resources.prod.twilio.com/427557e2cdd672553db5d03555b3a6cb446afb6dcc98c6904587b486353bc32b.png)

### What's New

#### TrackPublication

In twilio-video.js 1.x, developers primarily interacted with the LocalParticipant's
and RemoteParticipants' media using Tracks. In twilio-video.js 2.x, developers will
interact with TrackPublications, which basically represent Tracks that are published
to the Room by its Participants. LocalTracks that are published by the LocalParticipant
are represented by LocalTrackPublications, and RemoteTracks that are published by
RemoteParticipants are represented by RemoteTrackPublications.

##### LocalTrackPublication

A LocalTrackPublication is created when a LocalParticipant successfully publishes
a LocalTrack, whether by adding it to the ConnectOptions' `tracks` array, or by
using the LocalParticipant's `publishTrack()` or `publishTracks()` methods.

*Publish a LocalTrack while connecting to a Room*

```js
const { connect, createLocalVideoTrack } = require('twilio-video');

const videoTrack = await createLocalVideoTrack();

const room = await connect('$TOKEN', {
  name: 'my-room',
  tracks: [videoTrack]
});

function trackPublished(publication) {
  console.log(`Published LocalTrack: ${publication.track}`);
}

// Access the already published LocalTracks.
room.localParticipant.tracks.forEach(trackPublished);
```

*Publish a LocalTrack after connecting to a Room*

```js
// Access LocalTracks that are published after connecting to the Room.
room.localParticipant.on('trackPublished', trackPublished);

const audioTrack = await createLocalVideoTrack();

// publishTrack() resolves with a LocalTrackPublication when the LocalTrack is
// successfully published.
const audioTrackPublication = await room.localParticipant.publishTrack(audioTrack);

trackPublished(audioTrackPublication);
```

In order to unpublish the LocalTrack, the developer can either use the
LocalTrackPublication's `unpublish()` method, or the LocalParticipant's
`unpublishTrack()` method. The LocalTrackPublication maintains a reference to
the published LocalTrack through its `track` property.

*Unpublish a LocalTrack using LocalTrackPublication#unpublish*

```js
audioTrackPublication.unpublish();
```

*Unpublish a LocalTrack using LocalParticipant#unpublishTrack*

```js
room.localParticipant.unpublishTrack(videoTrack);
```

##### RemoteTrackPublication

A RemoteTrackPublication is created when a RemoteParticipant successfully publishes
a RemoteTrack. In twilio-video.js 1.x, the LocalParticipant always subscribed to
each published RemoteTrack. In 2.x, we are moving towards the LocalParticipant
being able to subscribe to only the desired RemoteTracks. In this regard,
RemoteTracks that are not yet subscribed to will have their RemoteTrackPublications'
`isSubscribed` property set to `false`, and their `track` property set to `null`.
A subscribed RemoteTrack will have its RemoteTrackPublication's `isSubscribed`
property set to `true`, and the `track` property will be set to the subscribed
RemoteTrack. When a RemoteTrack is subscribed to, a "subscribed" event is emitted
on the RemoteTrackPublication. When a RemoteTrack is unsubscribed from, an
"unsubscribed" event is emitted on the RemoteTrackPublication.

```js
const { connect } = require('twilio-video');

const room = await connect('$TOKEN', {
  name: 'my-room'
});

function trackPublished(publication, participant) {
  console.log(`RemoteParticipant ${participant.identity} published a RemoteTrack: ${publication}`);
  assert(!publication.isSubscribed);
  assert.equal(publication.track, null);

  publication.on('subscribed', track => {
    console.log(`LocalParticipant subscribed to a RemoteTrack: ${track}`);
    assert(publication.isSubscribed);
    assert(publication.track, track);
  });

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

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

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

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

room.participants.forEach(participantConnected);
room.on('participantConnected', participantConnected);
```

NOTE: We do not have support for Track subscriptions yet. So each LocalParticipant
will subscribe to all the published RemoteTracks. The only way a LocalParticipant
unsubscribes from a RemoteTrack is if the RemoteParticipant unpublishes it. So:

* When a RemoteParticipant *publishes* a RemoteTrack, the following events are
  emitted in the given order:

  * "trackPublished" event on the RemoteParticipant
  * "subscribed" event on the RemoteTrackPublication
  * "trackSubscribed" event on the RemoteParticipant
* When a RemoteParticipant *unpublishes* a RemoteTrack, the following events are
  emitted in the given order:

  * "unsubscribed" event on the RemoteTrackPublication
  * "trackUnsubscribed" event on the RemoteParticipant
  * "trackUnpublished" event on the RemoteParticipant

### What's Changed

#### ConnectOptions

* `dscpTagging` has been deprecated and renamed to `enableDscp`.

#### Room

* "trackPublished" event is emitted when a RemoteParticipant *publishes* a RemoteTrack.
* "trackUnpublished" event is emitted when a RemoteParticipant *unpublishes* a RemoteTrack.
* "trackSubscribed" event is emitted when the LocalParticipant *subscribes to* a RemoteTrack published by a RemoteParticipant.
* "trackUnsubscribed" event is emitted when the LocalParticipant *unsubscribes from* a RemoteTrack published by a RemoteParticipant.
* "trackAdded" event is no longer emitted.
* "trackRemoved" event is no longer emitted.

#### LocalParticipant

* `tracks` is now a collection of LocalTrackPublications instead of a collection of LocalTracks.
* `audioTracks` is now a collection of LocalAudioTrackPublications instead of a collection of LocalAudioTracks.
* `dataTracks` is now a collection of LocalDataTrackPublications instead of a collection of LocalDataTracks.
* `videoTracks` is now a collection of LocalVideoTrackPublications instead of a collection of LocalVideoTracks.
* `addTrack()` is now replaced by `publishTrack()`.
* `addTracks()` is now replaced by `publishTracks()`.
* `removeTrack()` is now replaced by `unpublishTrack()`.
* `removeTracks()` is now replaced by `unpublishTracks()`.
* "trackPublished" event is emitted when a LocalTrack has been successfully published to the Room.
* "trackPublicationFailed" event is emitted when the LocalParticipant failed to publish a LocalTrack to the Room.
* "trackAdded" event is no longer emitted.
* "trackRemoved" event is no longer emitted.

#### RemoteParticipant

* `tracks` is now a collection of RemoteTrackPublications instead of a collection of RemoteTracks.
* `audioTracks` is now a collection of RemoteAudioTrackPublications instead of a collection of RemoteAudioTracks.
* `dataTracks` is now a collection of RemoteDataTrackPublications instead of a collection of RemoteDataTracks.
* `videoTracks` is now a collection of RemoteVideoTrackPublications instead of a collection of RemoteVideoTracks.
* "trackPublished" event is emitted when the RemoteParticipant *publishes* a RemoteTrack.
* "trackUnpublished" event is emitted when the RemoteParticipant *unpublishes* a RemoteTrack.
* "trackSubscribed" event is emitted when the LocalParticipant *subscribes to* a RemoteTrack published by a RemoteParticipant.
* "trackUnsubscribed" event is emitted when the LocalParticipant *unsubscribes from* a RemoteTrack published by a RemoteParticipant.
* "trackAdded" event is no longer emitted.
* "trackRemoved" event is no longer emitted.

#### RemoteTrack

* `id` is no longer available. Use `sid` or `name` instead.
* `isSubscribed` is no longer available. Use the corresponding RemoteTrackPublication's `isSubscribed` instead.
* "unsubscribed" event is now emitted on the corresponding RemoteTrackPublication instead of the RemoteTrack.
