Skip to contentSkip to navigationSkip to topbar
Rate this Page:

Get Started with Twilio Video Part 1: Creating a Server with Python/Flask


(warning)

Warning

This page is for reference only. We are no longer onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2024(link takes you to an external page).
We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide(link takes you to an external page) to assist you in minimizing any service disruption.

This is the first part of a two-part tutorial for creating a video web application with a Python3/Flask backend and a JavaScript frontend. In this section, you'll set up a backend server that creates free Twilio WebRTC Go video rooms and generates Access Tokens for video room participants. In part two, you'll create the frontend side of the application, where participants can join a video room and share their video and audio with other participants.

At the end of this full tutorial, you'll have a web application that allows you to join a two-person video room and video chat with another person.

You can also view the completed code from both parts of the tutorial(link takes you to an external page) in GitHub.

If you have already completed the backend section of this tutorial, jump over to Part Two. Otherwise, let's get going!


Setup

setup page anchor

Requirements

requirements page anchor

Create the project directory

create-the-project-directory page anchor

Open a new terminal window and navigate to the directory where you want your project to live. Then, create a project folder and change into this directory:


_10
mkdir video_tutorial && cd video_tutorial

Collect account values and store them in a .env file

collect-account-values-and-store-them-in-a-env-file page anchor

To start, you'll need to collect a few values from the Twilio Console(link takes you to an external page) so that you can connect your application to Twilio. You will store these values in a .env file, and your server will read in these values.

Within the new project folder you created above, create a file called .env and open it in your preferred text editor.

The first value you'll need is your Account SID, which you can find in the Twilio Console(link takes you to an external page). Once you've gotten that value, store it in the .env file:


_10
TWILIO_ACCOUNT_SID=<your account sid>

Create an API Key

create-an-api-key page anchor

Next, you'll need to create an API key. This is what you'll use to authenticate with Twilio when making API calls.

You can create an API key using the Twilio CLI, the REST API, or the Twilio Console(link takes you to an external page). This tutorial will show how to generate it via the Console.

To generate the API Key from the Twilio Console:

When you've created the key, you'll see the friendly name, type, key SID, and API key secret.

(warning)

Warning

Make sure to copy the secret now, because you'll only be able to see it once. When you leave this page, you won't be able to see the secret again.

Copy the API Key ID and the API Key Secret and store both values in the .env file.


_10
TWILIO_ACCOUNT_SID=<your account sid>
_10
TWILIO_API_KEY_SID=<key sid>
_10
TWILIO_API_KEY_SECRET=<secret>

If you're using git for version control, make sure these credentials remain secure and out of version control. To do this, create a .gitignore file at the root of your project directory. In this file, you can list the files and directories that you want git to ignore from being tracked or committed.

Open the new .gitignore file in your code editor and add the .env file. While you're here, you can also add venv/, for the virtual environment directory you'll create in the next step.


_10
.env
_10
venv/

Great! Now that you've stored those credentials and added the .env to .gitignore, you can move on to creating the Flask server.

Install the dependencies

install-the-dependencies page anchor

First, you'll need to create and activate a virtual environment(link takes you to an external page) where you'll install your dependencies. In your terminal window, type the following command to create a virtual environment called venv:


_10
python3 -m venv venv

Then, activate the virtual environment. Whenever you run the server for this project or install dependencies, you should be in the virtual environment.

To activate the virtual environment for macOS or Unix, run the following command:


_10
source venv/bin/activate

If you are using a Windows machine, run:


_10
venv\Scripts\activate.bat

Then, you'll use pip(link takes you to an external page) to install the dependencies for this project:

In your terminal window, type the following command:


_10
pip install flask python-dotenv twilio

This command will add the dependencies to your virtual environment. Whenever you start your server, make sure you're in the virtual environment by running source venv/bin/activate (macOS/Unix) or venv\Scripts\activate.bat (Windows). You'll know that you're in the virtual environment because you'll see (venv) at the beginning of the command line prompt.


You will need a server to generate Access Tokens (to grant participants permission to access a video room) and serve the frontend code that you'll build in Part Two of this tutorial. There are several options for creating web servers with Python, but this tutorial uses Flask(link takes you to an external page).

This section walks through the general setup for a basic Flask server. In the next section, you'll add the Twilio-specific code for creating video rooms.

