Categories
Mobile

How to build a video streaming app with React Native and Mux

[ad_1]

This article is written by Kolawole Mangabo

In this tutorial, you’ll learn how to use React Native, the mobile framework, the Mux Video API, and Codemagic for better CI/CD pipelines to build a video streaming application.

If you are familiar with applications such as Instagram, TikTok, or YouTube, you already know about video streaming.

Such applications can be quite complex to make. That’s why we’ll be using the Mux Video API to abstract the complexities of video streaming and write the logic of the API directly.

Mux API configuration

To use the Mux API, we’ll need API secrets from Mux. We’ll be adding assets and then retrieving API keys. Let’s begin!

Log in and go to the dashboard.

Adding an asset

Click on Add a video file.

Running the request for adding the video file

Once it’s done, click on Run Request. We can now generate the API tokens we’ll use to make requests to the API.

Go to the settings, and click on Generate new token.

Generating the tokens

Fill in the required details and generate the tokens.

Details for creating tokens

Your tokens will be generated now.

Generating tokens

We’ll be using these keys in a .env file, which will be ignored by .gitignore.

The project: What our app will look like

For this tutorial, we’ll be building a simple React Native application with two screens.

  • The first screen will be used to register a video and list all our assets from the Mux API;
  • The second screen will play the content and show information about the video.

Building the back end: Setting up a mini server with Flask

But first, we’ll need to set up some back end — a server. We’ll be creating this server using Flask — a lightweight and fast Python framework for building web applications or APIs. As we’ll only need a few endpoints here, Flask is definitely a great solution for our project. We could also have used Django, for example, but it comes with a lot of tools we won’t be using.

But why use a server and not just the default request module of JavaScript in React Native, such as Axios? First of all, it’s not really a good practice to put env keys on the front end, as they can be easily accessed, and this can result in a sensitive data leak. Using these keys on the server side significantly reduces the risk. So, a mini server is a better solution in our case.

We’ll be making requests to the mini server from the React Native application instead of directly hitting the Mux API on the React Native side. Now, let’s go.

First of all, let’s create a virtual environment.

cd flask-api
virtualenv --python=/usr/bin/activate venv
source venv/bin/activate

Once it’s done, create and install Flask.

pip install Flask python-dotenv

Also, let’s install the Mux Python package.

pip install git+https://github.com/muxinc/mux-python.git

Now, create a file .env, and add the following information.

MUX_TOKEN_ID="<mux_token_id>"
MUX_TOKEN_SECRET="<mux_token_secret>"

The next step is to create an app.py, and then we’ll start writing the code logic.

import os
from flask import Flask, request, jsonify
import mux_python
from mux_python.rest import ApiException
import json 

# Authentication Setup
configuration = mux_python.Configuration()
configuration.username = os.environ.get('MUX_TOKEN_ID')
configuration.password = os.environ.get('MUX_TOKEN_SECRET')

# API Client Initialization
assets_api = mux_python.AssetsApi(mux_python.ApiClient(configuration))
playback_ids_api = mux_python.PlaybackIDApi(mux_python.ApiClient(configuration))

app = Flask(__name__)

We are importing the Flask utilities, as well as some utilities from the mux_python package. This will help us initialize the clients to make requests to the Mux API.

As a first step here, let’s write a route to create a new video asset.

@app.route('/assets', methods=['POST'])
def create_asset():
    input_json = request.get_json(force=True)
    url = input_json.get('url')
    if url is None or not isinstance(url, str):
        abort(400, {'url': "This field is required"})
    input_settings = [mux_python.InputSettings(url=url)]
    try:
        create_asset_request = mux_python.CreateAssetRequest(input=input_settings)
        create_asset_response = assets_api.create_asset(create_asset_request)
    except ApiException:
        abort(400, {'message': "An error has occurred"})

    asset = create_asset_response.data
    new_data = {
        "id": asset.id,
        "status": asset.status,
        "created_at": asset.created_at,
        "duration": asset.duration,
        "max_stored_resolution": asset.max_stored_resolution,
        "max_stored_frame_rate": asset.max_stored_frame_rate,
        "aspect_ratio": asset.aspect_ratio
    }
    return json.dumps(new_data)

This function will create an asset. We are getting the body in the request and performing some verification. Once the check is done, we are using the API client we defined earlier to make a request to create a Mux asset.

Start running the server using this command.

flask run

Now that we can create assets, we’ll use Insomnia or Postman to make a POST request at http://127.0.0.1:5000/assets.

GET all assets

Let’s add endpoints — one to retrieve all assets and another one for one asset.

@app.route('/assets', methods=['GET'])
def list_assets(): 
    try:
        list_assets_response = assets_api.list_assets()
    except ApiException:
        abort(400, {'message': "An error has occurred"})
    new_data = map(lambda asset: {
        "id": asset.id,
        "status": asset.status,
        "created_at": asset.created_at,
        "duration": asset.duration,
        "max_stored_resolution": asset.max_stored_resolution,
        "max_stored_frame_rate": asset.max_stored_frame_rate,
        "aspect_ratio": asset.aspect_ratio
    }, list_assets_response.data)
    return jsonify(list(new_data))

@app.route('/assets/<string:asset_id>', methods=['GET'])
def get_asset(asset_id):
    try:
        asset_object_response = assets_api.get_asset(asset_id)
        asset = asset_object_response.data
    except ApiException:
        return "An error has occurred"
    new_data = {
        "id": asset.id,
        "status": asset.status,
        "created_at": asset.created_at,
        "playback_id": asset.playback_ids[0].id,
        "duration": asset.duration,
        "max_stored_resolution": asset.max_stored_resolution,
        "max_stored_frame_rate": asset.max_stored_frame_rate,
        "aspect_ratio": asset.aspect_ratio
    }
    return jsonify(new_data)

if __name__ == '__main__':
    app.run()

These two functions also use some functions provided by the mux_python package.

  • The assets_api.list_assets() function will return a Python object containing some attributes and the list of assets.
  • The assets_api.get_asset(asset_id) function will return a Python object containing some attributes as well as data about the asset we are looking for.

All right, the server is ready. As you can see, this was done very quickly with Flask. Now, let’s move to the front-end part with React Native.