- product:video - sdk:relaybrowser3 - language:javascript - language:nodejs # Simple Video Demo SignalWires Video API allows you to host real-time video calls and conferences on your website or app. In this guide, we will use SignalWire APIs in three steps to create a minimal full-stack video-calling website. This is what we will cover: 1. Registering with SignalWire to [obtain your API key and Project ID](#obtaining-your-api-key-and-project-id) 2. Writing a minimal [backend server](#backend) in Node.js. This is a simple proxy server, so if you prefer you can use any platform such as PHP or Python. 3. Developing a simple [frontend web app](#frontend) in JavaScript. The SignalWire Browser SDK will do most of the work for us. When the site is finished, it will look something like this: Before we begin, try using the [demo app](https://codesandbox.io/s/simple-video-demo-1ntfr2?file=/src/frontend/index.js). This is what we will build, step by step. Feel free to explore the codebase. You dont necessarily have to understand everything right now, but try tinkering with it. When youre ready, lets set up API access. ## Obtaining your API key and Project ID First, we will need access to the SignalWire APIs. If you already have a SignalWire account, can [sign in to the SignalWire website](https://signalwire.com/signin). If youre not already registered, you can [**sign up**](https://signalwire.com/signups/new) in trial mode, which comes with a $5 credit. This will be plenty to follow along with this guide. Once youve signed up and verified your email, create a new project. Chose any name you like. For this example, we will use hello world. After the project has been created, youll be taken to that projects page. Two important pieces of information about our project are displayed there: - **Space URL:** Youll use this URL to access SignalWire APIs - **Project ID:** Youll use this UUID to specify your project to the API There is one more piece of information that we need from our new project. We need to generate an **API token** to access SignalWires APIs from our own code. We can do that by navigating to the API page from the sidebar. Once you have navigated to the API page, click on **Create Token**. Give it an easily idenitifable name, and make sure that the **Video scope** is enabled. Then hit **Save**. After the token is created, you will see it listed in the table. :::caution API Tokens are confidential It is important that the API tokens are not publically exposed. They can be used to make API requests on your behalf. Take extreme care to make sure that the tokens are not pushed to GitHub or exposed in frontend code. For Node.js backends, you can use [dotenv files](https://www.npmjs.com/package/dotenv) or similar mechanisms to safely store confidential constants. ::: Now that we have collected the Project ID, the Space URL, and the API token, we can start writing our application. ## Backend ### Why do I need my own backend? As mentioned in the previous section, API tokens must be kept confidential. When you build a web application or any application that runs on a users device, the code running on the device should be considered _untrusted_ (secrets can be stolen). S ince you must use the API token from a _trusted_ environment, you do so in your own server. Having your own backend server also allows you to build custom authorization policies instead of giving every client admin access. The figure below illustrates the typical network interaction we are building. Your server can directly access the SignalWire servers (for example, to get a list of active rooms). However, for a client to interact with SignalWire servers, it must first ask _your server_ to provide a limited-scope token (we call this the _Video Room Token_). :::info What is the difference between the API token and the Video Room Token? The **API token** gives full access to SignalWire APIs. Whoever owns the API token can, for example, delete any room, mute or unmute any participant, and so on without limitations. You may only use the API token **in your server** to communicate with SignalWire. The **Video Room Token** is a limited-scope token that clients can use to access SignalWire APIs without knowing the API token. Clients must ask your proxy server for a Video Room Token. Your server will obtain it from SignalWire servers and pass it back to the client. Video Room Tokens are associated with a given <_user_, _room_> pair, so you can think of them as a personal key for a given user to access a given room. Your server sets the permissions for each Video Room Token, for example, whether they are allowed to mute other users. ::: ### Getting a Video Room Token using cURL Lets take a look at how our backend will use the API token to get a Video Room Token. To get a token from the REST API for a user with name john and a room office with only video muting permissions, we can use this call: shell curl --request POST \ --url https://your_space_url.signalwire.com/api/video/room_tokens \ --header Content-Type: application/json \ --data {user_name: john, room_name: office, permissions: [room.self.video_mute]} You can see a complete list of possible [permissions](/rest/signalwire-rest/overview/permissions) and [video token parameters](/rest/signalwire-rest/endpoints/video/create-room-token) in our documentation. The JSON response from the API will look like this and can be safely sent to the client: json { token: eyJ0eXAiOiJWUlQiLCJhbGciOiJIUzUxMiJ9.eyJpYXQiOjE2MzI0OTE3ODAsImp0aSI6ImM2NmU3ODlkLTJmMjItMTIzNC1hNzMzLThlZjA2MzdmNWI2YiIsInN1YiI6ImExNmQ4ZjllLTIxNjYtNGU4Mi01Njc4LWE0ODQwZjIxN2JjMyIsInUiOiJqb2huIiwiciI6Im9mZmljZSIsInMiOlsicm9vbS5yZWNvcmRpbmciXSwiYWNyIjp0cnVlfQ.qYQwQ1PEnzGbAIb1RoVuYLf0mlqApi15wSC2n7QMCFP4M7jOjOIb_Ia_BhKnbnTHb7sI78d2jS7f_qsFV2OHLw } ### Getting a Video Room Token using your own server Instead of using curl, and to allow for more granular control over permissions alongside user authentication, well create a server to accept an incoming request for a Video Room Token, obtain the Video Room Token, and send it back to the client. Our server only needs to expose a single endpoint, which we will call /get_token (but it can be anything you want). javascript // Auth constants to be stored in a dotenv file (or equivalent) with gitignore const auth = { username: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx, // Project ID password: PTxxx...xxx, // API token }; const apiurl = https://
Simple Video Demo
). It will serve as the container for the video stream. When roomSession.join is called, the SDK will join the room, and the video will appear in rootElement. These pieces are all you need to get the video up and running. However, we can polish our application by using the Events included on the Room Session object. ### Using Events The Room Session object supports the standard .on() method to attach event listeners and the corresponding .off() method to detach them. **You should subscribe to events after the room is created but before joining the room.** Some of the events you might subscribe to are: - room.joined: you have joined the room - room.updated: a room property has been updated - room.ended: the room has ended - member.updated: a member property has changed (e.g., video muted) - member.updated.audio_muted: the audio_muted state has changed for a member - member.updated.video_muted: the video_muted state has changed for a member - member.updated.visible: the member is now visible in the video layout - member.left: a member left the room - layout.changed: the layout of the room has changed Find the complete list in our [API reference](/docs/sdks/reference/browser-sdk/video/video-roomsession.mdx#events). Heres how we can use some these events in our example program: javascript roomSession.on(room.joined, (e) => logevent(You joined the room)); roomSession.on(member.joined, (e) => logevent(e.member.name + has joined the room)); roomSession.on(member.left, (e) => logevent(e.member.id + has left the room)); ### Putting it All Together All the above ideas can be combined to create the following function, which well use (with minor variations) in the frontend. Please note this snippet includes references to a user interface which you can see in our [demo](https://codesandbox.io/s/simple-video-demo-1ntfr2?file=/src/frontend/index.js). javascript async function join() { const username = $(usernameinput).value.trim(); const roomname = $(roomnameinput).value.trim(); gotopage(loading); try { token = await axios.post(backendurl + /get_token, { user_name: username, room_name: roomname, }); console.log(token.data); token = token.data.token; try { try { roomSession = new SignalWire.Video.RoomSession({ token, rootElement: document.getElementById(root), }); } catch (e) { console.log(e); } roomSession.on(room.joined, (e) => logevent(You joined the room)); roomSession.on(member.joined, (e) => logevent(e.member.name + has joined the room) ); roomSession.on(member.left, (e) => logevent(e.member.id + has left the room)); await roomSession.join(); } catch (error) { console.error(Something went wrong, error); } gotopage(videoroom); } catch (e) { console.log(e); alert(Error encountered. Please try again.); gotopage(getusername); } } Please visit our [GitHub page](https://github.com/signalwire/guides/tree/main/Video/Simple%20Video%20Demo) to see complete code or fork the repository. ## Conclusion Here is the final result of our development with a preview of some added features: The most noteworthy thing about SignalWire Video technology is that it only streams a single video stream no matter how many participants there are. The video is composited on powerful SignalWire servers by stitching all of the individual video streams together. So you can invite as many people as you like to your virtual video party. Your app will run without a hitch. **What now?** If you would like a custom approach that adds to what we developed here, visit one of our guides below. If you prefer a guide to build a standard, polished video application from scratch, you can see our [Zoom Clone Guide](guides/video-api/examples/javascript/zoom-clone-2/index.mdx).