First, create a new file called app.py. This will be the server file where you put all the core logic for your web server. Open that file in your text editor, and copy and paste the following code into the file:


_31
import os
_31
import uuid # for generating random user id values
_31
_31
import twilio.jwt.access_token
_31
import twilio.jwt.access_token.grants
_31
import twilio.rest
_31
from dotenv import load_dotenv
_31
from flask import Flask, render_template, request
_31
_31
# Load environment variables from a .env file
_31
load_dotenv()
_31
_31
# Create a Twilio client
_31
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
_31
api_key = os.environ["TWILIO_API_KEY_SID"]
_31
api_secret = os.environ["TWILIO_API_KEY_SECRET"]
_31
twilio_client = twilio.rest.Client(api_key, api_secret, account_sid)
_31
_31
# Create a Flask app
_31
app = Flask(__name__)
_31
_31
_31
# Create a route that just returns "In progress"
_31
@app.route("/")
_31
def serve_homepage():
_31
return "In progress!"
_31
_31
_31
# Start the server when this file runs
_31
if __name__ == "__main__":
_31
app.run(host="0.0.0.0", debug=True)

At the top of the file, you import the dependencies needed for the server. Then, you load the values in your .env file with load_dotenv and grab the values from the environment. Using those values, you can create a client with the Twilio Python helper library. You'll use this client to communicate with Twilio.

Next, you create a basic Flask app. Currently, it is just an application with a single route that returns "In progress!".

At the bottom of the file, the server is set to run in debug mode. When the server is in debug mode, it will provide helpful error messages and it will automatically reload the server when you make changes to it. You should remove debug=True if you run this server in production.

Currently, the application doesn't do much, but you can test it by running the command python app.py in your terminal, making sure you're in your virtual environment. You should see output similar to the following:


_10
(venv) $ python app.py
_10
* Serving Flask app 'app' (lazy loading)
_10
* Environment: production
_10
WARNING: This is a development server. Do not use it in a production deployment.
_10
Use a production WSGI server instead.
_10
* Debug mode: off
_10
* Running on all addresses.
_10
WARNING: This is a development server. Do not use it in a production deployment.
_10
* Running on http://192.168.86.244:5000/ (Press CTRL+C to quit)

This will start the server on port 5000. Navigate to localhost:5000 in your browser, and you should see the string "In progress!".

Now that you have a functioning web server, you'll create a function that tells Twilio to create or find a video room.


You'll use the twilio_client you created earlier in app.py, and write a function to create new video rooms.

In app.py, underneath where you create the app (app=Flask(__name__)) and above the "/" route, paste in the following function:


_10
def find_or_create_room(room_name):
_10
try:
_10
# try to fetch an in-progress room with this name
_10
twilio_client.video.rooms(room_name).fetch()
_10
except twilio.base.exceptions.TwilioRestException:
_10
# the room did not exist, so create it
_10
twilio_client.video.rooms.create(unique_name=room_name, type="go")

In the code above, you create a function called find_or_create_room, which takes in a room name and checks if a video room with that name already exists for your account. If that room doesn't exist, you'll get a TwilioRestException, which will indicate that you should create the room.

This function will create the room as a WebRTC Go room (type="go"), which is a free room that can have up to two participants.

Eventually, you'll use this function to allow a participant to specify a room to either create or join. In the next section, you'll write a function to create an Access Token for a participant.

Here's the full app.py code with the new find_or_create_room function:


_40
import os
_40
import uuid # for generating random user id values
_40
_40
import twilio.jwt.access_token
_40
import twilio.jwt.access_token.grants
_40
import twilio.rest
_40
from dotenv import load_dotenv
_40
from flask import Flask, render_template, request
_40
_40
# Load environment variables from a .env file
_40
load_dotenv()
_40
_40
# Create a Twilio client
_40
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
_40
api_key = os.environ["TWILIO_API_KEY_SID"]
_40
api_secret = os.environ["TWILIO_API_KEY_SECRET"]
_40
twilio_client = twilio.rest.Client(api_key, api_secret, account_sid)
_40
_40
# Create a Flask app
_40
app = Flask(__name__)
_40
_40
_40
def find_or_create_room(room_name):
_40
try:
_40
# try to fetch an in-progress room with this name
_40
twilio_client.video.rooms(room_name).fetch()
_40
except twilio.base.exceptions.TwilioRestException:
_40
# the room did not exist, so create it
_40
twilio_client.video.rooms.create(unique_name=room_name, type="go")
_40
_40
_40
# Create a route that just returns "In progress"
_40
@app.route("/")
_40
def serve_homepage():
_40
return "In progress!"
_40
_40
_40
# Start the server when this files runs
_40
if __name__ == "__main__":
_40
app.run(host="0.0.0.0", debug=True)


