Migrating Your WebRTC Application from Twilio to AWS: A Developer’s Guide

On December 5th, 2023 Twilio announced the End of Life (EOL) of their Programmable Video product. This abrupt offering discontinuation has forced many customers to explore alternative options for running smart camera or video streaming solutions. In this blog, we will highlight some considerations that customers can utilize as guidance to shape their migration strategy.

Scalability, depth and breadth of capabilities, and security implementation are critical parameters that will influence the design of your video streaming solutions and the applications built around it. Designing for long term reliability requires taking into consideration how your application will handle high traffic volumes and video quality. These are common challenges while delivering for range of devices through available Software Development Kits (SDKs). Therefore, when your existing technology requires code changes to lift-and-shift to new WebRTC technology, it should include a purpose-fit code migration strategy that addresses the previously mentioned challenges and provides comprehensive testing routine to frequently cross-check your migration progress.

Amazon Kinesis Video Streams, a managed cloud service that makes it easy for you to securely stream video from connected devices to AWS for analytics, machine learning (ML), playback, and other processing. It offers an ideal path for you to easily support and integrate near real-time video streams from connected cameras and similar devices for use cases, such as surveillance, live streaming, and video analysis. Moreover, Amazon Kinesis Video Streams integration with other AWS services allows you to extensively process and store large volumes of data, making it easy for you to migrate your existing solution with minimal disruption. In this blog, our example code will focus on helping you migrate your existing Twilio-based streaming solution to AWS with the help of Amazon Kinesis Video Streams. But, before we go further into the specific implementation with Amazon Kinesis Video Streams, it is critical that you learn about all the available options and make an informed choice aligned with your use case and business needs. Therefore, please read Choose the right AWS video service for your use case to familiarize yourself with all feasible options.

Twilio to Amazon Kinesis Video Streams Implementation

The code examples below provide a scenario where you may be replacing Twilio with Amazon Kinesis Video Streams with WebRTC functionality. It demonstrates basic WebRTC functionality with Twilio and replacing it with Amazon Kinesis Video Streams. This code doesn’t dive into many complexities of a real-world application, such as complete signaling logic, ICE candidate handling, and UI interaction. To get more familiar with the WebRTC protocols and Amazon Kinesis Video Stream signaling, please review some of the reference materials mentioned below.

Prerequisites

    • An AWS account
    • Kinesis Video Streams service permissions via IAM role or IAM policy
    • An EC2 instance or serverless ability to run NodeJS with Express would also be necessary to replicate the code examples.

Setting up a WebRTC Connection With Twilio

The source code below demonstrates Twilio API use for room creation, token generation and passing the security token to the client to allow connection to the room. Your use and classes may vary depending on your implementation. For the purpose of keeping this example simple, our main JavaScript class file is where these functions are defined.

// use dotenv configuration
require("dotenv").config();

// use uuid for guids
const { v4: uuidv4 } = require("uuid");

/*
*  This section is twilio token handling, room creation and authn
*  This is later replaced with a kvs signaling object for use
*/

const AccessToken = require("twilio").jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;

// ExpressJS is used to serve the application and handle HTTP posts, gets, etc
const express = require("express");
const app = express();
const port = 5000;

// use the Express JSON middleware
app.use(express.json());


// create the twilioClient
const twilioClient = require("twilio")(
  process.env.TWILIO_API_KEY,
  process.env.TWILIO_API_SECRET,
  { accountSid: process.env.TWILIO_ACCOUNT_SID }
);

const findOrCreateRoom = async (roomName) => {
    try {
      // see if the room exists already. If it doesn't, this will throw
      // error 20404.
      await twilioClient.video.v1.rooms(roomName).fetch();
    } catch (error) {
      // the room was not found, so create it
      if (error.code == 20404) {
        await twilioClient.video.v1.rooms.create({
          uniqueName: roomName,
          type: "go",
        });
      } else {
        // let other errors bubble up
        throw error;
      }
    }
  };

  const getAccessToken = (roomName) => {
    // create an access token
    const token = new AccessToken(
      process.env.TWILIO_ACCOUNT_SID,
      process.env.TWILIO_API_KEY,
      process.env.TWILIO_API_SECRET,
      // generate a random unique identity for this participant
      { identity: uuidv4() }
    );
    // create a video grant for this specific room
    const videoGrant = new VideoGrant({
      room: roomName,
    });
  
    // add the video grant
    token.addGrant(videoGrant);
    // serialize the token and return it
    return token.toJwt();
  };

The above function definitions facilitate acquisition of a new Twilio room or joining one if it already exists. Twilio utilizes JSON Web Tokens (JWT) to grant access to new or existing rooms. The JWT is generated from Twilio credentials then granted to the room. These server-generated tokens are then passed to clients to connect to a room.

