{"id":19845444,"url":"https://github.com/opentok/learning-opentok-web","last_synced_at":"2025-07-30T02:07:43.464Z","repository":{"id":24073744,"uuid":"27460300","full_name":"opentok/learning-opentok-web","owner":"opentok","description":null,"archived":false,"fork":false,"pushed_at":"2020-08-03T15:10:20.000Z","size":45,"stargazers_count":27,"open_issues_count":1,"forks_count":45,"subscribers_count":75,"default_branch":"basics","last_synced_at":"2024-04-08T16:02:35.867Z","etag":null,"topics":["javascript","opentok","tokbox","web","webrtc"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"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":null,"code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-12-03T00:08:47.000Z","updated_at":"2020-11-16T14:18:52.000Z","dependencies_parsed_at":"2022-07-07T20:31:19.934Z","dependency_job_id":null,"html_url":"https://github.com/opentok/learning-opentok-web","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Flearning-opentok-web","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Flearning-opentok-web/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Flearning-opentok-web/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opentok%2Flearning-opentok-web/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opentok","download_url":"https://codeload.github.com/opentok/learning-opentok-web/tar.gz/refs/heads/basics","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224278479,"owners_count":17285080,"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","opentok","tokbox","web","webrtc"],"created_at":"2024-11-12T13:07:53.241Z","updated_at":"2024-11-12T13:07:53.900Z","avatar_url":"https://github.com/opentok.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Learning OpenTok Web\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\nThis sample client app shows how to accomplish the following using the OpenTok.js SDK:\n\n* Initialize and connect to an OpenTok session, publish to a stream and subscribe to a stream\n* The ability to record the session, stop the recording, and view the recording\n* Text chat for the participants\n\nThe code for this sample is found the following git branches:\n\n* basics -- This branch shows you how to connect to the OpenTok session, publish a stream, subscribe to a stream, and mute audio.\n\n* archiving -- This branch shows you how to record the session.\n\n* signaling -- This branch shows you how to use the OpenTok signaling API to implement text chat.\n\nYou will also need to clone the OpenTok GettingStarted repo and run its code on a PHP-enabled web server. See the next section for more information.\n\n## Setting up the test web service\n\nThe [Learning OpenTok PHP](https://github.com/opentok/learning-opentok-php) repo includes code for\nsetting up a web service that handles the following API calls:\n\n* \"/session\" -- The JS client calls this endpoint to get an OpenTok session ID, token, and API key.\n* \"/start\" -- The JS client calls this endpoint to start recording the OpenTok session to an archive.\n* \"/stop\" -- The JS client calls this endpoint to stop recording the archive.\n* \"/view\" -- The JS client loads this endpoint in a web browser to display the archive recording.\n\nDownload the repo and run its code on a PHP-enabled web server. If you do not have a PHP\nserver set up, you can use Heroku to run a remote test server -- see [Automatic deployment to\nHeroku](https://github.com/opentok/learning-opentok-php#automatic-deployment-to-heroku).\n\n## Configuring the application\n\n1. Clone this repository. This repository as mentioned earlier has three branches.\n\n2. When you do a git clone, you check out the `basics` branch. To check out other branches you need\nto execute the following commands:\n\n        git fetch\n        git checkout -b signaling origin/signaling\n\n        git checkout -b archiving origin/archiving\n\n3. Now, switch to `basics` branch using `git checkout basics` command. Navigate to `web/js`\ndirectory and make a copy of the sampleconfig.js file named config.js.\n\n4. Edit the config.js file and set the value for SAMPLE_SERVER_BASE_URL.\n\n   If you deployed a the test web service to a local PHP server, set this to the following:\n\n        var SAMPLE_SERVER_BASE_URL = 'http://localhost:8080';\n\n   If you deployed this to Heroku, set this to the following:\n\n        var SAMPLE_SERVER_BASE_URL = 'https://YOUR-HEROKU-APP-URL';\n\n   ***Do not add the trailing slash of the URL.***\n\n5. The web app lives at index.html. You will need to run this on a web server. If you have Python on\nyour system, you can start the web server by running `python -m SimpleHTTPServer 8000` in the `web` folder.\n\n6. Once you have the server running open the index.html in a supported browser. For example, if\nyour local web server is running on port 8000, load the following URL:\n\n   http://localhost:8000\n\n   The OpenTok.js library is supported in Chrome, Firefox, and Internet Explorer 10 - 11.\n   (Internet Explorer requires installation of the OpenTok plugin, which the libary asks you\n   to install, if you haven't already.)\n\n7. When prompted, grand the page access to your camera and microphone.\n\n8. Mute the speaker on your computer, and then load the page again in another browser tab.\n\n   You will see a person-to-person video chat session using OpenTok.\n\n## Getting an OpenTok session ID, token, and API key\n\nAn OpenTok session connects different clients letting them share audio-video streams and send\nmessages. Clients in the same session can include iOS, Android, and web browsers.\n\n**Session ID** -- Each client that connects to the session needs the session ID, which identifies\nthe session. Think of a session as a room, in which clients meet. Depending on the requirements of\nyour application, you will either reuse the same session (and session ID) repeatedly or generate\nnew session IDs for new groups of clients.\n\n*Important*: This demo application assumes that only two clients -- the local Web client and\nanother client -- will connect in the same OpenTok session. For test purposes, you can reuse the\nsame session ID each time two clients connect. However, in a production application, your\nserver-side code must create a unique session ID for each pair of clients. In other applications,\nyou may want to connect many clients in one OpenTok session (for instance, a meeting room) and\nconnect others in another session (another meeting room). For examples of apps that connect users\nin different ways, see the OpenTok ScheduleKit, Presence Kit, and Link Kit [Starter Kit\napps](https://tokbox.com/opentok/starter-kits/).\n\nSince this app uses the OpenTok archiving feature to record the session, the session must be set to\nuse the routed media mode, indicating that it will use the OpenTok Media Router. The OpenTok Media\nRouter provides other advanced features (see [The OpenTok Media Router and media\nmodes](https://tokbox.com/opentok/tutorials/create-session/#media-mode)). If your application does\nnot require the features provided by the OpenTok Media Router, you can set the media mode to\nrelayed.\n\n**Token** -- The client also needs a token, which grants them access to the session. Each client is\nissued a unique token when they connect to the session. Since the user publishes an audio-video\nstream to the session, the token generated must include the publish role (the default). For more\ninformation about tokens, see the OpenTok [Token creation\noverview](https://tokbox.com/opentok/tutorials/create-token/).\n\n**API key** -- The API key identifies your OpenTok developer account.\n\nUpon starting up, the application executes the following code in the app.js file:\n\n    $(document).ready(function() {\n      // Make an Ajax request to get the OpenTok API key, session ID, and token from the server\n      $.get(SAMPLE_SERVER_BASE_URL + '/session', function(res) {\n        apiKey = res.apiKey;\n        sessionId = res.sessionId;\n        token = res.token;\n\n        initializeSession();\n      });\n    });\n\nThis method makes an XHR (or Ajax request) to the \"/session\" endpoint of the web service. The web\nservice returns an HTTP response that includes the session ID, the token, and API key formatted as\nJSON data:\n\n    {\n         \"sessionId\": \"2_MX40NDQ0MzEyMn5-fn4\",\n         \"apiKey\": \"12345\",\n         \"token\": \"T1==cGFydG5lcl9pZD00jg=\"\n    }\n\n## Connecting to the session\n\nUpon obtaining the session ID, token, and API, the app calls the `initializeSession()` method.\nFirst, this method initializes a Session object:\n\n    // Initialize Session Object\n    var session = OT.initSession(apiKey, sessionId);\n\nThe `OT.initSession()` method takes two parameters -- the OpenTok API key and the session ID. It\ninitializes and returns an OpenTok Session object.\n\nThe `connect()` method of the Session object connects the client application to the OpenTok\nsession. You must connect before sending or receiving audio-video streams in the session (or before\ninteracting with the session in any way). The `connect()` method takes two parameters -- a token\nand a completion handler function:\n\n    // Connect to the Session\n    session.connect(token, function(error) {\n\n      // If the connection is successful, initialize a publisher and publish to the session\n      if (!error) {\n        var publisherOptions = {\n          insertMode: 'append',\n          width: '100%',\n          height: '100%'\n        };\n        var publisher = OT.initPublisher('publisher', publisherOptions, function(error) {\n          if (error) {\n            console.log('There was an error initilizing the publisher: ', error.name, error.message);\n            return;\n          }\n          session.publish(publisher, function(error) {\n            if (error) {\n              console.log('There was an error publishing: ', error.name, error.message);\n            }\n          });\n        });\n      } else {\n        console.log('There was an error connecting to the session:', error.name, error.message);\n      }\n    });\n\nAn error object is passed into the completion handler of the `Session.connect()` method if the\nclient fails to connect to the OpenTok session. Otherwise, no error object is passed in, indicating\nthat the client connected successfully to the session.\n\nThe Session object dispatches a `sessionDisconnected` event when your client disconnects from the\nsession. The application defines an event handler for this event:\n\n    session.on('sessionDisconnected', function(event) {\n      console.log('You were disconnected from the session.', event.reason);\n    });\n\n## Publishing an audio video stream to the session\n\nUpon successfully connecting to the OpenTok session (see the previous section), the application\ninitializes an OpenTok Publisher object and publishes an audio-video stream to the session. This is\ndone inside the completion handler for the connect() method, since you should only publish to the\nsession once you are connected to it.\n\nThe Publisher object is initialized as shown below. The `OT.initPublisher()` method takes three\noptional parameters:\n\n* The target DOM element or DOM element ID for placement of the publisher video\n* The properties of the publisher\n* The completion handler\n\n```\nvar publisherOptions = {\n  insertMode: 'append',\n  width: '100%',\n  height: '100%'\n};\nvar publisher = OT.initPublisher('publisher', publisherOptions, function(error) {\n  if (error) {\n    console.log('There was an error initializing the publisher: ', error.name, error.message);\n    return;\n  }\n  session.publish(publisher, function(error) {\n    if (error) {\n      console.log('There was an error publishing: ', error.name, error.message);\n    }\n  });\n});\n```\n\nOnce the Publisher object is initialized, we publish to the session using the `publish()`\nmethod of the Session object:\n\n    session.publish(publisher);\n\n## Subscribing to another client's audio-video stream\n\nThe Session object dispatches a `streamCreated` event when a new stream (other than your own) is\ncreated in a session. A stream is created when a client publishes to the session. The\n`streamCreated` event is also dispatched for each existing stream in the session when you first\nconnect. This event is defined by the StreamEvent object, which has a `stream` property,\nrepresenting stream that was created. The application adds an event listener for the\n`streamCreated` event and subscribes to all streams created in the session using the\n`Session.subscribe()` method:\n\n    // Subscribe to a newly created stream\n    session.on('streamCreated', function(event) {\n      var subscriberOptions = {\n        insertMode: 'append',\n        width: '100%',\n        height: '100%'\n      };\n      session.subscribe(event.stream, 'subscriber', subscriberOptions, function(error) {\n        if (error) {\n          console.log('There was an error publishing: ', error.name, error.message);\n        }\n      });\n    });\n\nThe `Session.subscribe()` method takes four parameters:\n\n* The Stream object to which we are subscribing\n* The target DOM element or DOM element ID (optional) for placement of the subscriber video\n* A set of properties (optional) that customize the appearance of the subscriber view\n* The completion handler function (optional) that is called when the method completes\n  successfully or fails\n\n## Recording the session to an archive\n\n**Important**: To view the code for this functionality, switch to the *archiving* branch of this\ngit repository.\n\nThe OpenTok archiving API lets you record a session's audio-video streams to MP4 files. You use\nserver-side code to start and stop archive recordings. In the config.js file, you set the\n`SAMPLE_SERVER_BASE_URL` variable to the base URL of the web service the app calls to start archive\nrecording, stop recording, and play back the recorded video.\n\nThe archiving application uses the same code available in the basics branch to initialize an\nOpenTok session, connect to the session, publish a stream, and subscribe to stream in the session.\nIf you have not already gotten familiar with the code in that branch, consider doing so before\ncontinuing (see the previous sections).\n\nTo start recording the video stream, the user clicks the Start Recording button which invokes the\n`startArchive()` method in app.js. This method in turn sends an XHR (or Ajax) request to server.\nThe session ID of the session that needs to be recorded is passed as a URL parameter to the server.\nAs soon as the `startArchive()` method is called, the Start Recording button is hidden and the Stop\nRecording button is displayed.\n\n    function startArchive() {\n      $.post(SAMPLE_SERVER_BASE_URL + '/start/' + sessionId);\n      $('#start').hide();\n      $('#stop').show();\n    }\n\nTo stop the recording, the user clicks the Stop Recording button, which invokes the `stopArchive()`\nmethod. This method is similar to the `startArchive()` method in that it sends an Ajax request to\nthe server to stop the archive. The only difference is that this method passes the archive ID of\nthe archive that needs to be stopped as a URL parameter instead of the sessionId. The Stop\nRecording button is hidden and the View Archive button is enabled.\n\n    function stopArchive() {\n      $.post(SAMPLE_SERVER_BASE_URL + '/stop/' + archiveID);\n      $('#stop').hide();\n      $('#start').show();\n      $('#view').prop('disabled', false);\n    }\n\nTo download the archive that has just been recorded, the user clicks View Archive button which\ninvokes the `viewArchive()` method. This method is similar to the `startArchive()` and\n`stopArchive()` methods in that it sends an Ajax request to the server. The server code has the\nlogic to check if the archive is available for download or not. If it is available, the application\nis redirected to the archive page. If not, a new page is loaded which continuously checks whether\nthe archive is available for download or not and loads it when it is available.\n\n*Notes:*\n\n* In most applications, control of the archive recording would not be granted to each\nend-user.\n\n* You can have automatically archived sessions, which are recorded whenever a client\nstarts publishing a stream.\n\n* You will want to set up an Amazon S3 or Microsoft Azure target\nfor storage of your archive recordings.\n\nFor more information, see the [OpenTok archiving developer\nguide](https://tokbox.com/developer/guides/archiving/).\n\n## Using the signaling API to implement text chat\n\n**Important**: To view the code for this functionality, switch to the *signaling* branch of this\ngit repository.\n   \nText chat is implemented using the OpenTok signaling API. A signal is sent using the `signal()`\nmethod of the Session object. To receive a signal a client needs to listen to the `signal` event\ndispatched by the session object.\n\nIn our application, when the user enters text in the input text field, the following code is\nexecuted:\n\n    form.addEventListener('submit', function(event) {\n      event.preventDefault();\n\n      session.signal({\n          type: 'msg',\n          data: msgTxt.value\n        }, function(error) {\n          if (error) {\n            console.log('Error sending signal:', error.name, error.message);\n          } else {\n            msgTxt.value = '';\n          }\n        });\n      });\n    });\n\nThis method calls the `signal()` method of the Session object, which sends a signal to all clients\nconnected to the OpenTok session. Each signal is defined by a `type` property identifying the type\nof message (in this case `\"msg\"`) and a `data` property containing the message. The text entered is\nsent in the data property of the signal method.\n\nWhen another client connected to the session (in this app, there is only one) sends a message, the\nsession's `signal` event handler is invoked:\n\n    session.on('signal:msg', function(event) {\n      var msg = document.createElement('p');\n      msg.innerText = event.data;\n      msg.className = event.from.connectionId === session.connection.connectionId ? 'mine' : 'theirs';\n      msgHistory.appendChild(msg);\n      msg.scrollIntoView();\n    });\n\nThis method checks to see if the signal was sent by the local web client or by the other client\nconnected to the session:\n\n    event.from.connectionId === session.connection.connectionId ? 'mine' : 'theirs';\n\nThe Session object represents your OpenTok session. It has a `connection` property, which has a\n`connectionId` property. The event object represents the event associated with this signal. It has\na `from` property (which is a Connection object) with a `connectionId` property. This represents\nthe connection ID of the client sending the signal. If these match, the signal was sent by the\nlocal web client.\n\nThe data associated with the event is then appended as a child of the `history` DOM element.\n\nThis app uses the OpenTok signaling API to implement text chat. However, you can use the signaling\nAPI to send messages to other clients (individually or collectively) connected to the session.\n\n## Development and Contributing\n\nInterested in contributing? We :heart: pull requests! See the [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](https://twitter.com/VonageDev) on Twitter\n- Or [join the Vonage Developer Community Slack](https://developer.nexmo.com/community/slack)\n\n## Further Reading\n\n- Check out the Developer Documentation at \u003chttps://tokbox.com/developer/\u003e\n- [API reference](https://tokbox.com/developer/sdks/js/reference/) -- Provides details on\nthe OpenTok.js API\n- [Developer guides](https://tokbox.com/developer/guides/) -- Includes conceptual information and code samples for all OpenTok features","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentok%2Flearning-opentok-web","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopentok%2Flearning-opentok-web","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopentok%2Flearning-opentok-web/lists"}