Generate an Access Token for a Participant

generate-an-access-token-for-a-participant page anchor

Now, you'll create a function that returns an Access Token for a participant. An Access Token gives a participant permission to join video rooms.

The Access Token will be in the JSON Web Token (JWT)(link takes you to an external page) standard. The Python Twilio helper library contains functions for creating and decoding these tokens in the JWT format.

Copy and paste the following get_access_token function into app.py, under the find_or_create_room function:


_10
def get_access_token(room_name):
_10
# create the access token
_10
access_token = twilio.jwt.access_token.AccessToken(
_10
account_sid, api_key, api_secret, identity=uuid.uuid4().int
_10
)
_10
# create the video grant
_10
video_grant = twilio.jwt.access_token.grants.VideoGrant(room=room_name)
_10
# Add the video grant to the access token
_10
access_token.add_grant(video_grant)
_10
return access_token

The function does the following:

  • Takes in a room name
  • Creates an Access Token (in JWT(link takes you to an external page) format)

    • Generates a unique string for a participant's identity (see note below about the participant identity requirement)
  • Creates a Video Grant
  • Adds it to the Access Token
  • Returns the token
(information)

Info

The participant identity doesn't need to be a random string — it could be a value like an email, a user's name, or a user ID. However, it does need to be a unique value for the specific room. You cannot create more than one token for a given participant identity in a room.

The Video Grant is important to add to the token, because it is the piece that allows a participant to connect to video rooms. You can limit the participant's access to a particular video room (which the code above does), or you can generate a token with general access to video rooms.

If you were going to connect this application with other Twilio services, such as Twilio Sync or Twilio Conversations(link takes you to an external page), you could create additional Sync or Conversation grants and add them to this token to allow access to those services as well.

Here's the full server code with the added get_access_token function:


_52
import os
_52
import uuid # for generating random user id values
_52
_52
import twilio.jwt.access_token
_52
import twilio.jwt.access_token.grants
_52
import twilio.rest
_52
from dotenv import load_dotenv
_52
from flask import Flask, render_template, request
_52
_52
# Load environment variables from a .env file
_52
load_dotenv()
_52
_52
# Create a Twilio client
_52
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
_52
api_key = os.environ["TWILIO_API_KEY_SID"]
_52
api_secret = os.environ["TWILIO_API_KEY_SECRET"]
_52
twilio_client = twilio.rest.Client(api_key, api_secret, account_sid)
_52
_52
# Create a Flask app
_52
app = Flask(__name__)
_52
_52
_52
def find_or_create_room(room_name):
_52
try:
_52
# try to fetch an in-progress room with this name
_52
twilio_client.video.rooms(room_name).fetch()
_52
except twilio.base.exceptions.TwilioRestException:
_52
# the room did not exist, so create it
_52
twilio_client.video.rooms.create(unique_name=room_name, type="go")
_52
_52
_52
def get_access_token(room_name):
_52
# create the access token
_52
access_token = twilio.jwt.access_token.AccessToken(
_52
account_sid, api_key, api_secret, identity=uuid.uuid4().int
_52
)
_52
# create the video grant
_52
video_grant = twilio.jwt.access_token.grants.VideoGrant(room=room_name)
_52
# Add the video grant to the access token
_52
access_token.add_grant(video_grant)
_52
return access_token
_52
_52
_52
# Create a route that just returns "In progress"
_52
@app.route("/")
_52
def serve_homepage():
_52
return "In progress!"
_52
_52
_52
# Start the server when this file runs
_52
if __name__ == "__main__":
_52
app.run(host="0.0.0.0", debug=True)


Put it all together in a route

put-it-all-together-in-a-route page anchor

Next, you'll create a route called /join-room. In Part Two of this Tutorial, your frontend application will make a POST request to this /join-room route with a room_name in the body of the request.

Copy and paste the following code in app.py, underneath the route that returns "In progress!":


