{"id":15984235,"url":"https://github.com/opentok/opentok-node","last_synced_at":"2026-01-06T16:10:37.011Z","repository":{"id":1867573,"uuid":"2792774","full_name":"opentok/opentok-node","owner":"opentok","description":"OpenTok Server SDK for node.js","archived":false,"fork":false,"pushed_at":"2025-04-24T12:35:59.000Z","size":3091,"stargazers_count":164,"open_issues_count":13,"forks_count":169,"subscribers_count":67,"default_branch":"main","last_synced_at":"2025-04-24T13:36:46.036Z","etag":null,"topics":["javascript","nodejs","opentok","tokbox","webrtc"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"fix-macosx/net-monitor","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opentok.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2011-11-17T02:35:01.000Z","updated_at":"2025-04-24T12:36:02.000Z","dependencies_parsed_at":"2023-01-14T10:55:07.273Z","dependency_job_id":"ef758f14-d5ef-4c2b-b65c-8762da88e31e","html_url":"https://github.com/opentok/opentok-node","commit_stats":{"total_commits":377,"total_committers":47,"mean_commits":8.02127659574468,"dds":0.6976127320954908,"last_synced_commit":"86edf7215f295f53a7ecc8f7acab98a17e537401"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Fopentok-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Fopentok-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Fopentok-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Fopentok-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opentok","download_url":"https://codeload.github.com/opentok/opentok-node/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251207159,"owners_count":21552521,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","nodejs","opentok","tokbox","webrtc"],"created_at":"2024-10-08T02:05:15.680Z","updated_at":"2026-01-06T16:10:37.004Z","avatar_url":"https://github.com/opentok.png","language":"JavaScript","readme":"# OpenTok Node SDK\n\n\u003e [!IMPORTANT]\n\u003e ⚠️ This SDK is intended **only for existing TokBox/OpenTok customers**. New developers should use the [Vonage Server SDK for Node](https://github.com/vonage/vonage-node-sdk) instead.\n\n[![Build Status](https://travis-ci.org/opentok/opentok-node.png)](https://travis-ci.org/opentok/opentok-node) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)\n\n\u003cimg src=\"https://assets.tokbox.com/img/vonage/Vonage_VideoAPI_black.svg\" height=\"48px\" alt=\"Tokbox is now known as Vonage\" /\u003e\n\nThe OpenTok Node SDK provides methods for:\n\n* Generating [sessions](https://tokbox.com/developer/guides/create-session/) and\n  [tokens](https://tokbox.com/developer/guides/create-token/) for\n  [OpenTok](https://www.vonage.com/communications-apis/video/) applications\n* Working with OpenTok [archives](https://tokbox.com/developer/guides/archiving)\n* Working with OpenTok [live streaming broadcasts](https://tokbox.com/developer/guides/broadcast/live-streaming/)\n* Working with OpenTok [SIP interconnect](https://tokbox.com/developer/guides/sip)\n* [Sending signals to clients connected to a session](https://tokbox.com/developer/guides/signaling/)\n* [Disconnecting clients from sessions](https://tokbox.com/developer/guides/moderation/rest/)\n* [Forcing clients in a session to disconnect or mute published audio](https://tokbox.com/developer/guides/moderation/)\n\nIf you are looking for the JavaScript Client SDK please see the [@opentok/client](https://www.npmjs.com/package/@opentok/client) NPM module.\n\n## Before you start\n\nThis library is designed to work with the TokBox/OpenTok platform, which is part of the Vonage Video API. **The TokBox platform is no longer accepting new sign-ups.** If you are a new customer or starting a new project, you should use the [Vonage Customer Dashboard](https://dashboard.vonage.com) and the [Vonage Server SDK for Node](https://github.com/vonage/vonage-node-sdk), which includes support for the Vonage Video API.\n\nNot sure which exact platform you are using? Take a look at [this guide](https://api.support.vonage.com/hc/en-us/articles/10817774782492).\n\nIf you're an existing TokBox customer, don't worry — the TokBox platform continues to run on the same infrastructure as the Unified Vonage platform and remains supported. \n\n\u003e [!NOTE]\n\u003e We **strongly encourage migrating** to the Unified platform to benefit from streamlined billing and easier access to [Vonage’s other CPaaS APIs](https://www.vonage.com/communications-apis/).\n\nIf you are new to the Vonage Video API, create a developer account at the [Vonage Customer Dashboard](https://dashboard.vonage.com) and get started with the [Vonage Server SDK for Node](https://github.com/vonage/vonage-node-sdk).\n\n## Installation using npm (recommended):\n\nnpm helps manage dependencies for node projects. Find more info here: \u003chttp://npmjs.org\u003e.\n\nRun this command to install the package and adding it to your `package.json`:\n\n```\n$ npm install opentok --save\n```\n\n## Usage\n\n### Initializing\n\nImport the module to get a constructor function for an OpenTok object, then call it with `new` to\ninstantiate an OpenTok object with your own API Key and API Secret.\n\n```javascript\nconst OpenTok = require(\"opentok\");\nconst opentok = new OpenTok(apiKey, apiSecret);\n```\n\n#### Increasing Timeouts\nThe library currently has a 20 second timeout for requests. If you're on a slow network, and you need to increase the timeout, you can pass it (in milliseconds) when instantiating the OpenTok object.\n\n```javascript\nconst OpenTok = require(\"opentok\");\nconst opentok = new OpenTok(apiKey, apiSecret, { timeout: 30000});\n```\n\n### Creating Sessions\n\nTo create an OpenTok Session, use the `OpenTok.createSession(properties, callback)` method. The\n`properties` parameter is an optional object used to specify whether the session uses the OpenTok\nMedia Router, to specify a location hint, and to specify whether the session will be automatically\narchived or not. The callback has the signature `function(error, session)`. The `session` returned\nin the callback is an instance of Session. Session objects have a `sessionId` property that is\nuseful to be saved to a persistent store (such as a database).\n\n```javascript\n// Create a session that will attempt to transmit streams directly between\n// clients. If clients cannot connect, the session uses the OpenTok TURN server:\nopentok.createSession(function (err, session) {\n  if (err) return console.log(err);\n\n  // save the sessionId\n  db.save(\"session\", session.sessionId, done);\n});\n\n// The session will the OpenTok Media Router:\nopentok.createSession({ mediaMode: \"routed\" }, function (err, session) {\n  if (err) return console.log(err);\n\n  // save the sessionId\n  db.save(\"session\", session.sessionId, done);\n});\n\n// A Session with a location hint\nopentok.createSession({ location: \"12.34.56.78\" }, function (err, session) {\n  if (err) return console.log(err);\n\n  // save the sessionId\n  db.save(\"session\", session.sessionId, done);\n});\n\n// A Session with an automatic archiving\nopentok.createSession({ mediaMode: \"routed\", archiveMode: \"always\" }, function (\n  err,\n  session\n) {\n  if (err) return console.log(err);\n\n  // save the sessionId\n  db.save(\"session\", session.sessionId, done);\n});\n```\n\n### Generating Tokens\n\nOnce a Session is created, you can start generating Tokens for clients to use when connecting to it.\nYou can generate a token by calling the `OpenTok.generateToken(sessionId, options)` method. Another\nway is to call the `generateToken(options)` method of a Session object. The `options`\nparameter is an optional object used to set the role, expire time, and connection data of the Token.\nFor layout control in archives and broadcasts, the initial layout class list of streams published\nfrom connections using this token can be set as well.\n\n```javascript\n// Generate a Token from just a sessionId (fetched from a database)\ntoken = opentok.generateToken(sessionId);\n\n// Generate a Token from a session object (returned from createSession)\ntoken = session.generateToken();\n\n// Set some options in a Token\ntoken = session.generateToken({\n  role: \"moderator\",\n  expireTime: new Date().getTime() / 1000 + 7 * 24 * 60 * 60, // in one week\n  data: \"name=Johnny\",\n  initialLayoutClassList: [\"focus\"],\n});\n```\n\n### Working with archives\n\nYou can start the recording of an OpenTok Session using the `OpenTok.startArchive(sessionId, options, callback)` method. The `options` parameter is an optional object used to set the name of\nthe Archive. The callback has the signature `function(err, archive)`. The `archive` returned in\nthe callback is an instance of `Archive`. Note that you can only start an archive on a Session with\nconnected clients.\n\n```javascript\nopentok.startArchive(sessionId, { name: \"Important Presentation\" }, function (\n  err,\n  archive\n) {\n  if (err) {\n    return console.log(err);\n  } else {\n    // The id property is useful to save off into a database\n    console.log(\"new archive:\" + archive.id);\n  }\n});\n```\n\nYou can also disable audio or video recording by setting the `hasAudio` or `hasVideo` property of\nthe `options` parameter to `false`:\n\n```javascript\nvar archiveOptions = {\n  name: \"Important Presentation\",\n  hasVideo: false, // Record audio only\n};\nopentok.startArchive(sessionId, archiveOptions, function (err, archive) {\n  if (err) {\n    return console.log(err);\n  } else {\n    // The id property is useful to save to a database\n    console.log(\"new archive:\" + archive.id);\n  }\n});\n```\n\nBy default, all streams are recorded to a single (composed) file. You can record the different\nstreams in the session to individual files (instead of a single composed file) by setting the\n`outputMode` option to `'individual'` when you call the `OpenTok.startArchive()` method:\n\n```javascript\nvar archiveOptions = {\n  name: \"Important Presentation\",\n  outputMode: \"individual\",\n};\nopentok.startArchive(sessionId, archiveOptions, function (err, archive) {\n  if (err) {\n    return console.log(err);\n  } else {\n    // The id property is useful to save off into a database\n    console.log(\"new archive:\" + archive.id);\n  }\n});\n```\n\nYou can stop the recording of a started Archive using the `OpenTok.stopArchive(archiveId, callback)`\nmethod. You can also do this using the `Archive.stop(callback)` method an `Archive` instance. The\ncallback has a signature `function(err, archive)`. The `archive` returned in the callback is an\ninstance of `Archive`.\n\n```javascript\nopentok.stopArchive(archiveId, function (err, archive) {\n  if (err) return console.log(err);\n\n  console.log(\"Stopped archive:\" + archive.id);\n});\n\narchive.stop(function (err, archive) {\n  if (err) return console.log(err);\n});\n```\n\nTo get an `Archive` instance (and all the information about it) from an `archiveId`, use the\n`OpenTok.getArchive(archiveId, callback)` method. The callback has a function signature\n`function(err, archive)`. You can inspect the properties of the archive for more details.\n\n```javascript\nopentok.getArchive(archiveId, function (err, archive) {\n  if (err) return console.log(err);\n\n  console.log(archive);\n});\n```\n\nTo delete an Archive, you can call the `OpenTok.deleteArchive(archiveId, callback)` method or the\n`delete(callback)` method of an `Archive` instance. The callback has a signature `function(err)`.\n\n```javascript\n// Delete an Archive from an archiveId (fetched from database)\nopentok.deleteArchive(archiveId, function (err) {\n  if (err) console.log(err);\n});\n\n// Delete an Archive from an Archive instance, returned from the OpenTok.startArchive(),\n// OpenTok.getArchive(), or OpenTok.listArchives() methods\narchive.delete(function (err) {\n  if (err) console.log(err);\n});\n```\n\nYou can also get a list of all the Archives you've created (up to 1000) with your API Key. This is\ndone using the `OpenTok.listArchives(options, callback)` method. The parameter `options` is an\noptional object used to specify an `offset` and `count` to help you paginate through the results.\nThe callback has a signature `function(err, archives, totalCount)`. The `archives` returned from\nthe callback is an array of `Archive` instances. The `totalCount` returned from the callback is\nthe total number of archives your API Key has generated.\n\n```javascript\nopentok.listArchives({ offset: 100, count: 50 }, function (\n  error,\n  archives,\n  totalCount\n) {\n  if (error) return console.log(\"error:\", error);\n\n  console.log(totalCount + \" archives\");\n  for (var i = 0; i \u003c archives.length; i++) {\n    console.log(archives[i].id);\n  }\n});\n```\n\nNote that you can also create an automatically archived session, by passing in `'always'`\nas the `archiveMode` option when you call the `OpenTok.createSession()` method (see \"Creating\nSessions,\" above).\n\nFor composed archives, you can set change the layout dynamically, using the\n`OpenTok.setArchiveLayout(archiveId, type, stylesheet, screenshareType, callback)` method:\n\n```javascript\nopentok.setArchiveLayout(archiveId, type, null, null, function (err) {\n  if (err) return console.log(\"error:\", error);\n});\n```\n\nYou can set the initial layout class for a client's streams by setting the `layout` option when\nyou create the token for the client, using the `OpenTok.generateToken()` method. And you can\nchange the layout classes for streams in a session by calling the\n`OpenTok.setStreamClassLists(sessionId, classListArray, callback)` method.\n\nSetting the layout of composed archives is optional. By default, composed archives use the\n\"best fit\" layout (see [Customizing the video layout for composed\narchives](https://tokbox.com/developer/guides/archiving/layout-control.html)).\n\nFor more information on archiving, see the\n[OpenTok archiving developer guide](https://tokbox.com/developer/guides/archiving/).\n\n### Working with live streaming broadcasts\n\n_Important:_\nOnly [routed OpenTok sessions](https://tokbox.com/developer/guides/create-session/#media-mode)\nsupport live streaming broadcasts.\n\nTo start a [live streaming\nbroadcast](https://tokbox.com/developer/guides/broadcast/live-streaming) of an OpenTok session,\ncall the `OpenTok.startBroadcast()` method. Pass in three parameters: the session ID for the\nsession, options for the broadcast, and a callback function:\n\n```javascript\nvar broadcastOptions = {\n  outputs: {\n    hls: {},\n    rtmp: [\n      {\n        id: \"foo\",\n        serverUrl: \"rtmp://myfooserver/myfooapp\",\n        streamName: \"myfoostream\",\n      },\n      {\n        id: \"bar\",\n        serverUrl: \"rtmp://mybarserver/mybarapp\",\n        streamName: \"mybarstream\",\n      },\n    ],\n  },\n  maxDuration: 5400,\n  resolution: \"640x480\",\n  layout: {\n    type: \"verticalPresentation\",\n  },\n};\nopentok.startBroadcast(sessionId, broadcastOptions, function (\n  error,\n  broadcast\n) {\n  if (error) {\n    return console.log(error);\n  }\n  return console.log(\"Broadcast started: \", broadcast.id);\n});\n```\n\nSee the API reference for details on the `options` parameter.\n\nOn success, a Broadcast object is passed into the callback function as the second parameter.\nThe Broadcast object has properties that define the broadcast, including a `broadcastUrls`\nproperty, which has URLs for the broadcast streams. See the API reference for details.\n\nCall the `OpenTok.stopBroadcast()` method to stop a live streaming broadcast pass in the\nbroadcast ID (the `id` property of the Broadcast object) as the first parameter. The second\nparameter is the callback function:\n\n```javascript\nopentok.stopBroadcast(broadcastId, function (error, broadcast) {\n  if (error) {\n    return console.log(error);\n  }\n  return console.log(\"Broadcast stopped: \", broadcast.id);\n});\n```\n\nYou can also call the `stop()` method of the Broadcast object to stop a broadcast.\n\nCall the `Opentok.getBroadcast()` method, passing in a broadcast ID, to get a Broadcast object.\n\nYou can also get a list of all the Broadcasts you've created (up to 1000) with your API Key. This is\ndone using the `OpenTok.listBroadcasts(options, callback)` method. The parameter `options` is an\noptional object used to specify an `offset`, `count`, and `sessionId` to help you paginate through the results.\nThe callback has a signature `function(err, broadcasts, totalCount)`. The `broadcasts` returned from\nthe callback is an array of `Broadcast` instances. The `totalCount` returned from the callback is\nthe total number of broadcasts your API Key has generated.\n\n```javascript\nopentok.listBroadcasts({ offset: 100, count: 50 }, function (\n  error,\n  broadcasts,\n  totalCount\n) {\n  if (error) return console.log(\"error:\", error);\n\n  console.log(totalCount + \" broadcasts\");\n  for (var i = 0; i \u003c broadcasts.length; i++) {\n    console.log(broadcasts[i].id);\n  }\n});\n```\n\nTo change the broadcast layout, call the `OpenTok.setBroadcastLayout()` method,\npassing in the broadcast ID and the [layout\ntype](https://tokbox.com/developer/guides/broadcast/live-streaming/#configuring-video-layout-for-opentok-live-streaming-broadcasts).\n\nYou can set the initial layout class for a client's streams by setting the `layout` option when\nyou create the token for the client, using the `OpenTok.generateToken()` method. And you can\nchange the layout classes for streams in a session by calling the\n`OpenTok.setStreamClassLists(sessionId, classListArray, callback)` method.\n\nSetting the layout of a live streaming broadcast is optional. By default, live streaming broadcasts\nuse the \"best fit\" layout.\n\n### Sending signals\n\nYou can send a signal to all participants in an OpenTok Session by calling the\n`OpenTok.signal(sessionId, connectionId, payload, callback)` method and setting\nthe `connectionId` parameter to `null`:\n\n```javascript\nvar sessionId =\n  \"2_MX2xMDB-flR1ZSBOb3YgMTkgMTE6MDk6NTggUFNUIDIwMTN-MC2zNzQxNzIxNX2\";\nopentok.signal(sessionId, null, { type: \"chat\", data: \"Hello!\" }, function (\n  error\n) {\n  if (error) return console.log(\"error:\", error);\n});\n```\n\nOr send a signal to a specific participant in the session by calling the\n`OpenTok.signal(sessionId, connectionId, payload, callback)` method and setting all paramters,\nincluding `connectionId`:\n\n```javascript\nvar sessionId =\n  \"2_MX2xMDB-flR1ZSBOb3YgMTkgMTE6MDk6NTggUFNUIDIwMTN-MC2zNzQxNzIxNX2\";\nvar connectionId = \"02e80876-02ab-47cd-8084-6ddc8887afbc\";\nopentok.signal(\n  sessionId,\n  connectionId,\n  { type: \"chat\", data: \"Hello!\" },\n  function (error) {\n    if (error) return console.log(\"error:\", error);\n  }\n);\n```\n\nThis is the server-side equivalent to the signal() method in the OpenTok client SDKs. See\n[OpenTok signaling developer guide](https://www.tokbox.com/developer/guides/signaling/) .\n\n### Disconnecting participants\n\nYou can disconnect participants from an OpenTok Session using the\n`OpenTok.forceDisconnect(sessionId, connectionId, callback)` method.\n\n```javascript\nopentok.forceDisconnect(sessionId, connectionId, function (error) {\n  if (error) return console.log(\"error:\", error);\n});\n```\n\nThis is the server-side equivalent to the forceDisconnect() method in OpenTok.js:\n\u003chttps://www.tokbox.com/developer/guides/moderation/js/#force_disconnect\u003e.\n\n### Forcing clients in a session to mute published audio\n\nYou can force the publisher of a specific stream to stop publishing audio using the \n`Opentok.forceMuteStream(sessionId)`method.\n\nYou can force the publisher of all streams in a session (except for an optional list of streams)\nto stop publishing audio using the `Opentok.forceMuteAll()` method.\nYou can then disable the mute state of the session by calling the\n`Opentok.disableForceMute()` method.\n\n### Working with SIP Interconnect\n\nYou can add an audio-only stream from an external third-party SIP gateway using the SIP Interconnect\nfeature. This requires a SIP URI, the session ID you wish to add the audio-only stream to, and a\ntoken to connect to that session ID.\n\n```javascript\nvar options = {\n  from: \"15551115555\",\n  secure: true,\n};\nopentok.dial(sessionId, token, sipUri, options, function (error, sipCall) {\n  if (error) return console.log(\"error: \", error);\n\n  console.log(\n    \"SIP audio stream Id: \" +\n      sipCall.streamId +\n      \" added to session ID: \" +\n      sipCall.sessionId\n  );\n});\n```\n\nFor more information, see the\n[OpenTok SIP Interconnect developer guide](https://tokbox.com/developer/guides/sip/).\n\n### Getting Stream Info\n\nYou can get information on an active stream in an OpenTok session:\n\n```javascript\nvar sessionId =\n  \"2_MX6xMDB-fjE1MzE3NjQ0MTM2NzZ-cHVTcUIra3JUa0kxUlhsVU55cTBYL0Y1flB\";\nvar streamId = \"2a84cd30-3a33-917f-9150-49e454e01572\";\nopentok.getStream(sessionId, streamId, function (error, streamInfo) {\n  if (error) {\n    console.log(error.message);\n  } else {\n    console.log(stream.id); // '2a84cd30-3a33-917f-9150-49e454e01572'\n    console.log(stream.videoType); // 'camera'\n    console.log(stream.name); // 'Bob'\n    console.log(stream.layoutClassList); // ['main']\n  }\n});\n```\n\nPass a session ID, stream ID, and callback function to the `OpenTok.getStream()` method.\nThe callback function is called when the operation completes. It takes two parameters:\n`error` (in the case of an error) or `stream`. On sucessful completion, the `stream` object\nis set, containing properties of the stream.\n\nTo get information on _all_ active streams in a session, call the `OpenTok.listStreams()` method,\npassing in a session ID and a callback function. Upon sucess, the callback function is invoked\nwith an array of Stream objects passed into the second parameter:\n\n```javascript\nopentok.listStreams(sessionId, function(error, streams) {\n  if (error) {\n    console.log(error.message);\n  } else {\n    streams.map(function(stream) {\n      console.log(stream.id); // '2a84cd30-3a33-917f-9150-49e454e01572'\n      console.log(stream.videoType); // 'camera'\n      console.log(stream.name); // 'Bob'\n      console.log(stream.layoutClassList); // ['main']\n    }));\n  }\n});\n```\n\n# Samples\n\nThere are sample applications included in this repository. To get going as fast as possible,\nclone the whole repository and read the README in each of the sample directories:\n\n- [HelloWorld](sample/HelloWorld/README.md)\n- [Archiving](sample/Archiving/README.md)\n- [SipInterconnect](sample/StreamInfo/README.md)\n\n## Documentation\n\nReference documentation is available at \u003chttps://tokbox.com/developer/sdks/node/reference/index.html\u003e.\n\n## Requirements\n\nYou need an OpenTok API key and API secret, which you can obtain by logging into your\n[TokBox account](https://tokbox.com/account).\n\nThe OpenTok Node SDK requires Node.js 14 or higher. It may work on older versions but they are no longer tested.\n\n## Release Notes\n\nSee the [Releases](https://github.com/opentok/opentok-node/releases) page for details\nabout each release.\n\n### Important changes since v2.2.0\n\n**Changes in v2.2.3:**\n\nThe default setting for the `createSession()` method is to create a session with the media mode set\nto relayed. In previous versions of the SDK, the default setting was to use the OpenTok Media Router\n(media mode set to routed). In a relayed session, clients will attempt to send streams directly\nbetween each other (peer-to-peer); if clients cannot connect due to firewall restrictions, the\nsession uses the OpenTok TURN server to relay audio-video streams.\n\n**Changes in v2.2.0:**\n\nThis version of the SDK includes support for working with OpenTok archives.\n\nThe `createSession()` method has changed to take one parameter: an `options` object that has `location`\nand `mediaMode` properties. The `mediaMode` property replaces the `properties.p2p.preference`\nparameter in the previous version of the SDK.\n\nThe `generateToken()` has changed to take two parameters: the session ID and an `options` object that has `role`, `expireTime` and `data` properties.\n\nSee the reference documentation\n\u003chttp://www.tokbox.com/opentok/libraries/server/node/reference/index.html\u003e and in the\ndocs directory of the SDK.\n\n## Development and Contributing\n\nInterested in contributing? We :heart: pull requests! See the [Development](DEVELOPING.md) and\n[Contribution](CONTRIBUTING.md) guidelines.\n\n## Getting Help\n\nWe love to hear from you so if you have questions, comments or find a bug in the project, let us know! You can either:\n\n- Open an issue on this repository\n- See \u003chttps://support.tokbox.com/\u003e for support options\n- Tweet at us! We're [@VonageDev on Twitter](https://twitter.com/VonageDev)\n- Or [join the Vonage Developer Community Slack](https://developer.nexmo.com/community/slack)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentok%2Fopentok-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopentok%2Fopentok-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentok%2Fopentok-node/lists"}