Migrating to Amazon Kinesis Video Streams

The JavaScript source code below demonstrates using the AWS SDK to create an Amazon Kinesis Video Streams signaling channel for use. Again, our main JavaScript class file is where these functions are defined; however, you may desire to create new classes or file nomenclature to create new instantiations of Kinesis Video Stream clients. Producer and client applications require valid credentials to access Amazon Kinesis video streams. Though not demonstrated below, this can be achieved with temporary security credentials in IAM for your producer and client application access.

//  This is the KVS signaling replacement
   
// Import AWS SDK and necessary components
const AWS = require('aws-sdk');
const { KinesisVideo, KinesisVideoSignalingChannels } = require('aws-sdk');

// Configure AWS credentials
AWS.config.update({
  accessKeyId: process.env.AWS_ACCESS_KEY,
  secretAccessKey: process.env.AWS_SECRET_KEY,
  region: process.env.AWS_REGION
});
// Initialize AWS Kinesis Video and Signaling Clients
const kinesisVideoClient = new KinesisVideo({ apiVersion: '2019-12-04' });
const signalingClient = new KinesisVideoSignalingChannels({ apiVersion: '2019-12-04' });

async function createChannel(chnName) {
      try {
        data = await kinesisVideoClient.createSignalingChannel({ 
           ChannelName: chnName
           })
           .promise();
        console.log('Created signaling channel:', data.ChannelARN);
        //sigchan = data.ChannelARN;
        // Further code for signaling in WebRTC goes here
    } catch (error) {
        console.error('Error creating signaling channel:', error);
    }
    return data.ChannelARN;
}

// Function to attach local media (simplified)
async function attachLocalMedia(channelARN) {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
      // This is where you'd typically connect the stream to a WebRTC peer connection
      console.log('Stream ready to be connected to Kinesis Video Stream');
    } catch (error) {
          console.error('Media device access error:', error);
    }
}

The aws-sdk provides the necessary libraries for your Amazon Kinesis Video Streams migration. It is useful and consistent beyond this use case for the aforementioned credential management for client application access. The JavaScript above creates a signaling channel. The signaling component manages the WebRTC signaling endpoints that allow applications to securely connect with each other for peer-to-peer live media streaming.

Server Side POST handling

The app.post Express routing examples below demonstrate a scenario where application HTTP POST calls can be modified to utilize the newly created Amazon Kinesis Video Streams signaling channels for your video needs. It is important to note that additional functions for ICE signaling will be required for peer connectivity.

app.post("/twexample", async (req, res) => {
  // return 400 if the request has an empty body or no roomName
  if (!req.body || !req.body.roomName) {
    return res.status(400).send("Must include roomName argument.");
  }
  const roomName = req.body.roomName;
  // find or create a room with the given roomName
  findOrCreateRoom(roomName);
  // generate an Access Token for a participant in this room
  const token = getAccessToken(roomName);
  res.send({
    token: token,
  });
});

/* POST to /twexample URL for a twilio room
   include JSON in the body to specify a room name
   {"roomName":"our kvs signaling channel"}
*/

app.post("/kvsexample", async (req, res) => {
  // Less complex than above twilio example - if no roomName specified in the body, use random
  if (!req.body.roomName || req.body.roomName.length === 0) {
    roomName = uuidv4();  
    console.log(`eval body not met - using rand ${roomName}`);
  } else {
    roomName = req.body.roomName
  }

  sigchan = await createChannel(roomName);
 
  console.log(`arn=`, sigchan);
  res.send({
    ChannelARN: sigchan,
  })
});

Key Changes in the Migration

      • Use of Async/Await: The example above makes use of async/await for better handling of asynchronous operations. This can improve application performance reducing the need for complex function callback chains.
      • Signaling for WebRTC: The Amazon Kinesis Video Streams example acknowledges the need for additional WebRTC signaling code, which is a complex process involving creating offers, answering, and handling ICE candidates.

Conclusion

Transitioning to Amazon Kinesis Video Streams provides a robust platform for real-time video processing and analytics, suitable for scenarios like live streaming and surveillance. With its user-friendly features, AWS service integration and WebRTC capabilities, you only pay for what you use. Another option mentioned above in this blog could be migrating to Amazon Chime SDK, which offers an ideal solution for real-time communication needs, facilitating video/audio conferencing and collaborative platforms with its user-friendly features and AWS service integration. For further guidance or inquiries regarding this migration, please reach out to AWS Support or your AWS Account Team or submit an IoT Migration Request here.

Barry McCall

Barry McCall

Barry McCall is a Sr. Technical Account Manager with AWS