_12
@app.route("/join-room", methods=["POST"])
_12
def join_room():
_12
# extract the room_name from the JSON body of the POST request
_12
room_name = request.json.get("room_name")
_12
# find an existing room with this room_name, or create one
_12
find_or_create_room(room_name)
_12
# retrieve an access token for this room
_12
access_token = get_access_token(room_name)
_12
# return the decoded access token in the response
_12
# NOTE: if you are using version 6 of the Python Twilio Helper Library,
_12
# you should call `access_token.to_jwt().decode()`
_12
return {"token": access_token.to_jwt()}

This route takes a POST request containing a JSON object with a room name, and then calls the find_or_create_room function and the get_access_token function. It returns the decoded Access Token, which is a JSON Web Token (JWT)(link takes you to an external page).

Here's the final server file with all of these pieces:


_66
import os
_66
import uuid # for generating random user id values
_66
_66
import twilio.jwt.access_token
_66
import twilio.jwt.access_token.grants
_66
import twilio.rest
_66
from dotenv import load_dotenv
_66
from flask import Flask, render_template, request
_66
_66
# Load environment variables from a .env file
_66
load_dotenv()
_66
_66
# Create a Twilio client
_66
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
_66
api_key = os.environ["TWILIO_API_KEY_SID"]
_66
api_secret = os.environ["TWILIO_API_KEY_SECRET"]
_66
twilio_client = twilio.rest.Client(api_key, api_secret, account_sid)
_66
_66
# Create a Flask app
_66
app = Flask(__name__)
_66
_66
_66
def find_or_create_room(room_name):
_66
try:
_66
# try to fetch an in-progress room with this name
_66
twilio_client.video.rooms(room_name).fetch()
_66
except twilio.base.exceptions.TwilioRestException:
_66
# the room did not exist, so create it
_66
twilio_client.video.rooms.create(unique_name=room_name, type="go")
_66
_66
_66
def get_access_token(room_name):
_66
# create the access token
_66
access_token = twilio.jwt.access_token.AccessToken(
_66
account_sid, api_key, api_secret, identity=uuid.uuid4().int
_66
)
_66
# create the video grant
_66
video_grant = twilio.jwt.access_token.grants.VideoGrant(room=room_name)
_66
# Add the video grant to the access token
_66
access_token.add_grant(video_grant)
_66
return access_token
_66
_66
_66
# Create a route that just returns "In progress"
_66
@app.route("/")
_66
def serve_homepage():
_66
return "In progress!"
_66
_66
_66
@app.route("/join-room", methods=["POST"])
_66
def join_room():
_66
# extract the room_name from the JSON body of the POST request
_66
room_name = request.json.get("room_name")
_66
# find an existing room with this room_name, or create one
_66
find_or_create_room(room_name)
_66
# retrieve an access token for this room
_66
access_token = get_access_token(room_name)
_66
# return the decoded access token in the response
_66
# NOTE: if you are using version 6 of the Python Twilio Helper Library,
_66
# you should call `access_token.to_jwt().decode()`
_66
return {"token": access_token.to_jwt()}
_66
_66
_66
# Start the server when this file runs
_66
if __name__ == "__main__":
_66
app.run(host="0.0.0.0", debug=True)

Test this new route by running the server (with the command python app.py) and making a POST request to http://localhost:5000/join-room. You can use curl(link takes you to an external page), Postman(link takes you to an external page), HTTPie(link takes you to an external page), or another tool for making this request. To make the request using curl, run the following command in your terminal:


_10
curl -X POST http://localhost:5000/join-room \
_10
-H "Content-Type: application/json" \
_10
--data '{"room_name": "test room!"}'

You should receive output similar to the output below:


_10
{
_10
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImN0..."
_10
}

You can use the site jwt.io(link takes you to an external page) to inspect the token you received and see the different components that make up the Access Token. If you paste the token you received into the jwt.io debugger, it will decode the token and show you what the token includes. You should see that it contains a video grant for the specific room you created. The token will also include fields with other information you provided:

  • iss : your TWILIO_API_KEY_SID
  • sub : your TWILIO_ACCOUNT_SID
  • identity : the randomly generated uuid for the participant's identity

You now have a working backend server that will create video rooms and generate Access Tokens! You're done with this section of the tutorial and can move on to Part Two, where you'll create the frontend for this web app.


Rate this Page: