# Hola! 👋

### **Welcome to Uiza, the video streaming as code!**&#x20;

We aim to provide developers with an end-to-end video streaming solution that offers simple integration and stable performance at scale. At the very beginning of our roadmap, we tackle the problem that is considered the most severe, ***video and live stream delivery***. The proximity between the infrastructure and the streamer/viewer is the key factor that influence the quality of the video streams. Setting up and managing a wide network of infrastructures that penetrates locally to reach out as closely as possible to the streamers and viewers in various cities are tough. The first version of our brand-new platform is created to solve this problem.

{% hint style="success" %}
Our **key differentiation** is that we are developing a diversified network of infrastructures that does not only rely on public cloud like Amazon Web Services, Google Cloud Platform, or Digital Ocean, but also a wide range of local infrastructures those are rooted in lower-tier cities like *Bengaluru, Kolkata, Chennai*... This means your viewers will most likely *watch the videos being streamed from the infrastructure located in the same city of theirs*, which improves the quality and scalability of the video streams significantly.
{% endhint %}

![](/files/-Lvy1ZLdD3Cbvz7i3WN8)


# Introduction

Uiza helps you broadcast your live stream to your audiences with literally a few lines of codes, or at least we are trying hard to get there:muscle::muscle::muscle:. But before experiencing the magic, let's make sure that you understand the terms correctly.

* ***`live_entity`***: Live entities are basically live events, with or without a live feed. A live entity contains the information required for Uiza to allocate resources to power the live event, and direct your live feed toward these resources for ingestion and broadcasting.
* ***`live_session`***: The duration of one session is counted from the moment Uiza receives the first signal until the last of that live feed. Therefore, one entity could contain multiple sessions. The durations of these sessions are calculated as *Live Minutes* in your billing.
* ***Streamer***: Streamers record the live events and are the source of the live  signals that Uiza receives.
* ***Viewer***: Viewers are the users who watch the live stream on their devices. They are the destination of the delivery of the live stream.

Now that we are on the same page, let's navigate to the **Quickstart** to start *live streaming*.

{% content-ref url="/pages/-LwqhgC-FZjkAy13MWg8" %}
[Authentication](/2022-06-22/getting-started/authentication)
{% endcontent-ref %}


# Authentication

Uiza APIs apply the [HTTP Basic Authentication Protocol](https://swagger.io/docs/specification/2-0/authentication/basic-authentication/), where the client sends HTTP requests with the API key in the Authorization header.

Once you have signed up, you can create applications (maximum of 2 applications) with an API Key assigned to each application.&#x20;

You can manage your applications and API Keys in the [Uiza Dashboard](https://app.uiza.io/).

All API requests to Uiza *must go* over HTTPS and include a valid API Key.


# Errors

This page describes the error statuses returned by the Uiza APIs

Whether an API request to Uiza is successful or not is indicated by conventional *HTTP* codes. In general, Uiza returns responses with equivalent *status codes* which are listed below.

> **200 - OK**
>
> The request is successful.

> **400 - Bad request**
>
> The request is inadequate. This is usually caused by missing required parameters or malformed syntax.

> **403 - Forbidden**
>
> The API key doesn't have permissions to perform the request.

> **404 - Not Found**
>
> The requested resource does not exist.

> **409 - Conflict**
>
> The request conflicts with the current state of the server. For example updating an immutable resource already present on the server.

> **500, 502, 503, 504 - Internal Server Error**
>
> Something went wrong on Uiza's end

> Errors are returned with format containing a `message` and an `error_type` to help you pinpoint what went wrong. While you can find all the possible error messages in our API Reference, these errors are categorized by the following `error_types`:

|       Error Types       |                           Definitions                           |
| :---------------------: | :-------------------------------------------------------------: |
|  `api_connection_error` |       Errors that occurred during the HTTP communication.       |
|       `api_error`       |            Errors occurred internally with Uiza API.            |
|  `authentication_error` |    The keys supplied to Uiza were either missing or invalid.    |
| `invalid_request_error` | The parameters supplied to Uiza were either missing or invalid. |
|    `rate_limit_error`   |         Too many requests were sent to Uiza too quickly.        |
|      `video_error`      |     There is something wrong with your video or live stream.    |


# Quick Starts

Welcome to the most exciting part of Uiza Documentation. Now, we will accompany you in streaming your first video, and live broadcasting your very first session with Uiza APIs. :partying\_face::partying\_face::partying\_face:

{% content-ref url="/pages/-LvsA4FyDRUwKP4Z7tjP" %}
[Live Streaming](/2022-06-22/getting-started/quick-starts/quickstart)
{% endcontent-ref %}

{% content-ref url="/pages/-Lwm3LFbLppQcOYeL\_pt" %}
[Video Streaming](/2022-06-22/getting-started/quick-starts/video-streaming)
{% endcontent-ref %}


# Live Streaming

Our *REST APIs* use standard *HTTP* response codes, authentication, and verbs, and return *JSON-encoded responses*. Using these APIs, you will be able to start a live event and stream the content to our network, which will deliver that content to your audiences. Once a live entity is created, Uiza allocates dedicated resources and return an *RTMP* server to ingest and deliver your stream. The overall framework is articulated in the diagram below.

![](/files/-LxVHSp0O-p10YRdBAom)

## **Step 1: Create a live entity**

To start streaming, you need a [`live_entity`](https://docs.uiza.io/api-reference/live-entities) to be created with resources allocated, ready to broadcast the live signal. You could create a live entity by using ***Create A Live Entity*** ***API***.&#x20;

## /v1/live\_entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/live_entities`

#### Request Body

| Name        | Type    | Description                                                                                                                                                                                          |
| ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | string  | The name of your live entity.                                                                                                                                                                        |
| region      | string  | Choose the region closest to the location of your streamer.                                                                                                                                          |
| description | string  | The description of your live entity (maximum is 1000 characters)                                                                                                                                     |
| dvr         | boolean | Indicates whether Digital Video Record (DVR) is enabled for the `live_entity`. Set as `true` to enable and as `false` to disable. The default value is false.                                        |
| encode      | boolean | Indicates whether encoding mode is enabled for the `live_entity`. Set as `true` to enable and as `false` to disable. The default value is false, when the encode is true, it required a `preset_id`. |
| preset\_id  | string  | The identifier of the `video_preset` to be applied when encoding your signal.                                                                                                                        |
| relay       | array   | A list of ingest servers to be relayed. Contains `url` and `key` and `name` (optional) in each ingest server.                                                                                        |

{% tabs %}
{% tab title="200 " %}
{% tabs %}
{% tab title=" live\_entities without encoding" %}

```

  "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
  "name": "Test event without encoding",
  "description": "Event for Test",
  "region": "in-bangalore-1",
  "status": "init",
  "dvr": false,
  "encode": false,
  "ingest": null,
  "playback": null,
  "relay": [
    {
      "url": "rtmp://youtu.be/live",
      "key": "Abco1",
      "name": "Youtube 1"
    }
  ],
  "preset": null,
  "created_at": "2020-03-23T07:22:34Z",
  "updated_at": "2020-03-23T07:22:34Z"
}
```

{% endtab %}

{% tab title=" live\_entities with encoding" %}

```
{
    "id": "b7f02d48-d0ec-4c34-86d1-247a38eda4e1",
    "name": "Test event with encoding",
    "description": "Event for Test",
    "ingest": null,
    "playback": null,
    "relay": [
        {
            "url": "rtmp://youtu.be/live",
            "key": "Abco1",
            "name": "Youtube 1"
        }
    ],
    "region": "in-bangalore-1",
    "status": "init",
    "dvr": false,
    "encode": true,
    "preset": {
        "id": "9432fa62-5988-11ea-883b-028fc5698662",
        "name": "Uiza LIVE 720p",
        "description": "",
        "is_default": true,
        "profiles": [
            {
                "id": "85844e8b-6281-11ea-883b-028fc5698662",
                "name": "720p H264 30fps Normal Latency",
                "segment_duration": 4,
                "orientation": "landscape",
                "video_profile": {
                    "video_resolution": "720",
                    "video_codec": "H264",
                    "video_bitrate": "2000K",
                    "video_frame_rate": "30"
                },
                "audio_profile": {
                    "audio_channel": "2",
                    "audio_codec": "AAC",
                    "audio_bitrate": "128K",
                    "audio_frame_rate": "1"
                }
            }
        ],
        "created_at": "2020-02-27T17:42:52Z",
        "updated_at": "2020-02-29T16:47:34Z"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```go
curl -X POST https://api.uiza.sh/v1/live_entities \
-H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' \
-d '{"name": "Test Event", "region": "in-bangalore-1", "description": "Test 1"}'
```

{% endcode %}

{% hint style="info" %}
Please pay attention that you entered a supported region, else the API will return an error message. Defining correct region helps Uiza allocates the resource that is closest to the streamer location. This will minimize the risks of network issues and reduce the impact on your business. While we are adding more and more regions to Uiza Network, please check the current available regions below:

`in-bangalore-1` (Bangalore - India)

`in-mumbai-1` (Mumbai - India)

`sg-singapore-1`(Singapore)

`vn-saigon-1` (Vietnam)
{% endhint %}

## **Step 2: Retrieve a live entity**

You will need the `ingest.key` and `ingest.url` to configure your broadcasting software. These 2 attributes could be retrieved by using the `id` you get in the response in ***Step 1*** for the ***Retrieve an entity*** API.

{% hint style="warning" %}
It is important that the value of the **`status`** you get from the response is **`ready`**, meaning that resources have been allocated and ready to ingest and broadcast your live feed. If the **`status`** of your entity is **`init`**, meaning that Uiza is still allocating resources for your entity and your live signal will not be able to be ingested and broadcasted during this process. Please, be patient and keep requesting for the entity's information until you get the **`ready`** status. This process may take up to 1 minute.
{% endhint %}

## /v1/live\_entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.sh/v1/live_entities/:id`

#### Path Parameters

| Name | Type   | Description                                                        |
| ---- | ------ | ------------------------------------------------------------------ |
| id   | string | The unique identifier of a live entity to be retrieved information |

{% tabs %}
{% tab title="200 " %}

```
{
 "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
 "name": "Test Event",
 "description": "Test 1",
 "ingest": {
   "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
   "key": "live_TB62vHgxSY"
 },
 "playback": {
   "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8"
 },
 "region": "in-bangalore-1",
 "status": "ready",
 "dvr": false,
 "broadcast": "offline",
 "created_at": "2019-12-11T02:47:04Z",
 "updated_at": "2019-12-16T02:53:30Z"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```go
curl -X GET https://api.uiza.sh/v1/live_entities/2b970a39-874a-4d2a-be8a-fd445646d74c \
-H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
```

{% endcode %}

{% hint style="info" %}
You could also set up a [webhook](https://docs.uiza.io/api-reference/webhook_endpoints) to be notified automatically when your `live_entity` is ready.
{% endhint %}

## **Step 3: Configure your broadcasting software and start broadcasting**

Most available broadcasting software uses [RTMP protocol](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) which requires a *server's URL* and a *Stream Key* to direct the live signal to the ingest servers. Use the `ingest.url` and `ingest.key` obtained at **Step 2** to configure your broadcasting software in their Settings. The following are the 2 most popular broadcasting software that we strongly recommend.

{% hint style="info" %}
**OBS Studio** (Available for Mac, Windows, and Linu&#x78;**)** - Get it [here](https://obsproject.com/).&#x20;
{% endhint %}

![](/files/-LvsDOpl_ledM1Slwgj7)

{% hint style="info" %}
**Streamlabs (**&#x54;he best live streaming app for iPhone & Androi&#x64;**)** - Get it [here](https://streamlabs.com/mobile-app).
{% endhint %}

![](/files/-LvsEXnmQmcXq5XxHRPt)

Once you have configured the `ingest.url` and `ingest.key`, you could start streaming right away.

## **Step 4: Configure the playback link to your player and start watching your live stream!**

The playback links (`hls` for HLS streaming and `mpd` for MPEG-dash streaming) of your live entity is the value of `playback` returned in ***Step 2*****.** With the HLS link obtained, you could play your live stream by these methods:&#x20;

1. Configure the HLS link to Player SDK.
2. Paste the HLS link to Safari and play directly with Apple's native player.
3. Install the HLS extension and play it on Google Chrome browser.

The `mpd` video format could be played natively by  [Microsoft Edge](https://www.microsoftedgeinsider.com/en-us/).

By following these *4 steps*, you will be able to live stream your event using Uiza:pray:. We understand that this beta version of ours requires quite some amount of manual involvement, but we are working hard to deliver a more delightful experience with more APIs and automation. If you are ready to live-stream your first event, let's move on to the ***API Reference***.


# Video Streaming

**Streaming videos** with Uiza is pretty straightforward where the whole process could be summarized in 4 simple steps:&#x20;

1. You give us the video,
2. You allow us to publish the video,
3. We let you know when your video is published, and
4. You tell your player to start streaming :nerd:&#x20;

![](/files/-LxQZO0_8W966JjHyU7S)

## Step 1: Create a video entity

You can create a [`video_entity`](https://docs.uiza.io/api-reference/video-entities) using HTTP/HTTPS URL links to your original video files. In case the video file is located in your PC, you can upload the video via the [Uiza Developer Console](https://app.uiza.io/) by following these steps:

1. Login to Uiza Developer Console
2. **Start** your application, then go to **Upload Video** page
3. Browse to your local video file or enter multiple HTTP/HTTPS URLs
4. Click **Proceed** to start uploading your selected video files

![Upload Video Selection Page](/files/-M4TeyQWizdpvWNf-YHt)

Successfully uploaded `video_entities` will be ingested and listed out in the Developer Console. To transcode the video, click on "Publish" or move to step 2.

![Upload Video Result Page](/files/-M4ThijWbsfQ-GAmQAf_)

Go to **Entities** page and select created video entity for checking `id` and other details.

## Step 2: Publish the video entity

The renditions of your video, as the output of transcoding, will be distributed to Uiza's [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) through which it is delivered to viewers.&#x20;

To let Uiza know that you are ready to publish your video to your viewers, you can use [Uiza Developer Console](https://app.uiza.io/) or send a request to ***Publish a video entity*** API.

## /v1/video\_entities/:id/publish

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/video_entities/:id/publish`

#### Path Parameters

| Name | Type   | Description                                         |
| ---- | ------ | --------------------------------------------------- |
| id   | string | The identifier of the video entity to be published. |

{% tabs %}
{% tab title="200 " %}

```
{
 "message": "Video entity started to publish successfully"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.sh/v1/video_entities/f42b4ac3-869e-4010-8e21-042e40be7655/publish 
     -H 'Accept: */*' 
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
     -H 'Cache-Control: no-cache' 
     -H 'Connection: keep-alive'
```

{% endcode %}

## Step 3: Retrieve the video entity's information

The process of transferring the renditions of your video to Uiza's CDN takes time. You player can only start playing the video after it has been successfully published. To keep track of this process, retrieve the video entity's information. The `publish_to_cdn` argument indicates the publishing status of your video entity. If the value is `success`, you are good to go.

## /v1/video\_entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.sh/v1/video_entities/:id`

#### Path Parameters

| Name | Type   | Description                                         |
| ---- | ------ | --------------------------------------------------- |
| id   | string | The identifier of the video entity to be retrieved. |

{% tabs %}
{% tab title="200 " %}
{% tabs %}
{% tab title="The Video Entity has not been published" %}

```
{
 "id": "f42b4ac3-869e-4010-8e21-042e40be7655",
 "name": "Sample Demo-Video",
 "description": "Lorem ipsum dolor sit amet, vis odio oratio scripserit ut",
 "short_description": "Duo ad graeci principes, legimus mnesarchum scribentur ut pro",
 "view": 1000,
 "poster": "Lorem ipsum dolor",
 "thumbnail": "Lorem ipsum dolor",
 "type": "VOD",
 "duration": 11213,
 "publish_to_cdn": "queue",
 "created_at": "2019-12-11T02:47:04Z",
 "updated_at": "2019-12-11T02:47:04Z"
}
```

{% endtab %}

{% tab title="The Video Entity is published successfully" %}

```
{
    "id": "77123e09-a30b-456b-b954-c16fe81f97f7",
    "name": "test 998",
    "description": "Entity for Test",
    "short_description": "",
    "view": 0,
    "poster": "",
    "thumbnail": "",
    "input_type": "UNKNOWNVODINPUTTYPE",
    "duration": 269.588,
    "publish_to_cdn": "success",
    "playback": {
        "hls": "https://dvr-playback-secure.uizadev.io/05bb5869-e134-4e9e-a2d2-de5c77dd182f/77123e09-a30b-456b-b954-c16fe81f97f7/master.m3u8",
        "hls_ts": "",
        "mpd": ""
    },
    "created_at": "2020-02-12T12:28:00Z",
    "updated_at": "2020-02-12T12:32:30Z"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X GET https://api.uiza.sh/v1/live_entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
     -H 'Accept: */*' 
     -H 'Accept-Encoding: gzip, deflate' 
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
     -H 'Cache-Control: no-cache' 
     -H 'Connection: keep-alive'
```

{% endcode %}

## Step 4: **Configure the playback link to your player and start streaming!**

Three playback links are returned in the response of Step 3. These playback links represent the 3 streaming protocols that Uiza currently supports:

* `hls` for HLS fMP4 streaming,
* `hls_ts` for HLS ts streaming, and
* `mpd` for MPEG-dash streaming.

Configure these playback links to your player will enable your player to get the video chunks from Uiza's CDN, decode and display them to your viewers. And that is How to stream your first video with Uiza in 4 simple steps. :wink:&#x20;


# Pagination

Uiza's List method is using page-based pagination, this is one of the simplest forms of paging. Initially, only a certain number of results will be returned at a time. The default is 50.

#### Arguments

> **`limit`** *number*
>
> The maximum number of objects to be returned per call, between 1 and 50. The default `limit` is 50.

> **`page`** *number*
>
> Indicates the page number, the page being the one requested. By default, this query parameter is equal to 1.

{% code title="Sample Response" %}

```
{
 "data": {
    "items": [
      {
        "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
        "name": "Demo app 1",
        "description": "Demo application for documentation",
        "dvr": true,
        "encoding_template": "none",
        "ingest": {
          "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
          "key": "live_TB62vHgxSY"
        },
        "playback": {
          "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
          "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
        },
        "region": "in-mumbai-1",
        "relay": [
          {
            "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
            "name": "Replay name3333",
            "url": "rtmp://a.rtmp.youtube.com/live2",
            "key": "0df3-76bz-6t4r-1by5xxxxxx",
            "status": "enable",
            "created_at": "2020-06-24T16:25:58Z",
            "updated_at": "2020-06-24T16:25:58Z"
          }
        ],
        "status": "ready",
        "created_at": "2020-03-10T03:20:37.202Z",
        "updated_at": "2020-03-10T03:20:37.202Z"
      }
    ],
    "total": 99
  }
}
```

{% endcode %}


# Recommended Specifications

*Live broadcasting*, especially in high resolution, consumes significant resources from your devices. Therefore, we recommend the following specifications for the *optimal* streaming experience.:metal:&#x20;

|                           | <p><strong>HD streaming on desktop</strong></p><p><strong>(720p)</strong></p> | <p><strong>Full-HD streaming on desktop</strong></p><p><strong>(1080p)</strong></p> |                 **Mobile streaming**                |
| :-----------------------: | :---------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :-------------------------------------------------: |
|       **Processor**       |               <p>Intel Core i5 - 5th Gen</p><p>or AMD Ryzen</p>               |                 <p>Intel Core i7 - 5th Gen</p><p>or AMD Ryzen 2</p>                 |                 ARM Cortex-s 64 bit                 |
|         **Memory**        |                                      8GB                                      |                                         8GB                                         |       <p>2GB for iOS</p><p>4GB for Android</p>      |
|        **Graphics**       |                              Intel integrated GPU                             |                                    NVDIA GTX 1050                                   |                    Not applicable                   |
|        **Network**        |        <p>Wi-fi or Ethernet</p><p>(at least 5Mbps of upload speed)</p>        |               <p>Ethernet</p><p>(at least 10Mbps of upload speed)</p>               | <p>Wi-fi</p><p>(at least 5Mbps of upload speed)</p> |
|    **Operating System**   |         <p>Windows 10 and above</p><p>MacOS High Sierra and above</p>         |            <p>Windows 10 and above</p><p>MacOS High Sierra and above</p>            |  <p>Android 7 and above</p><p>iOS 10 and above</p>  |
| **Broadcasting Software** |                         [OBS](https://obsproject.com/)                        |                            [OBS](https://obsproject.com/)                           |        [Streamlabs](https://streamlabs.com/)        |


# Sample Streaming Apps

Uiza provides the video and live streaming API and SDK for your app. These samples introduce various applications based on Uiza API. Refer to the following applications.

* [NodeJS Basic Live Streaming App](/2022-06-22/getting-started/sample-streaming-apps/nodejs-live-streaming-app): The project is a sample application written in **NodeJS** and **React** composed of common live streaming features.&#x20;
* [Python Basic Live Streaming App](/2022-06-22/getting-started/sample-streaming-apps/python-live-streaming-app): The project is a sample application written in **Python** composed of common live streaming features.&#x20;
* [Java Basic Live Streaming App](/2022-06-22/getting-started/sample-streaming-apps/java-live-streaming-app): The project is a sample application written in **Java**  and **React** composed of common live streaming features.&#x20;

The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

This is just a head start! If there’s an integration or sample application you’d like to see or if you’d like to partner with us, [ping us!](mailto:kevin@uiza.io)


# NodeJS Live Streaming App

How to build your live streaming web app with Uiza’s API using React and NodeJS

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Javascript.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. The broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming app

### Step 1. Creating a new Project and install dependencies

To build a broadcast web app, we start with creating a new react web application. Let us create a brand new application. Open terminal / command prompt and execute the below lines to create a starter app:

1. Create a new project

   ```
   npx create-react-app uiza
   ```
2. Get into the project directory

   ```
   cd uiza
   ```
3. Start the development server.

   ```
   npm start
   ```

#### Getting started with Uiza

To start a broadcast with Uiza we will need to do two things:&#x20;

1\. Create a live entity in Uiza servers.&#x20;

2\. Get the ingest.url and ingest.key for this entity.

#### Install program dependencies

To increase the readability of this tutorial, we use the Axios library to send requests to the Uiza server. Install Axios with the following command:

```javascript
npm install axios
```

To play the video stream we will need a player control. Install react-player with the following command:

```javascript
npm install react-player
```

### Step 2. Make changes to the App.js

Open the `App.js` file in the `src` directory.

#### Import repositories

Import react, router, react video player and css file.

```javascript
import React, { Component } from 'react';
import ReactPlayer from 'react-player';
import './App.css';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useParams
} from "react-router-dom";
```

We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

The code snippet shows the constants:

```javascript
const authorization_key = "<<Your API key>>";
const url = "https://api.uiza.sh/api/v5/live/entities";
const default_headers = {
  "Content-Type": "application/json",
  "Authorization": authorization_key
}
```

Then we import Axios to send `GET` and `POST` requests:

```javascript
const  axios  =  require('axios').default;
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.&#x20;
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use application-wide states that can be displayed in the application, and manipulated at run-time. As you can see, we can set default values with states. Our default region value is `in-bangalore-1`

```javascript
state  = {
    message:  '',
    region_value:  'in-bangalore-1',
    broadcast_url:  '',
    broadcast_key:  ''
};
```

#### Define a function to start a broadcast

We define this function as `start_broadcast`. We clear the states and set the message state to `fetching`. Then we start loading the information.

```javascript
this.setState({message: "Fetching"});
this.setState({broadcast_url: ""});
this.setState({broadcast_key: ""});
```

Now we set the parameters, so that we can make the `create entity` call. The below structure contains all the information of the HTTP request that we pass to Axios. As you can see, we make use of the `region_value` state to set the region to a supported value.

```javascript
var broadcast_create_options = {
  "method": "post",
  "url": "https://development-api.uizadev.io/api/v5/live/entities",
  "headers": default_headers,
  "data": {
        "name": 'Demo app',
        "region": this.state.region_value,
        "description": 'Application description'
 }
};
```

Now let's create the polling call structure so that we don't end up creating the same structure from the loop. As you can see it will be a `GET` request. Authorization header will expect your API key.

```javascript
var broadcast_polling_options = {
  "method": "get",
  "headers": default_headers,
  "data": {
      "name": 'Demo app',
      "region": this.state.region_value,
      "description": 'Application description'
    }
};
```

We make a `POST` request to create an entity.

```javascript
var create_response = await axios(broadcast_create_options);
console.log('Response Received')
```

The call returns the entity `id` in the respone.

```javascript
 var broadcast_id = create_response.data.id;
 this.setState({message: 'broadcast Created: '+ broadcast_id});
```

The `GET` method takes the entity `id` and returns the broadcast information (including the stream URL and key).

```javascript
broadcast_polling_options["url"] = url + "/" + broadcast_id;
```

To get the stream URL and key, the entity has to be in a `ready` state. We use `setInterval` to poll the API every 3 seconds to check the status of the entity using `response.data.status`.

The initial status of an entity is `init`. When the server is ready with a stream URL and key, the status becomes `ready`.

If the status is not`ready` yet, we continue polling and the current state of `message` will be set to `Polling`.

Once the status is `ready` we can extract `url` and `key` from the response.

`self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });`

The above code creates a nice text animation so that we know the program is not stuck and is working.

```javascript
var counter = 0;
var self = this;
var poll_interval = setInterval(async function() {
  try {
    var response = await axios(broadcast_polling_options);
    if (response.data.status === "ready") {
      self.setState({ message: "Stream is now ready" });
      self.setState({ broadcast_url: "URL: " + response.data.ingest.url });
      self.setState({ broadcast_key: "Key: " + response.data.ingest.key });
      clearInterval(poll_interval);
    } else {
      self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });
    }
    counter = counter + 1;
  } catch (error) { console.log(error) }
}, 3000);
```

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the `region_value`. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

The first line displays the messages from the program's status: `Fetching`, `Polling` etc.

```javascript
{this.state.message}<br/>
```

The second line contains the stream URL (i.e. `stream_url`)

```javascript
{this.state.broadcast_url}<br/>
```

The third line contains the key for the stream key (i.e `stream_key`)

```javascript
{this.state.broadcast_key}<br/>
```

#### Putting the broadcast page UI together:

```javascript
render() {
    return (
      <div className='page'>
        <div className="App">
          <h1> Uiza Guide </h1>
          <header className="App-header">

            <div style={{ align: "left", float: 'left', width: "45%", margin: "10px", height: "220px", padding: '10px', border: "1px solid white" }}>
              <p> Start broadcast <br />
                <label>Pick your region: &nbsp;
                <select value={this.state.region_value} onChange={(event) => { this.setState({ region_value: event.target.value }); }}>
                    <option value="asia-southeast-1">asia-southeast-1</option>
                    <option value="do-bangalore-1">do-bangalore-1</option>
                    <option value="asia-south-1">asia-south-1</option>
                  </select>
                </label> &nbsp;
              <button onClick={this.start_broadcast}>Start broadcast</button> <br />
              {this.state.message}<br/>
              {this.state.broadcast_url}<br/>
              {this.state.broadcast_key}<br/>
              </p>
            </div>
            </header>
        </div></div>
    )
  }
}

export default App;
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams. Green tiles are online entities and red tiles are offline entities.

The following `load_alive_streams` function loads the streams. Available streams are loaded and saved to `state` so that they update automatically.

```javascript
load_alive_streams = async () => {
    var options = {
      "method": "get",
      "url": url,
      "headers": {
        "Content-Type": "application/json",
        "Authorization": authorization_key
      }
    };
    var response = await axios(options);
    var data = response.data.data;
    var streams = [];
    data.forEach(element => {
      try {
        streams.push({
          online: element.broadcast === 'online' ? true : false,
          stream_url: element.ingest.stream_url,
          stream_key: element.ingest.stream_key,
          playback_url: element.playback.hls
        })
      } catch (err) { }
    });
    this.setState({
      streams: streams,
      last_loaded: new Date()
    });
    console.log(`Completed reading data: ${streams.length} streams are online now!`);
  }
```

#### Rendering the view page UI

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

The above line sends the user to an `href` link which is understood by the router later. The regex removes the protocol from the URL (i.e http / https)

Following code shows the VideoTile component:

```javascript
class VideoTile extends Component {

  render() {
    return (
      <div style={{
        width: "240px", height: "200px", float: "left", margin: "10px", padding: "8px", display: "flex", flexDirection: "column",
        wordWrap: "break-word", fontSize: "16px", border: "2px solid white", backgroundColor: this.props._online ? 'MediumSeaGreen' : 'Tomato'
      }}>

        {/* remove http(s) */}
        <a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
          <span name='url'>URL: {this.props._url}</span><br /><br />
          <span name='key'>KEY: {this.props._key}</span><br /><br />
          <span name='playback_url'>PLAYBACK: {this.props._playback_url}</span>
        </a>
      </div>
    )
  }
}
```

As mentioned above, requests are only made every 5-seconds. We attach the parameters to the VideoTile element. After putting it all together:

```javascript
render() {
    try {

      if (typeof this.state.last_loaded === "string" || ((new Date() - this.state.last_loaded) / 1000) > 5) {
        var items = [];
        this.load_alive_streams().then((result) => {

          for (const [index, value] of this.state.streams.entries()) {
            items.push(<VideoTile key={index}
                                  _url={value.stream_url}
                                  _key={value.stream_key}
                                  _playback_url={value.playback_url}
                                  _online={value.online}></VideoTile>)
          }

          this.setState({ items: items });
          console.log('Loading complete');
        });
      }
    } catch (err) {
      this.setState({ last_loaded: new Date() });
    }

    return (
      <div className="App">
        <h1 style={{ padding: "8px" }}>  Uiza Online Videos </h1>
        <header className="App-header">
          <div name='tileContainer'>
            {this.state.items}
          </div></header>
      </div>
    )
  }
```

### Step 6. Playback the live stream

Now we have the video tiles ready but what do we show when this tile is clicked? This clever little view code launches the player on screen. We launched the player on the screen when the tile is clicked with the following code:

```javascript
function VideoPage() {
  let { videoid } = useParams();
  return (
    <div style={{ padding: "20px" }}>
      <ReactPlayer url={"https://" + videoid} playing={true} controls={true}></ReactPlayer>
    </div>)
}
```

#### Routing and overall APP UI

We make use of the `Router` component in react to create pagination in our app. We will have the link to broadcast and view page

To enable pagination in the app, we need to make use of react's routing. Following code does the routing:

```javascript
class App extends Component {

  render() {
    return (
      <Router>
        <div className='page'>
          <nav>
            <ul>
              <li>
                <Link to="/broadcast">Broadcast Page</Link>
              </li>
              <li>
                <Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>
              </li>
            </ul>
          </nav>

          {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
          <Switch>
            <Route path="/broadcast">
              <BroadcastPage />
            </Route>
            <Route path="/viewer">
              <ViewerPage />
            </Route>
            <Route path="/video/:videoid*">
              <VideoPage />
            </Route>
          </Switch>
        </div>
      </Router>
    )
  }
}
```

The streams are loaded when we click on the viewer with the below line. Following line loads the streams on click: `<Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>`

The routing path below with `*` wildcard enables video stream url to be parsed with `/` and to be sent to the video page. Otherwise, the videoid is split at the first occurence of `/`

```javascript
<Route path="/video/:videoid*">
              <VideoPage />
```

## Conclusion

That's all wasn't that fun? If you have any questions please check out our Github repo where this entire project has been uploaded with source code [here](https://github.com/uizaio/uiza-node-sample-app) and if you have any other questions please contact us here: <anhnh@uiza.io>


# Java Live Streaming App

How to build your live streaming web app with Uiza’s API using React and Java

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Javascript.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. Tha broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming JAVA app (Backend)

### Step 1. Getting started with Uiza Java application

To start a broadcast with Uiza Java App, we will need to configure stream\_url and stream\_key in application propeties file.

We need an API key to access Uiza's services. To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key. Configured your API key and URL in application properties as below.

We have created Java because we can not pass API key through browser. If we pass API key through browser then anyone can stole our API key and use Uiza api. So using JAVA app, we are storing this API key in the JAVA property file and calling Uiza api from Java App.

```
application.uiza.url= https://api.uiza./v1/live_entities
application.uiza.authorization-token="API Key"
```

### Step 2. Deploy/Run Java App

Download the Java sample code at [Github link](https://github.com/uizaio/uiza-live-java-server-integration)

1. Go To Project Directory

   ```
   cd uiza
   ```
2. Run below command

   ```
   mvn clean install
   ```
3. After step 2 finishes installation, go to `target` directory inside the project.&#x20;

   ```
   cd target
   ```
4. Run the below command to run java application. Java application will run 8080 port.

   ```
   java -jar uiza-0.0.1-SNAPSHOT.jar
   ```

### Step 3. This guide will help you create a simple REST service using Spring Boot.

In this guide, we will create three services using proper URIs and HTTP methods:

* @GetMapping("/app/live/entities"): You can retrieve the live entities using request method Get and example uri /app/live/entities.
* @GetMapping("/app/live/entities/{id}"): You can retrieve a specific live entity using request method Get and example uri /app/live/entities/1.
* @PostMapping("/app/live/entities") : You can create a live entity by sending a POST request to URI /app/live/entities

#### Using appropriate Request Methods

Always use HTTP Methods. Best practices with respect to each HTTP method is described below:

* `GET` : Should not update anything. Should be idempotent (same result in multiple calls). Possible Return Codes 200 (OK) + 404 (NOT FOUND) +400 (BAD REQUEST)
* `POST` : Should create new resource. Ideally return JSON with link to newly created resource. Same return codes as get possible. In addition : Return code 201 (CREATED) is possible.
* `PUT` : Update a known resource. ex: update client details. Possible Return Codes : 200(OK)
* `DELETE` : Used to delete a resource.

#### Project Structure

Following screenshot shows the structure of the project we have created. ![](https://i.imgur.com/Zvtz1E2.png) **A few details:**

* **LiveEntityResource.java** - Rest controller exposing all the three service methods discussed above.
* **LiveEntity.java** - Business Logic for the application.
* **UizaApplication.java** - Launcher for the Spring Boot Application. To run the application, just launch this file as Java Application.
* **pom.xml** - Contains all the dependencies needed to build this project. We will use Spring Boot Starter Web.

#### Adding Couple of GET Rest Services

The Rest Service LiveEntityResource exposes couple of get services.

@Autowired private RestTemplate restTemplate : We are using Spring Autowiring to wire the RestTemplate service into the LiveEntityResource. This rest template will use for call Uiza server api to get/create live entity. @Value("${application.uiza.url}") private String ulzaUrl : Use the uiza server url that we have configured in step1.

@PathVariable String id: Value of live entity id from the uri will be mapped to this parameter. package com.uiza.api.rest;

```
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.uiza.api.dto.GetLiveEntityResponse;
import com.uiza.api.dto.LiveEntity;

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/app/live/entities")
public class LiveEntityResource {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${application.uiza.url}")
    private String ulzaUrl;

    @GetMapping
    public GetLiveEntityResponse getLiveEntities() {

        ResponseEntity<GetLiveEntityResponse> responseEntity = restTemplate.getForEntity(ulzaUrl,
                GetLiveEntityResponse.class);

        return responseEntity.getBody();
    }

    @GetMapping("/{id}")
    public LiveEntity getLiveEntities(@PathVariable String id) {

        ResponseEntity<LiveEntity> responseEntity = restTemplate.getForEntity(ulzaUrl + "/" + id, LiveEntity.class);

        return responseEntity.getBody();
    }

}
```

**Executing the Get Service for retrieve all live Using Postman.**

We will fire a request to <http://localhost:8080/app/live/entities> to test the service. Response is as shown below.

```
[{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}]
```

**Executing the Get Service to retrieve live entity by id Using Postman**

We will fire a request to <http://localhost:8080/app/live/entities/2b970a39-874a-4d2a-be8a-fd445646d74c> to test the service. Response is as shown below.

```
{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}
```

#### Adding a POST Rest Service

A POST Service should return a status of created (201) when the resource creation is successful.

@PostMapping("/app/live/entities"): Mapping a url for the POST Request @RequestBody LiveEntity liveEntity: Using Binding to bind the body of the request to LiveEntity object. responseEntity.getBody(): Return a status of created. Also return the location of created resource as a Response Header.

```
    @PostMapping
    public LiveEntity createLiveEntity(@RequestBody LiveEntity liveEntity) {

        ResponseEntity<LiveEntity> responseEntity = restTemplate.postForEntity(ulzaUrl, liveEntity, LiveEntity.class);

        return responseEntity.getBody();
    }
```

**Executing a POST Rest Service**

Example Request is shown below. It contains all the details to create a live entity.

```
{
  "name": "Demo",
  "description": "AFF CUP",
  "region": "in-bangalore-1"
}
```

Example Response is shown below. It contains all the details that has been created for live entity.

```
{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}
```

#### Modification in live entity

* Suppose if we have to add new field in live entity then we have to do as below example.
* For example, If we have to add new field(abc) in live entity then we have to do below modification in LiveEntity.java

```javascript
private String abc;
public String getAbc(){ return abc; }
public void setAbc(String abc){ this.abc = abc; }
```

## Building the live streaming app (front-end part)

```


## Step 1. Creating a new Project and install dependencies
To build a broadcast web app, we start with creating a new react web application.
Let us create a brand new application. 
Open terminal / command prompt and execute the below lines to create a starter app: 

1. Create a new project
```

### Step 1. Creating a new Project and install dependencies

To build a broadcast web app, we start with creating a new react web application.

Let us create a brand new application.&#x20;

Open terminal / command prompt and execute the below lines to create a starter app:&#x20;

#### 1. Create a new project

To build a broadcast web app, we start with creating a new react web application. Let us create a brand new application. Open terminal / command prompt and execute the below lines to create a starter app:&#x20;

`npx create-react-app uiza`

#### 2. Get into the project directory

`cd uiza`

#### 3. Start the development server.

`npm start`

#### Getting started with Uiza

To start a broadcast with Uiza we will need to do two things:

1. Create a live entity in Uiza servers.
2. Get the stream\_url and stream\_key for this entity.

#### Install program dependencies

To increase the readability of this tutorial, we use the Axios library to send requests to the Uiza server. Install Axios with the following command:

`` `npm install axios` ``

To play the video stream we will need a player control. Install react-player with the following command:

`` `npm install react-player` ``

### Step 2. Make changes to the App.js

Open the \`App.js\` file in the \`src\` directory.

#### Import repositories

Import react, router, react video player and css file.

```javascript
import React, { Component } from 'react';
import ReactPlayer from 'react-player';
import './App.css';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useParams
} from "react-router-dom";
```

We need an JAVA API to access Uiza's services.

```javascript
const url = "https://api.uiza.sh/app/live/entities";
const default_headers = {
  "Content-Type": "application/json"
}
```

Then we import axios to send get and post requests:

```javascript
const  axios  =  require('axios').default;
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use application-wide states that can be displayed in the application, and manipulated at run-time. As you can see, we can set default values with states. Our default region value is `in-bangalore-1`

```javascript
state  = {
    message:  '',
    region_value:  'in-bangalore-1',
    broadcast_url:  '',
    broadcast_key:  ''
};
```

#### Define a function to start a broadcast

We define this function as `start_broadcast`. We clear the states and set the message state to `fetching`. Then we start loading the information.

```javascript
this.setState({message: "Fetching"});
this.setState({broadcast_url: ""});
this.setState({broadcast_key: ""});
```

Now we set the parameters, so that we can make the `create entity` call. The below structure contains all the information of the HTTP request that we pass to Axios. As you can see, we make use of the `region_value` state to set the region to a supported value.

```javascript
var broadcast_create_options = {
  "method": "post",
  "url": "https://api.uiza.sh/api/v5/live/entities",
  "headers": default_headers,
  "data": {
        "name": 'Demo app',
        "region": this.state.region_value,
        "description": 'Application description'
 }
};
```

Now let's create the polling call structure so that we don't end up creating the same structure from the loop. As you can see it will be a `GET` request. Authorization header will expect your API key.

```javascript
var broadcast_polling_options = {
  "method": "get",
  "headers": default_headers,
  "data": {
      "name": 'Demo app',
      "region": this.state.region_value,
      "description": 'Application description'
    }
};
```

We make a `POST` request to create an entity.

```javascript
var create_response = await axios(broadcast_create_options);
console.log('Response Received')
```

The call returns the entity `id` in the response.

```javascript
 var broadcast_id = create_response.data.id;
 this.setState({message: 'broadcast Created: '+ broadcast_id});
```

The `GET` method takes the entity `id` and returns the broadcast information (including the stream URL and key).

```javascript
broadcast_polling_options["url"] = url + "/" + broadcast_id;
```

To get the stream URL and key, the entity has to be in a `ready` state. We use setInterval to poll the API every 3 seconds to check the status of the entity using `response.data.status` The initial status of an entity is `init`. When the server is ready with a stream URL and key, the status becomes `ready`

If the status is not`ready` yet, we continue polling and the current state of `message` will be set to `Polling`

Once the status is `ready` we can extract `url` and `key` from the response.

`self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });`

The above code creates a nice text animation so that we know the program is not stuck and is working.

```javascript
var counter = 0;
var self = this;
var poll_interval = setInterval(async function() {
  try {
    var response = await axios(broadcast_polling_options);
    if (response.data.status === "ready") {
      self.setState({ message: "Stream is now ready" });
      self.setState({ broadcast_url: "URL: " + response.data.ingest.url });
      self.setState({ broadcast_key: "Key: " + response.data.ingest.key });
      clearInterval(poll_interval);
    } else {
      self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });
    }
    counter = counter + 1;
  } catch (error) { console.log(error) }
}, 3000);
```

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the `region_value`. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

The first line displays the messages from the program's status: `Fetching`, `Polling` etc.

```javascript
{this.state.message}<br/>
```

The second line contains the stream URL (i.e. `stream_url`)

```javascript
{this.state.broadcast_url}<br/>
```

The third line contains the key for the stream key (i.e `stream_key`)

```javascript
{this.state.broadcast_key}<br/>
```

#### Putting the broadcast page UI together:

```javascript
render() {
    return (
      <div className='page'>
        <div className="App">
          <h1> Uiza Guide </h1>
          <header className="App-header">

            <div style={{ align: "left", float: 'left', width: "45%", margin: "10px", height: "220px", padding: '10px', border: "1px solid white" }}>
              <p> Start broadcast <br />
                <label>Pick your region: &nbsp;
                <select value={this.state.region_value} onChange={(event) => { this.setState({ region_value: event.target.value }); }}>
                    <option value="in-bangalore-1">in-bangalore-1</option>
                    <option value="in-mumbai-1">in-mumbai-1</option>
                  </select>
                </label> &nbsp;
              <button onClick={this.start_broadcast}>Start broadcast</button> <br />
              {this.state.message}<br/>
              {this.state.broadcast_url}<br/>
              {this.state.broadcast_key}<br/>
              </p>
            </div>
            </header>
        </div></div>
    )
  }
}

export default App;
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams. Green tiles are online entities and red tiles are offline entities.

The following `load_alive_streams` function loads the streams. Available streams are loaded and saved to `state` so that they update automatically.

```javascript
load_alive_streams = async () => {
    var options = {
      "method": "get",
      "url": url,
      "headers": {
        "Content-Type": "application/json"
      }
    };
    var response = await axios(options);
    var data = response.data.data;
    var streams = [];
    data.forEach(element => {
      try {
        streams.push({
          online: element.broadcast === 'online' ? true : false,
          stream_url: element.ingest.url,
          stream_key: element.ingest.key,
          playback_url: element.playback.hls
        })
      } catch (err) { }
    });
    this.setState({
      streams: streams,
      last_loaded: new Date()
    });
    console.log(`Completed reading data: ${streams.length} streams are online now!`);
  }
```

#### Rendering the view page UI

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

The above line sends the user to an `href` link which is understood by the router later. The regex removes the protocol from the URL (i.e http / https)

Following code shows the VideoTile component:

```javascript
class VideoTile extends Component {

  render() {
    return (
      <div style={{
        width: "240px", height: "200px", float: "left", margin: "10px", padding: "8px", display: "flex", flexDirection: "column",
        wordWrap: "break-word", fontSize: "16px", border: "2px solid white", backgroundColor: this.props._online ? 'MediumSeaGreen' : 'Tomato'
      }}>

        {/* remove http(s) */}
        <a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
          <span name='url'>URL: {this.props._url}</span><br /><br />
          <span name='key'>KEY: {this.props._key}</span><br /><br />
          <span name='playback_url'>PLAYBACK: {this.props._playback_url}</span>
        </a>
      </div>
    )
  }
}
```

As mentioned above, requests are only made every 5-seconds. We attach the parameters to the VideoTile element. After putting it all together:

```javascript
render() {
    try {

      if (typeof this.state.last_loaded === "string" || ((new Date() - this.state.last_loaded) / 1000) > 5) {
        var items = [];
        this.load_alive_streams().then((result) => {

          for (const [index, value] of this.state.streams.entries()) {
            items.push(<VideoTile key={index}
                                  _url={value.stream_url}
                                  _key={value.stream_key}
                                  _playback_url={value.playback_url}
                                  _online={value.online}></VideoTile>)
          }

          this.setState({ items: items });
          console.log('Loading complete');
        });
      }
    } catch (err) {
      this.setState({ last_loaded: new Date() });
    }

    return (
      <div className="App">
        <h1 style={{ padding: "8px" }}>  Uiza Online Videos </h1>
        <header className="App-header">
          <div name='tileContainer'>
            {this.state.items}
          </div></header>
      </div>
    )
  }
```

### Step 6. Playback the live stream

Now we have the video tiles ready but what do we show when this tile is clicked? This clever little view code launches the player on screen. We launched the player on the screen when the tile is clicked with the following code:

```javascript
function VideoPage() {
  let { videoid } = useParams();
  return (
    <div style={{ padding: "20px" }}>
      <ReactPlayer url={"https://" + videoid} playing={true} controls={true}></ReactPlayer>
    </div>)
}
```

#### Routing and APP overall UI

We make use of the `Router` component in react to create pagination in our app. We will have the link to broadcast and view page

To enable pagination in the app, we need to make use of react's routing. Following code does the routing:

```javascript
class App extends Component {

  render() {
    return (
      <Router>
        <div className='page'>
          <nav>
            <ul>
              <li>
                <Link to="/broadcast">Broadcast Page</Link>
              </li>
              <li>
                <Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>
              </li>
            </ul>
          </nav>

          {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
          <Switch>
            <Route path="/broadcast">
              <BroadcastPage />
            </Route>
            <Route path="/viewer">
              <ViewerPage />
            </Route>
            <Route path="/video/:videoid*">
              <VideoPage />
            </Route>
          </Switch>
        </div>
      </Router>
    )
  }
}
```

The streams are loaded when we click on the viewer with the below line. Following line loads the streams on click: `<Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>`

The routing path below with `*` wildcard enables video stream url to be parsed with `/` and to be sent to the video page. Otherwise, the videoid is split at the first occurence of `/`

```javascript
<Route path="/video/:videoid*">
              <VideoPage />
```

## Conclusion

That's all wasn't that fun? If you have any questions please check out our Github repo where this entire project has been uploaded with the Java source code [here](https://github.com/uizaio/uiza-live-java-server-integration) and the Javascript source code [here](https://github.com/uizaio/uiza-node-sample-app). If you have any other questions please contact us here: <anhnh@uiza.io>


# Python Live Streaming App

How to build your live streaming web app with Uiza’s API using Python

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Python.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. Tha broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming app

### Prerequisites

Install following dependencies in terminal

### Step 1. Creating a new Project and install dependencies

#### Dependencies

`pip install python`&#x20;

`pip install django`&#x20;

`pip install json`

To build a broadcast web app, we start with creating a new python project.

#### Creating a new Project

1. Open your favorite editor
2. Open the terminal&#x20;
3. Type: django-admin createproject (this makes a directory with your project name) in the terminal
4. Go to your project directory `cd project name`
5. To create your app, type: `django-admin createApp <AppName>`(this creates an app inside your project)
6. Create a templates folder in which your html files will be held.Templates folder will be in project folder.

   <img src="/files/-LxUJIirbZ84tgk_Pn5x" alt="your project directory structure should look like this" data-size="original">

   your project directory structure should look like this &#x20;

   **Don't worry about the project and app name, as any name will work.**
7. Open `setting.py` and add the app name to the installed apps list. Also add templates path to templates dir.

![](https://i.imgur.com/C6vAgtS.png)

![](https://i.imgur.com/PQ9pSaN.png)

#### Setting up the templates folder

Create 4 html files in templates folder:&#x20;

1. `base.html`&#x20;
2. `homepage.html`&#x20;
3. `viewspage.html`&#x20;
4. `broadcastpage.html`

For now leave these empty.

#### Django connects and renders:

We will define some urls in the `urls.py` file in project directory. There we write the view name, which performs some functions and renders a html file.

`url eg: path('viewers/', views.viewerspage, name = 'viewers')` so here 'viewers/' is the url that will be added to localhost, views.viewerspage is name of views which will perform some functions on this url and name = 'viewers' is used to redirect to another view from html file after submission which we will use later.

### &#x20;Step 2. Setting up the URLS

You must have noticed the `urls.py` file in the project directory. Lets open it and see what it does. In the file we see some imports and a list named url patterns. As discussed we need to connect urls and views, so we will import views to `urls.py` file

`from app name import views`

We will make some urls in url patterns list like this. &#x20;

![](/files/-LxUKfUOLnyngow_c-sb)

`admin/` was defined already, that is the default url provided by Django and Django is known for this feature of providing an admin portal which keeps all the database of your website. But let's take example of `viewers/` url. Lets divide this into 3 parts: url, view, and name

**URL** - what URL should appear at the URL bar&#x20;

**View** - what view to call when user puts this URL in the URL bar.

**Name** - this is name of url which we will use when talking about templates to redirect to             other urls from html pages.(don't worry if it is not clear now)

````
now we will make some urls in url patterns list like this.
![](https://i.imgur.com/omMT2p2.png)

so 'admin/' was defined already, that is the default url provided by django and django is known for this feature of providing an admin portal which keeps all the database of your website.
But let's take example of 'viewers/' url.
so lets divide this into 3 parts url,view,name
**Url** - what url should appear at the url bar 
**View** - what view to call when user puts this url in        the url bar.
**Name** - this is name of url which we will use when           talking about templates to redirect to             other urls from html pages.(don't worry if it is not clear now)

## Step 2. Setting up authorization


We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

Following code shows the constants:
```python=
Authorization_key = "<<Your API key>>"
url = 'https://development-api.uizadev.io/v1/live_entities'
````

### Step 2. Setting up authorization

We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

Following code shows the constants:

```python
Authorization_key = "<<Your API key>>"
url = 'https://development-api.uizadev.io/v1/live_entities'
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use global variables that can be displayed in the application, and manipulated at run-time.

```python
stream_key = ''
stream_url = ''
stream_hls = ''
NotPlayable = True
```

#### Define a view to start a broadcast

**Note:** a function in python is called a view in Django. The below structure contains all the information of the HTTP request.

As you can see, we make use of the `region` state to set the region to a supported value.

We will create an Entity using the `POST` method:

So what below view does?

First, it checks if the request method is a POST method. If it is not, then a simple html page is rendered.

Otherwise, the if condition is triggered and the POST method will be called after the submit button of form is clicked, which we will see in the html file.

Then we make a POST request using the parameters and get back a json response from the Uiza API

The parameter are defined in Uiza's API documentation.

```python
#when broadcast button is click post method is triggered

def create_event(request):
    if request.method == "POST":
        region = request.POST['region']

        # necessary headers and data for the post request 
        headers = {'Authorization': Authorization_key ,
                'Content-Type': 'application/json',
                'cache-control': 'no-cache' }   
        data = {
                "name":"Demo",
                "region":region,
                "description":"AFF CUP"
                }
        #post request for the id of live stream    
        response = requests.post(url = url, headers = headers, params= data)
        print(response.text)
        #convert the response to json
        live_response = json.loads(response.text)
        #retrieved id from json
        created_id = live_response["id"]
```

Using the retrieved entity, we call the 'GET' method with `id` as value. The authorization header expects your API key.

```python
# Now make the get request using the headers and using the id retrieve the     stream_key,stream_url and playback
get_headers = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate',
    'Authorization': Authorization_key,
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
}

newUrl = url+'/' + created_id
```

Now let's create the polling call structure. This loop will run until the 'status' returned is 'ready'. As soon as the status becomes 'ready', the global variables for `stream_url`, `stream_key`, and `stream_hls` are retrieved from the GET request.

```python
        #This while loop will make the get request from the uiza UPI till the status is     not ready and retrieve the necessary info and then will render the homepage
        while True:
            retrieve_entity = requests.get(url = newUrl, headers=get_headers)
            retrieve_entity_json = json.loads(retrieve_entity.text)
            status = retrieve_entity_json["status"]
            print(status)
            print(i)
            if status == "ready":
                print(retrieve_entity_json)
                global stream_url
                stream_url = retrieve_entity_json["ingest"]["url"]
                global stream_key
                stream_key = retrieve_entity_json["ingest"]["key"]
                global stream_hls
                stream_hls = retrieve_entity_json['playback']['hls']
                global NotPlayable
                NotPlayable = False

                return render(request,'homepage.html')
return render(request,'broadcastpage.html') #This render will be called if post request is not made.
```

Now we go to our html pages which we created earlier:

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the regions. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

Now what does this html page do?

It uses some html tags and Django template tagging. Template tagging is used to insert logic into html. Basically this implements a html form and a Javascript polling function. Now have a look at `action` in form. This is a template tag which tells when form is submitted, then goes to a url whose name is broadcast. Remember we gave names to url paths in the `urls.py` file. Under that you will see csrf token which is cross-site request forgery used with forms always.

Now button tag contains value="submit". This means the value selected by user from the drop down will be attached with submit button so that we can use that value in views.

Polling function is just to give animation, so that when broadcast button is clicked, `Polling...` starts till we get response from the Uiza API. Consider it as loading of another html page.

Also consider: `{% extends 'base.html' %}` . This inherits all the html tags from `base.html` . Writing of repetitive html code for every page is prevented with this; the uniformity of the code is maintained as well.

Everything inside

```markup
{% block body_block %}
{% endblock %}
```

is unique to this html file.

```markup
{% extends 'base.html' %}
<!-- form for the broadcasting page which lets user to select the region and start broadcasting -->
{% block body_block %}
<h1>UIZA GUIDE</h1>
<div style="align-content:left;float:left;width:'45%';margin:'10px';height:'220px';padding:'10px'; border:'1px solid red'"></div>
<!-- the template tag in action will take us to create_event view because in urls.py the views name is broadcast -->
<!-- onsubmit of form StartPolling js function is called -->
<form action="{% url 'broadcast' %}"  method="POST" onSubmit="StartPolling();">
    {% csrf_token %}
    <p> Start broadcast <br /><p>
        <label>Pick your region: &nbsp;
                <select name="region" id="region">
                    <option value="in-bangalore-1">in-bangalore-1</option>
                    <option value="in-mumbai-1">in-mumbai-1</option>
                  </select>
                </label> &nbsp;
                <!-- after submission the selected value from the dropdown will go to the create event view -->
              <button  type="submit" value="select" >Start broadcast</button> <br />
              <span id="wait"></span>
            </form>              
            <!-- this js function will play as loading screen until we get the response of our request from the API  -->
              <script>
                  function StartPolling() {
                  setInterval(function Polling() {

                  var wait = document.getElementById("wait");
                  if(wait.innerHTML.length==0)
                    wait.innerHTML = "Polling";
                  if ( wait.innerHTML.length > 10 ) 
                    wait.innerHTML = "Polling";
                  else 
                    wait.innerHTML += ".";
                  }, 1000);
                  }

              </script>
    </p>

</div>
</div> 
{% endblock %}
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams.

This view will render simple html page when `NotPlayable` is false; when true, it will send the list of responses to `viewerspage.html`in a context dictionary.

Context dictionary is just the information passed to the html page from the view.

```python
def viewerspage(request):
    # if broadcast button is not clicked then this view is rendered
    if NotPlayable: 
        print('got here')
        list_of_videos = []
        return render(request,'viewerspage.html')
    else:    
        # if broadcast button is clicked then this view is rendered and a context         dictionary is passed with stream_key, stream_url, playback link

        stream_dict=    {'stream_key':stream_key,'stream_url':stream_url,'playback':stream_hls}
        list_of_videos.append(stream_dict)
    #The last parameter of render is the context dictionary, these are the variables     which store useful info that we would want to use in out templates
    return render(request,'viewerspage.html',{'list_of_videos':list_of_videos})
```

#### Rendering the view page html

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

Following code shows the VideoTile component:

In this html we inherit from base.html, then we go to our body block and apply a for loop, which will give us 3 keys, and we need the playback key's url that we have put into the video tag which plays the video on click.

In the following code block we inherit from base.html. The body block contains a for loop, which gives us 3 keys; the playback key's URL from the video tag is needed, to play the video on click.

```markup
{% extends 'base.html' %}
{% block body_block %}
<h1>UIZA ONLINE VIDEOS</h1>

     <!-- the list of videos got by the context dictionary will be displayed here with stream url, stream key and playback  -->
    {% for each in list_of_videos %}  

    <div class = 'tileContainer' style="width: 240px; height: 200px;float: left; margin: 10px; padding: 8px; display: flex; flex-Direction: column;
    word-Wrap: break-word; font-Size: 16px; border: 2px solid white; background-Color:Tomato;">    
      {% for key, value in each.items %}

      <!-- play the video when playback link is found else just print the link in the video tile -->
      {% if key == 'playback' %}
        <video src="key" type="application/x-mpegURL"></video>
      {% else %}
      <p><a href="{{value}}">{{key}}</a></p>
      {% endif %}

      </div>
    {% endfor %}
  {% endfor %}  
{% endblock %}
```

## Conclusion

That's how you can integrate live streaming into your app using Uiza's APIs. With just two API methods, you will have your stream key and stream URL to start a live stream. If you have any questions please check out our Github repo where this entire project has been uploaded with source code [here](https://github.com/info3g/python-uiza) and if you have any other questions please contact us here: <anhnh@uiza.io>


# How to integrate live streaming into an Android App using Uiza’s Live API

## Introduction

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming Android app with Uiza’s APIs. The full sample code can be downloaded at the end of the tutorial.

### Integrating live streaming into android application

For this tutorial, we build two separate apps: The streaming app, where a video is captured over the phone's camera and streamed; the viewer app, where all the live entities are listed and can be watched on mobile. Step 1 to Step 4 is for the Streaming App, and Step 5 to Step 7 is for the Viewer app.

### Uiza Terminologies

Throughout the tutorial we will be mentioning live entities, streamers and viewers.

`live entities` are basically live events, with or without a live feed. A live entity contains the information required for Uiza to allocate resources to power the live event, and direct your live feed toward these resources for ingestion and streaming.

`Streamer`: Streamers record the live events and are the source of the live signals that Uiza receives.

`Viewer`: Viewers are the users who watch the live stream on their devices. They are the destination of the delivery of the live stream.

## Prerequisite

* Android Studio 3.3 or above
* Min API 19 (Android KitKat)
* Real devices (Nexus 5X or other devices)

### Uiza Account

We need an API key to access Uiza’s services. To get your API key follow these steps: 1. create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). 2. In the developer console, go to your application 3. Save the API Key 4. Update API key at `samplelive/src/main/java/io/uiza/samplelive/SampleLiveApplication.java`

```java
private static final String API_TOKEN = <<API Key>>; // dynamic
```

## Step 1 - Streaming app - Dependencies and Permissions

We start with setting the permissions in the manifest file.

### Permissions

```java
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" /> <!-- needed by background Rtp service to keep service alive -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Optional for play store -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- for record -->
```

### Dependencies

Add the `Jitpack` repository to your `build.gradle` file

```java
allprojects {
      repositories {
         maven { url 'https://jitpack.io' }
      }
}
```

Add the Uiza live streaming and playback SDK as follow:

```java
defaultConfig {  
    multiDexEnabled  true
}  
dependencies {  
    // for playing VOD, LIVE video  
    implementation 'com.github.uizaio.uiza-android-sdk-player:uizacoresdk:[latest-release-number]'        

    // for broadcasting / live streaming
    implementation 'com.github.uizaio.uiza-android-sdk-player:uizalivestream:[latest-release-number]'  
}
```

You can get the latest release number [HERE](https://github.com/uizaio/uiza-android-sdk-player/releases)

If you are using uiza\_android\_sdk\_player (version 4.0.9 and above), you will need to import following dependencies:

```java
// for playing VOD, LIVE video
implementation 'com.github.uizaio.uiza-android-sdk-player:uizacoresdk:4.0.9'
implementation 'com.google.android.exoplayer:exoplayer:2.10.8'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.10.8'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.10.8'
```

## Step 2 - Creating a live entity

We pass on the parameters to `createEntity`.

```java
        CreateLiveBody body = new CreateLiveBody(
                "<streamName>",
                "<Description>",
                "<region>"
        );
        UizaLiveService liveService = UizaClientFactory.getLiveService();
        RxBinder.bind(
                liveService.createEntity(body),
                liveEntity -> {
                    // onSuceess
                }, throwable -> {
                    // onError
                    Timber.e(throwable);
                }, () -> {
                    // onComple
                }
        )
```

This step returns us a live entity ID; the ID is used for the following step.

## Step 3 - Getting the live entity info

We will use the live entity ID to retrieve the key & URL.

```java
RxBinder.bind(UizaClientFactory.getLiveService().getEntity("<entityId>"), liveEntity -> {
        // onSuccess
    }, throwable -> {
        //onError
    }, () -> {
        // onComplete
    });
```

## Step 4 - Making a live stream

We capture the live stream using the Android camera In layout xml

```markup
    <io.uiza.live.UizaLiveView
        android:id="@+id/uiza_live_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:audioBitrate="64"
        app:audioSampleRate="32000"
        app:audioStereo="true"
        app:fps="24"
        app:frame_interval="2"
        app:videoSize="p720"
        app:useCamera2="true"
        app:AAEnabled="false"
        app:isFlipHorizontal="false"
        app:isFlipVertical="false"
        app:keepAspectRatio="true"
        app:numFilters="1"/>
```

In java code:

```java
    UizaLiveView liveView = findViewById(R.id.uiza_live_view);
```

To Start: We pass the URL and Key from the API call to `startStream`

```java
    if (liveView.isRecording() || liveView.prepareStream()) {
        liveView.startStream(liveStreamUrl);
    }
```

To Stop

```java
    liveView.stopStream();
```

To Switch Camera

```
    try {
        liveView.switchCamera();
    } catch (UizaCameraOpenException e) {
        // error
    }
```

## Step 5 - Viewer app - listing he entities

### Viewer App - list out all entities

The viewer app will display all active live streams for the viewer.

```java
RxBinder.bind(
    UizaClientFactory.getLiveService()
        .getEntities()
        .map(ListWrap::getData),
    entities -> {
        //onSuccess
    }, throwable -> {
        // onError
    }
);
```

Currently a dummy thumbnail is in use. When the thumbnail API is added, this part of the code will be updated to include the thumbnail.

## Step 6 - playback a live stream

### Viewer App - playback feature

Using the Uiza player, we will playback the stream

In layout xml we set the video dimensions.

In Java code:

```java
    UZUtil.setCasty(activity);
    UZVideo uzVideo = findViewById(R.id.uiza_video);
    uzVideo.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT);
    UZUtil.initLiveEntity(this, uzVideo, liveEntity.getPlaybackInfo());
            uzVideo.setFreeSize(true);
```

## Step 7 - adding chat functionality

To create a communication channel between viewer and streamer, we enable chat. We will use Google's Firebase for this sample code, as it is very well supported and intuitive.

### Google Firebase integration

```
// authenticate to firebase
implementation 'com.google.firebase:firebase-auth:19.2.0'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
// database to storage message
implementation 'com.google.firebase:firebase-database:19.2.0'
```

To detail: <https://firebase.google.com/docs/android/setup>

Following code shows the chat integration into our sample app.

```java
    private void setupChatConnection() {
        if (liveEntity != null) {
            FirebaseDatabase database = FirebaseDatabase.getInstance();
            DatabaseReference reference = database.getReference(liveEntity.getId());

            reference.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    Timber.d("SUCCESS!");
                    handleReturn(dataSnapshot);
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Timber.e("ERROR: %s", databaseError.getDetails());
                }
            });
        }
    }
```

## Conclusion

Our API provides simple and intuitive integration into any Android app. You can focus on your application and let Uiza do the hard work. The source code to this tutorial can be found here: [Github](https://github.com/uizaio/uiza-android-sdk-player/tree/v5)


# Versioning

Uiza API current version is 2020-05-07

When we release a new API version, by default, all requests to our backend will be served with the newest API specs. We tagged which version is the main version on our documentation page.

Now we still developing the backward-compatible way to make sure that your code will work fine when Uiza updates the API version. Because of the situation, when we make changes to the API, we release a new dated version, but to avoid breaking your code, we will inform you one month before the change by email.

Read our [Release notes](https://docs.uiza.io/api-upgrades/release-notes) to learn more about the new features we serve our customers, the bug fixes and how we improve our performance. Also, read the [API changelog](https://docs.uiza.io/api-upgrades/api-changelog) to stay up to date on the API changes.


# Live Entities

A **`live_entity`** contains the information required for Uiza to successfully allocate resources to power the `live_entity`'s live broadcasting sessions. You can reuse a `live_entity` and broadcast multiple live sessions sequentially.&#x20;

The API allows you to create, delete, reset your `ingest.key`, and update the `name` and `description` of the `live_entity`. Individual entities and a list of all your entities are retrievable via these APIs too.

### The live entity object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the live entity.

> **`name`** *string*
>
> The name of your live entity. (limit 100 characters)

> **`description`** *string*
>
> Describes the content of the live entity. Often useful for displaying to viewers. You could update this accordingly to suit different sessions of a single live entity.

> **`encoding_template`** *string*&#x20;
>
> Specify the template that our ingest server will process your stream source, from SD to Full-HD for the output singal. There are 4 values that Uiza currently support:
>
> `none` We keep the output stream same as your source.
>
> `sd` The output contains 1 video profile with 480p resolution.
>
> `hd` The output contains 2 video profile with 480p and 720p resolutions.
>
> `fhd` The output contains 3 video profile with 480p, 720p, and 1080p resolutions.

> **`ingest`** *array*
>
> Contains the information required to access to Uiza's ingest servers. Use the `key` and `url` to configure your broadcasting software.

> **`playback`** *object*
>
> Contains the playback URL for different streaming protocols including HLS fMP4 (`hls`) and MPEG-dash (`mpd`). Use this URL to configure your player to play the live stream.

> **`region`** *string*
>
> The geographical region where your live streams are broadcasted from. In case your region is not yet supported, try the nearest available one. Here are the regions that Uiza currently supports:
>
> `in-bangalore-1` Bangalore, India.
>
> `in-mumbai-1` Mumbai, India.
>
> `sg-singapore-1` Singapore

> **`status`** *string*
>
> Once the request to create a `live_entity` is received, Uiza will allocate resources in the requested `region`. While the process may take up to 1 minute, the `status` of the `live_entity` is `init`. This will be updated to `ready` once resources are successfully allocated and to `broadcasting` during a broadcasting session.

> **`dvr`** *string*
>
> Indicates whether Digital Video Record (DVR) is enabled for the `live_entity`. Set to `true` to enable and to `false` to disable this feature.

> **`relay`** *array*
>
> A list of ingesting object contains the information required to access to 3rd ingest servers. Use the `key` and `url` to configure your broadcasting destination. Uiza will relay your signal to our server to list of ingest servers in `relay` array.

> **`created_at`** *string*
>
> The timestamp, at which the `live_entity` is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `live_entity` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Create a live entity

To start live streaming, you need to create an Entity object. Once the request is received, Uiza will allocate resources to serve your live stream.

## /v1/live-entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities`

#### Request Body

| Name               | Type    | Description                                                                                                                                                  |
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| name               | string  | The entity's name.                                                                                                                                           |
| description        | string  | An arbitrary string attached to the object. Often useful for displaying to users.                                                                            |
| dvr                | boolean | Indicates whether Digital Video Record (DVR) is enabled for the live\_entity. Set as `true` to enable and as `false` to disable. The default value is false. |
| encoding\_template | string  | Indicates whether encoding mode is enabled for the live\_entity. Set as `sd, hd` or `fhd` to enable and as `none` to disable.                                |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "Test event without encoding",
    "description": "Event for Test",
    "region": "in-bangalore-1",
    "status": "init",
    "dvr": false,
    "encoding_template": "none",
    "ingest": null,
    "playback": null,
    "relay": [],
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="Missing region" %}

```
{
  "message": "Your request is missing region parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="Invalid region" %}

```
{
  "message": "The requested region is invalid. See the list of available regions here: docs.uiza.io/getting-started/regions.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-live/owner/v1/live-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>' \
--data-raw '{
    "name": "Test event with encoding",
    "description": "Event for Test",
    "encoding_template": "sd"
}'
```

{% endcode %}


# Retrieve a live entity

Retrieves the details of an existing Live Entity. The entity’s id that was returned upon entity creation is required for identifying the exact live entity to be retrieved.

## /v1/live-entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                        |
| ---- | ------ | -------------------------------------------------- |
| id   | string | The identifier of your live entity to be retrieved |

{% tabs %}
{% tab title="200 Live entity successfully retrieved." %}

```
{
  "data": {
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Demo app 1",
    "description": "Demo application for documentation",
    "dvr": true,
    "encoding_template": "hd",
    "ingest": {
      "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "region": "in-mumbai-1",
    "relay": [
      {
        "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
        "name": "Replay name3333",
        "url": "rtmp://a.rtmp.youtube.com/live2",
        "key": "0df3-76bz-6t4r-1by5xxxxxx",
        "status": "enable",
        "created_at": "2020-06-24T16:25:58Z",
        "updated_at": "2020-06-24T16:25:58Z"
      }
    ],
    "status": "ready",
    "created_at": "2020-03-10T03:20:37.202Z",
    "updated_at": "2020-03-10T03:20:37.202Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```http
curl -X GET https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Update a live entity

Updates a specified live entity's name, description, dvr setting.

## /v1/live-entities/:id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                      |
| ---- | ------ | ------------------------------------------------ |
| id   | string | The identifier of the live entity to be updated. |

#### Request Body

| Name        | Type    | Description                                                                                                                                                                                                              |
| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| dvr         | boolean | Indicates whether Digital Video Record (DVR) is enabled for the live\_entity. Set as `true` to enable and as `false` to disable.                                                                                         |
| name        | string  | The new name of live entity to be updated. This parameter cannot be empty in your body request.                                                                                                                          |
| description | string  | The new description of the live entity to be updated. This version does not support update description as an empty string, in case your old description is incorrect, replace it with the new one that makes more sense. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Test Event Updated",
    "description": "Event for Test",
    "ingest": {
      "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "relay": [
      {
        "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
        "name": "Replay name3333",
        "url": "rtmp://a.rtmp.youtube.com/live2",
        "key": "0df3-76bz-6t4r-1by5xxxxxx",
        "status": "enable",
        "created_at": "2020-06-24T16:25:58Z",
        "updated_at": "2020-06-24T16:25:58Z"
      }
    ],
    "preset": null,
    "region": "in-bangalore-1",
    "status": "ready",
    "dvr": false,
    "encode": false,
    "created_at": "2019-12-11T02:47:04Z",
    "updated_at": "2019-12-16T02:53:30Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X PUT https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "Test Event Updated", "description": "Event for Test"}'
```

{% endcode %}


# Delete a live entity

Permanently deletes a live entity. You need to stop broadcasting from your end to be able to delete a live entity. Once a live entity is deleted, it cannot be undone.

## /v1/live-entities/:id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                    |
| ---- | ------ | ---------------------------------------------- |
| id   | string | The identifier if the live event to be deleted |

{% tabs %}
{% tab title="200 " %}

```
{}
```

{% endtab %}

{% tab title="400 " %}

```
{
  "message": "The live entity is fail on allocating resource and will be deleted by system.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 Could not find a cake matching this query." %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="409 " %}
{% tabs %}
{% tab title="Delete a broadcasting entity" %}

```
{
  "message": "The live entity is broadcasting and could not be deleted. Please, stop the live session and try again.",
  "error_type": "video_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X DELETE https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# List all live entities

Returns a list of existing live entities in descending order by creation date (the most recently created one is on top)

## /v1/live-entities

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities`

#### Query Parameters

| Name  | Type   | Description                                                     |
| ----- | ------ | --------------------------------------------------------------- |
| limit | number | The maximum number of objects to be returned, between 1 and 20. |
| page  | string | The pagination number of the result page to be retrieved.       |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "items": [
      {
        "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
        "name": "Demo app 1",
        "description": "Demo application for documentation",
        "dvr": true,
        "encoding_template": "none",
        "ingest": {
          "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
          "key": "live_TB62vHgxSY"
        },
        "playback": {
          "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
          "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
        },
        "region": "in-mumbai-1",
        "relay": [
          {
            "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
            "name": "Replay name3333",
            "url": "rtmp://a.rtmp.youtube.com/live2",
            "key": "0df3-76bz-6t4r-1by5xxxxxx",
            "status": "enable",
            "created_at": "2020-06-24T16:25:58Z",
            "updated_at": "2020-06-24T16:25:58Z"
          }
        ],
        "status": "ready",
        "created_at": "2020-03-10T03:20:37.202Z",
        "updated_at": "2020-03-10T03:20:37.202Z"
      }
    ],
    "total": 99
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X GET https://api.uiza.io/api-live/owner/v1/live-entities 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Create a live relay

A Relay is ingesting object that contains the information required to access 3rd ingest servers (a.k.a RTMP/broadcast destination). Use the key and url to configure it.

## /v1/live-entities/:id/relays

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays`

#### Path Parameters

| Name | Type   | Description                                                               |
| ---- | ------ | ------------------------------------------------------------------------- |
| id   | String | The identifier of the live entity you want to create a new relay into it. |

#### Request Body

| Name | Type   | Description                                                                             |
| ---- | ------ | --------------------------------------------------------------------------------------- |
| name | String | The name of your broadcast destination.                                                 |
| url  | string | The new RTMP server endpoint to be updated, make sure it included the `rtmp://` prefix. |
| key  | string | The key of your new RTMP server that you want the live entity relay to.                 |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
    "name": "Replay name3333",
    "url": "rtmp://a.rtmp.youtube.com/live2",
    "key": "0df3-76bz-6t4r-1by5xxxxxx",
    "status": "enable",
    "created_at": "2020-06-24T16:25:58Z",
    "updated_at": "2020-06-24T16:25:58Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The relay information is included in a [live entity](/2022-06-22/api-reference/live-entities).
{% endhint %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "A Relay Updated", "url": "rtmp://youtu.be/live", "key": "test-key"}'
```

{% endcode %}


# Update a live relay

## /v1/live-entities/:id/relays/:relay\_id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays/:relay_id`

#### Path Parameters

| Name      | Type   | Description                                               |
| --------- | ------ | --------------------------------------------------------- |
| id        | string | The identifier of the live entity you want to be updated. |
| relay\_id | string | The identifier of the relay object.                       |

#### Request Body

| Name | Type   | Description                                                                             |
| ---- | ------ | --------------------------------------------------------------------------------------- |
| name | string | The new name of relay to be updated.                                                    |
| url  | string | The new RTMP server endpoint to be updated, make sure it included the `rtmp://` prefix. |
| key  | string | The key of your new RTMP server that you want the live entity relay to.                 |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
    "name": "Replay name3333",
    "url": "rtmp://a.rtmp.youtube.com/live2",
    "key": "0df3-76bz-6t4r-1by5xxxxxx",
    "status": "enable",
    "created_at": "2020-06-24T16:25:58Z",
    "updated_at": "2020-06-24T16:25:58Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X PUT https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays/8cf47749-1fa4-40e9-8303-580b34f14683 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "A Relay Updated", "url": "rtmp://youtu.be/live", "key": "test-key"}'
```

{% endcode %}


# Delete a live relay

## /v1/live-entities/:id/relays/:relay\_id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays/:relay_id`

#### Path Parameters

| Name      | Type   | Description                                               |
| --------- | ------ | --------------------------------------------------------- |
| id        | string | The identifier of the live entity you want to be updated. |
| relay\_id | string | The identifier of the relay object.                       |

{% tabs %}
{% tab title="200 " %}

```
{}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X DELETE https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays/8cf47749-1fa4-40e9-8303-580b34f14683 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Video Entities

A **`video_entity`** is created every time a video is uploaded to Uiza via a URL which redirects Uiza to your video storage to retrieve the video file. This URL could be either a *direct HTTP/HTTPS* link or a URL that leads to your *FTP or S3 storage*.&#x20;

Once the video has been successfully retrieved, Uiza transcodes the file into several renditions that have different resolutions and are compatible to different streaming protocol such as *HLS, fMP4*... These renditions are made available to your viewers by you publishing them to Uiza's *Content Delivery Network (CDN)* via Uiza APIs.

The APIs allow you to create, delete, publish, update the information of the video\_entities and retrieve your entities individually or collectively.

### The video entity object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the video entity.

> **`name`** *string*
>
> The name of your video entity.

> **`description`** *string*
>
> Describes the content of the video entity. Often useful for displaying to viewers.

> **`input_url`** *string*
>
> The source file URL of the video entity.

> **`encoding_template`** *string*&#x20;
>
> Specify the template that our ingest server will process your stream source, from SD to Full-HD for the output singal. There are 4 values that Uiza currently support:
>
> `none` We keep the output stream same as your source.
>
> `sd` The output contains 1 video profile with 480p resolution.
>
> `hd` The output contains 2 video profile with 480p and 720p resolutions.
>
> `fhd` The output contains 3 video profile with 480p, 720p, and 1080p resolutions.

> **`status`** *string*
>
> The status indicates whether your video entity had been published to Uiza's CDN or not. There are 4 possible statuses:
>
> > **`processing`** is returned when your video entity is in the queue to be published.
> >
> > **`ready`** is returned when your video entity has been successfully published and your viewers are able to watch the video.
> >
> > **`error`** is returned when something goes wrong during the publishing process of your video entity.

> **`playback`** *object*
>
> Contains the playback URL for different streaming protocols including HLS fMP4 (`hls`), and MPEG-dash (`dash`). Use this URL to configure your player to play the video.

> **`created_at`** *string*
>
> The timestamp, at which the `video_entity` is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `video_entity` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Create a video entity

To create your video streaming, you need to create an Entity object.

## /v1/video-entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities`

#### Request Body

| Name                                   | Type   | Description                                                                                                                   |
| -------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
| name<mark style="color:red;">\*</mark> | string | The entity's name.                                                                                                            |
| description                            | string | An arbitrary string attached to the object. Often useful for displaying to users.                                             |
| encoding\_template                     | string | Indicates whether encoding mode is enabled for the live\_entity. Set as `sd, hd` or `fhd` to enable and as `none` to disable. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    "content_policy": "public",
    "status": "processing",
    "playback": null,
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>' \
--data-raw '{
    "name": "My video 1",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd"
}'
```

{% endcode %}


# Retrieve a video entity

Retrieves the details of an existing Video Entity. The entity’s id that was returned upon entity creation is required for identifying the exact live entity to be retrieved.

## /v1/video-entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                         |
| ---------------------------------- | ------ | --------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be retrieved |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    "content_policy": "public",
    "status": "ready",
    "playback": {
      "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
      "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Update a video entity

Updates a specified Video entity's name, description,...

## /v1/video-entities/:id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                       |
| ---------------------------------- | ------ | ------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be updated |

#### Request Body

| Name        | Type   | Description                                                                                                                                                                                                                      |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | String | The new name of the video entity is to be updated. This parameter cannot be empty in your body request.                                                                                                                          |
| description | String | The new description of the video entity is to be updated. This version does not support updating a description as an empty string, in case your old description is incorrect, replace it with the new one that makes more sense. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    content_policy: "public",
    "status": "ready",
    "playback": {
      "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
      "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request PUT 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Delete a video entity

Permanently deletes a video entity. Once a video entity is deleted, it cannot be undone.

## /v1/video-entities/:id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                       |
| ---------------------------------- | ------ | ------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be deleted |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {}
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request DELETE 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# List all video entities

Returns a list of existing Video entities in descending order by creation date (the most recently created one is on top)

## /v1/video-entities

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities`

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "items": [
      {
        "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
        "name": "My video 1",
        "description": "Oops",
        "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
        "encoding_template": "hd",
        "content_policy": "public",
        "status": "ready",
        "playback": {
          "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
          "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
        },
        "created_at": "2020-03-23T07:22:34Z",
        "updated_at": "2020-03-23T07:22:34Z"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Events

Uiza  creates **`event`** objects containing data of the events occurred in your Uiza account that your applications might be interested in, for instance, a `live_entity` is created, a `ingest.key` is reset or a `video_entity` is deleted, etc.&#x20;

While some API requests do not cause any `event` to be created such as *Retrieve a live entity*, other APIs may generate more than one `event`. For example, when you create a live entity, a `live_entity.created`, a `live_entity.resource.accepted` and a `live_entity.ready` events will be created consecutively.

Fundamentally, an `event` is created whenever there is a change in the state of an API resource. Therefore, there are `events` created without the trigger of any API request. A `live_entity.publish` created when Uiza receives your live feed signal is triggered by your broadcasting software, not as the result of an API request.


# Event Types

Our event types are designed following the `resource.event` format for your intuitive coding. As new event types will be added as we roll out more features or make updates to existing ones, we recommend you to revisit this list whenever you receive a new event type.

#### Live entity and session related

> **`live_entities.created`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is created.

> **`live_entities.updated`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is updated.

> **`live_entities.deleted`**    *`data.object` is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is deleted.

> **`live_entities.ready`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever the `status` of a live entity is changed to `ready`. This event indicates that the live entity you created is ready to ingest and broadcast.

> **`live_entities.publish`**    *`data.object`* *contains a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity receives the first live signal of a live session.

> **`live_entities.publish_done`**    *`data.object`* *contains a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live session ends.


# Webhook Endpoints

**Webhook** provides a mechanism for Uiza to notifies you about the `events` that happen in your Uiza account. When something interesting happens (a `live_entity` is created, a `ingest.key` is reset, a `video_entity` is deleted, etc.) Uiza creates an `event` object which contains the details of what just occurred. This `event` will then be sent to the webhook endpoint, a pre-configured URL where Uiza makes HTTP POST requests to.

A single `event` could be be sent to multiple webhook endpoints. You could generate endpoint URLs for your tests [here](https://webhook.site/).

### The webhook endpoint object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the object.

> **`url`** *string*
>
> The URL of the `webhook_endpoint`.

> **`status`** *string*
>
> Indicates the current status of the `webhook_endpoint`, which is either `disabled` or `enabled`.

> **`signing_secret`** *string*
>
> SThe endpoint’s secret, used to generate webhook signature. Only returned at creation.

> **`event_type`** *array*
>
> The list of events to enable for this endpoint. `[’*’]` indicates that all events are enabled, except those that require explicit selection.

> **`created_at`** *string*
>
> The timestamp, at which the `webhook_endpoint`is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `webhook_endpoint` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Verifying signatures

The `Uiza-Signature` header included in each signed event contains a timestamp and one or more signatures. The timestamp is prefixed by `t=`, and each signature is prefixed by a *scheme*. Schemes start with `v`, followed by an integer. Currently, the only valid live signature scheme is `v1`

```
Uiza-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
```

Note that newlines have been added for clarity, but a real `Uiza-Signature` header is on a single line.

Uiza generates signatures using a hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) with [SHA-256](https://en.wikipedia.org/wiki/SHA-2). To prevent [downgrade attacks](https://en.wikipedia.org/wiki/Downgrade_attack), you should ignore all schemes that are not `v1`.

It is possible to have multiple signatures with the same scheme-secret pair. This can happen when you roll an endpoint’s secret from the Dashboard, and choose to keep the previous secret active for up to 24 hours. During this time, your endpoint has multiple active secrets and Uiza generates one signature for each secret.

Although it’s recommended to use our official libraries to verify webhook event signatures, you can create a custom solution by following these steps.

#### Step 1: Extract the timestamp and signatures from the header  <a href="#extract-timestamp" id="extract-timestamp"></a>

Split the header, using the `,` character as the separator, to get a list of elements. Then split each element, using the `=` character as the separator, to get a prefix and value pair.

The value for the prefix `t` corresponds to the timestamp, and `v1` corresponds to the signature (or signatures). You can discard all other elements.

#### Step 2: Prepare the `signed_payload` string  <a href="#prepare-payload" id="prepare-payload"></a>

The `signed_payload` string is created by concatenating:

* The timestamp (as a string)
* The character `.`
* The actual JSON payload (i.e., the request body)

#### Step 3: Determine the expected signature  <a href="#determine-expected-signature" id="determine-expected-signature"></a>

Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the `signed_payload` string as the message.

#### Step 4: Compare the signatures  <a href="#compare-signatures" id="compare-signatures"></a>

Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.

#### Code Example: Create a lib webhook.js file with content below

```javascript
'use strict';
const crypto = require('crypto');
const utils = {
  secureCompare: (a, b) => {
    a = Buffer.from(a);
    b = Buffer.from(b);
    if (a.length !== b.length) {
      return false;
    }
    if (crypto.timingSafeEqual) {
      return crypto.timingSafeEqual(a, b);
    }
    const len = a.length;
    let result = 0;
    for (let i = 0; i < len; ++i) {
      result |= a[i] ^ b[i];
    }
    return result === 0;
  },
}

const Webhook = {
  DEFAULT_TOLERANCE: 300, // 5 minutes
  constructEvent(payload, header, secret, tolerance) {
    this.signature.verifyHeader(
      payload,
      header,
      secret,
      tolerance || Webhook.DEFAULT_TOLERANCE
    );

    const jsonPayload = JSON.parse(payload);
    return jsonPayload;
  },

  /**
   * Generates a header to be used for webhook mocking
   *
   * @typedef {object} opts
   * @property {number} timestamp - Timestamp of the header. Defaults to Date.now()
   * @property {string} payload - JSON stringified payload object, containing the 'id' and 'object' parameters
   * @property {string} secret - Webhook secret 'webhook_...'
   * @property {string} scheme - Version of API to hit. Defaults to 'v1'.
   * @property {string} signature - Computed webhook signature
   */
};

const signature = {
  EXPECTED_SCHEME: 'v1',
  _computeSignature: (payload, secret) => {
    return crypto
      .createHmac('sha256', secret)
      .update(payload, 'utf8')
      .digest('hex');
  },

  verifyHeader(payload, header, secret, tolerance) {
    payload = Buffer.isBuffer(payload) ? payload.toString('utf8') : payload;
    if (Array.isArray(header)) {
      throw new Error(
        'Unexpected: An array was passed as a header, which should not be possible for the uiza-signature header.'
      );
    }

    header = Buffer.isBuffer(header) ? header.toString('utf8') : header;

    const details = parseHeader(header, this.EXPECTED_SCHEME);

    if (!details || details.timestamp === -1) {
      throw {message:'Unable to extract timestamp and signatures from header',name:'unable_to_extract_timestamp_and_signature_from_header'}
    }

    if (!details.signatures.length) {
      throw {message:'No signatures found with expected scheme',name:'signature_not_found'}
    }

    const expectedSignature = this._computeSignature(
      `${details.timestamp}.${payload}`,
      secret
    );

    const signatureFound = !!details.signatures.filter(
      utils.secureCompare.bind(utils, expectedSignature)
    ).length;
    if (!signatureFound) {
      throw { message: "No signatures found matching the expected signature for payload.", name: 'signature_not_found' }
    }

    const timestampAge = Math.floor(Date.now() / 1000) - details.timestamp;

    if (tolerance > 0 && timestampAge > tolerance) {
      throw {message:'Timestamp outside the tolerance zone',name:'timestamp_outside_zone'}
    }

    return true;
  },
};

function parseHeader(header, scheme) {
  if (typeof header !== 'string') {
    return null;
  }

  return header.split(',').reduce(
    (accum, item) => {
      const kv = item.split('=');

      if (kv[0] === 't') {
        accum.timestamp = kv[1];
      }

      if (kv[0] === scheme) {
        accum.signatures.push(kv[1]);
      }

      return accum;
    },
    {
      timestamp: -1,
      signatures: [],
    }
  );
}

Webhook.signature = signature;

module.exports = Webhook;
```

Verify

```javascript
    async (req,res)=>{
      const webhook = require('./webhook.js')
      const signature = req.headers['uiza-signature']
      const signing_secret = <Your signing_secret>
      const payload =req.body
      let payloadString = JSON.stringify(payload, null, 2)
      const event = webhook.constructEvent(payloadString, signature, signing_secret);
    }
```


# Create a webhook endpoint

A URL and a secret are required for webhook endpoint creation. While URLs are endpoints where Uiza sends the events to, secrets are used to generate webhook signatures.

## /v1/webhook

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-account/owner/v1/webhook`

Set up your webhook endpoint to receive live events from Uiza

#### Headers

| Name           | Type   | Description                     |
| -------------- | ------ | ------------------------------- |
| Authentication | string | Authentication token or Api Key |

#### Request Body

| Name        | Type   | Description                                                                                                                                  |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| url         | string | The URL of the webhook endpoint.                                                                                                             |
| event\_type | array  | The list of events to enable for this endpoint. `[’*’]` indicates that all events are enabled, except those that require explicit selection. |
| status      | string | The status of the webhook. It can be `enabled` or `disabled`.                                                                                |

{% tabs %}
{% tab title="200 Cake successfully retrieved." %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "signing_secret":"webhook_8fCc3HaU0a-aJT2szrU7",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}

> ```
> Sample Request
>
>
> curl --location --request POST 'https://api.uiza.io/api-account/owner/v1/webhook/'        
> --header 'Content-Type: application/json'  --header 'Authorization: '    
> --data-raw '{
>   "url": "https://uiza-example.com/webhook",
>   "status": "enabled",
>   "event_type": [
>     "live_entities.created"
>   ]
> }'
> ```

## /v1/webhook\_endpoints

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/webhook_endpoints`

#### Request Body

| Name   | Type   | Description                                                                         |
| ------ | ------ | ----------------------------------------------------------------------------------- |
| secret | string | The token used to validate the communication between Uiza and the webhook endpoint. |
| url    | string | The URL of the webhook endpoint.                                                    |

{% tabs %}
{% tab title="200 " %}

```
{
 "id": "f0f207af-b338-4b7f-8d32-fe9cfa9566eb",
 "url": "https://webhook-test.com/live/created",
 "status": "enabled",
 "created_at": "2019-12-16T10:57:32Z",
 "updated_at": "2019-12-16T10:57:32Z"
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing URL" %}

```
{
 "message": "Your request is missing url parameter. Please, verify and resubmit.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
 "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="409 " %}

```
{
 "message": "The requested app_id already registered with a webhook.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
 "message": "An unexpected error occurred on Uiza's end.",
 "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.sh/v1/webhook_endpoints
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64'
     -d '{"url": "https://webhook-test.com/live/created", "secret": "a-secret"}'
```

{% endcode %}


# Update a webhook endpoint

Updates the URL or secret of a webhook endpoint. You could also use this API to enable or disable your webhook endpoints. Any parameters not provided will be left unchanged.

## /v1/webhook/:id&#x20;

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-account/owner/v1/webhook/:id`

#### Path Parameters

| Name | Type   | Description           |
| ---- | ------ | --------------------- |
| id   | string | The webhook entity id |

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

#### Request Body

| Name        | Type   | Description |
| ----------- | ------ | ----------- |
| event\_type | array  |             |
| status      | string |             |
| url         | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data":{
    "id":"e9d49e8e-4b9b-4693-974a-76e177edb21a"
  }
}
```

{% endtab %}
{% endtabs %}


# Get a webhook endpoint

## /v1/webhook/:id&#x20;

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-account/owner/v1/webhook/:id`

#### Path Parameters

| Name | Type   | Description           |
| ---- | ------ | --------------------- |
| id   | string | The webhook entity id |

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}


# List all webhook endpoint

## /v1/webhook

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-account/owner/v1/webhook`

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}


# Introduction

{% content-ref url="/pages/-LxZwMIn5rPMsm9D2nrv" %}
[Android SDK](/2022-06-22/sdk-reference/android-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-LxZyPlIaA9pX\_2im0g\_" %}
[iOS SDK](/2022-06-22/sdk-reference/ios-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-LxRNC97ltOAoqq4CIFV" %}
[Web Player SDK](/2022-06-22/sdk-reference/web-player-sdk)
{% endcontent-ref %}


# Android SDK

## Welcome to Uiza Android SDK

Uiza provides Android SDKs for broadcasting and playback. The SDKs helps you set up your mobile application using Uiza's platform. You can start building your application on top and let Uiza handle the backbone of video and live streaming.

{% content-ref url="/pages/-M3\_4RDrQ-UwqSNON6AU" %}
[Android Player SDK](/2022-06-22/sdk-reference/android-sdk/android-player-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-M3\_6DPhhfxTUzRDy9Jd" %}
[Android Broadcast SDK](/2022-06-22/sdk-reference/android-sdk/android-broadcast-sdk)
{% endcontent-ref %}


# Android Player SDK

[![](https://camo.githubusercontent.com/d9251a4a27b44035616a8defef539fe459d66136/68747470733a2f2f6a69747061636b2e696f2f762f75697a61696f2f75697a612d616e64726f69642d706c617965722d73646b2e737667)](https://jitpack.io/#uizaio/uiza-android-player-sdk)

[![Play Store](https://camo.githubusercontent.com/e506ee96bbe6031926c6daebfaa3a07aebf8239b/68747470733a2f2f7777772e676f6f676c652e636f6d2f70686f746f732f61626f75742f7374617469632f696d616765732f62616467655f676f6f676c655f706c61795f333664702e737667)](https://play.google.com/store/apps/details?id=com.uiza.sampleplayer)

Link to the Source code here: <https://github.com/uizaio/snake.sdk.android-player>

## Welcome to UIZA Android Player SDK

Simple Streaming at scale.

Uiza is the complete toolkit for building a powerful video streaming application with unlimited scalability. We design Uiza so simple that you only need a few lines of codes to start streaming, but sophisticated enough for you to build complex products on top of it.

Read [CHANGELOG here](https://github.com/uizaio/uiza-android-sdk/blob/master/CHANGELOG.md).

## Importing the Library

**Step 1. Add the `JitPack` repository to your `build.gradle` file**

```
    allprojects {
          repositories {
             maven { url 'https://jitpack.io' }
          }
    }
```

**Step 2. Add the dependency**

```
    implementation 'com.github.uizaio:uiza-android-player-sdk:1.1.x'
```

For **Android Support Compat** (Support until January 2021)

```
    implementation 'com.github.uizaio:uiza-android-player-sdk:1.0.x'
```

Get latest release number [HERE](broken://pages/-M3_4hri1XaNb8ZQQSb3).

* Additionally, if you want to use the Chromecast feature, add the following dependencies to your project:

```
        // for ChromeCast
        implementation 'androidx.mediarouter:mediarouter:1.0.0'
        implementation 'com.google.android.gms:play-services-cast-framework:18.1.0'
```

if you use `android support compat`

```
        // for ChromeCast
        implementation 'com.android.support:mediarouter-v7:28.0.0'
        implementation 'com.google.android.gms:play-services-cast-framework:16.2.0' // from 17.x support androidx only
```

* If advertising support should be enabled, also add the following dependencies to your project:

```
        // for IMA Ads
        implementation 'com.google.android.exoplayer:extension-ima:2.10.8'
        implementation 'com.google.android.gms:play-services-ads:19.0.1' // from 18.x support androidx only
```

**Note:**

* The version of the ExoPlayer Extension IMA must match the version of the ExoPlayer library being used.
* If you are using both ChromeCast and IMA Ads dependencies, we recommend using dependency `com.google.android.gms:play-services-cast-framework:$version` with `version >= 18.1.0` or `version=16.2.0` (support compat) to avoid dependency version conflicts

Check [example here](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/build.gradle).

**Turn on Java 8 support**

If not enabled already, you need to turn on Java 8 support in all `build.gradle` files depending on ExoPlayer, by adding the following to the `android` section:

```
compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}
```

> Node, Inside v1:
>
> * Use [androidx](https://developer.android.com/jetpack/androidx)
> * Use [Timber](https://github.com/JakeWharton/timber) for logger

## Init SDK

1. Init UZPlayer

   ```
   public class App extends MultiDexApplication {
          @Override
          public void onCreate() {
              super.onCreate();
              UZPlayer.init();
          }
   }
   ```
2. If you want show log, install any `Tree` instances you want in the `onCreate` of your application class

```
	if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        }
```

### Manifest

```
    <application
      android:name=".App"
    >
```

## How to play the video?:

**XML**

```
    <com.uiza.sdk.view.UZVideoView
      android:id="@id/uiza_video"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
```

**JAVA**

```
Create java file MainActivity:

    public class MainActivity extends AppCompatActivity implements UZCallback {
       ...
    }
```

Manifest

```
    <activity
      android:name=".MainActivity "
      android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" />
```

In your `activity` or `fragment`

* Play with entity:

  ```
  uzVideo = (UZVideoView) findViewById(R.id.uiza_video);
  uzVideo.setUZCallback(this);
  uzVideo.play(UZPlayback playback);
  // or 
  UZPlayer.setCurrentPlayback(UZPlayback playback);
  uzVideo.play();
  // or playlist
  uzVideo.play(List<UZPlayback> playlist);
  ```

Don't forget to add in activity life cycle event:

```
    @Override
    public void onDestroy() {
        uzVideo.onDestroy();
        super.onDestroy();
    }

    @Override
    public void onResume() {
        uzVideo.onResume();
        super.onResume();
    }

    @Override
    public void onPause() {
        uzVideo.onPause();
        super.onPause();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        uzVideo.onActivityResult(resultCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }
```

## How to customize your skin?

Only 3 steps, you can customize everything about player skin.

**Step 1:** Create layout ***uzplayer\_skin\_custom.xml*** like [THIS](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/src/main/res/layout/uzplayer_skin_custom.xml):

Please note *`app:controller_layout_id="@layout/uz_controller_custom_layout"`*

**Step 2:** Create layout ***uz\_controller\_custom\_layout.xml*** like [THIS](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/src/main/res/layout/uz_controller_custom_layout.xml):

* In this xml file, you can edit anything you like: position, color, drawable resouces...
* You can add more view (TextView, Button, ImageView\...).
* You can remove any component which you dont like.
* Please note: Don't change any view `id`s if you are using it.

**Step 3:** On function `onCreate()` of `Activity`, put this code:

```
    UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
```

Ex:

```
    @Override
    protected void onCreate(@Nullable Bundle savedState) {
		UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
        super.onCreate(savedState);
    }
```

**Note:** If you are using Chromecast, please use UZPlayer.setCasty(Activity activity) on function onCreate() of Activity

```
    @Override
    protected void onCreate(@Nullable Bundle savedState) {
        UZPlayer.setCasty(this);
        UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
        super.onCreate(savedState);
    }
```

Ex: findView from your custom layout:

```
    TextView tvSample = uzVideo.findViewById(R.id.tv_sample);
```

That's enough! This code above will change the player's skin quickly. You can build and run your app now.

But if you wanna change the player's skin when the player is playing, please you this function:

```
    uzVideo.changeSkin(R.layout.uzplayer_skin_custom);
```

***Note:***

* You should not change the id of the view. Ex: `android:id="@id/player_view"` Do not change `android:id="@id/player_view_0"` or `android:id="@+id/player_view_0"` ...

## Picture In Picture (PIP)

1. You can use `UZDragView`, review [`PlayerActivity`](https://github.com/uizaio/uiza-android-player-sdk/blob/master/sampleplayer/src/main/java/com/uiza/sampleplayer/PlayerActivity.java)
2. From `Android Nougat` (Android SDK >= 24) Google supported `PIP`. To implement, in `AndroidManifest.xml` add `android:supportsPictureInPicture="true"` inside `Your Activity` and review [`PIPPlayerActivity`](https://github.com/uizaio/uiza-android-player-sdk/blob/master/sampleplayer/src/main/java/com/uiza/sampleplayer/PipPlayerActivity.java).

## R8 / ProGuard

***Do not support R8***

```
    buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        useProguard true
        proguardFiles = [
            getDefaultProguardFile('proguard-android.txt'),
            'proguard-rules.pro'
        ]
    }
    }
```

## For contributors

Uiza Checkstyle configuration is based on the Google coding conventions from Google Java Style that can be found at [here](https://google.github.io/styleguide/javaguide.html).

Your code must be followed the rules that defined in our [`uiza_style.xml` rules](https://github.com/uizaio/uiza-android-player-sdk/tree/master/configs/codestyle/uiza_style.xml)

You can setting the rules after import project to Android Studio follow below steps:

1. **File** > **Settings** > **Editor** > **Code Style**
2. Right on the `Scheme`, select the setting icon > **Import Scheme** > **Intellij IDEA code style XML**
3. Select the `uiza_style.xml` file path
4. Click **Apply** > **OK**, then ready to go

For apply check style, install [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea), then

1. **File** > **Settings** > **Other Settings** > **Checkstyle**
2. In Configuration file, select the **`+`** icon
3. Check `Use local checkstyle file` & select path to `uiza_check.xml` file
4. Select **OK** & you're ready to go

To run checkstyle for project

1. Right click on project
2. Select **Analyze** > **Inspect Code**

## Reference

[API Reference](https://uizaio.github.io/uiza-android-player-sdk/)

## Supported devices

Support all devices which have ***Android 5.0 (API level 21) above.*** For a given use case, we aim to support UizaSDK on all Android devices that satisfy the minimum version requirement.

**Note:** Some Android emulators do not properly implement components of Android’s media stack, and as a result do not support UizaSDK. This is an issue with the emulator, not with UizaSDK. Android’s official emulator (“Virtual Devices” in Android Studio) supports UizaSDK provided the system image has an API level of at least 23. System images with earlier API levels do not support UizaSDK. The level of support provided by third party emulators varies. Issues running UizaSDK on third party emulators should be reported to the developer of the emulator rather than to the UizaSDK team. Where possible, we recommend testing media applications on physical devices rather than emulators.

## Error message

Check this [class](https://github.com/uizaio/uiza-android-sdk/blob/master/uzplayer/src/main/java/com/uiza/sdk/exceptions/ErrorConstant.java) you can know error code and error message when use UZPlayer.

## Support

If you've found an error in this sample, please file an [issue](broken://pages/-M3_4hr_f9wc2YPGPtTI)

Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub. Please feel free to contact me anytime: <developer@uiza.io> for more details.

Address: *33 Ubi Avenue 3 #08- 13, Vertex Tower B, Singapore 408868* Email: [*developer@uiza.io*](mailto:developer@uiza.io) Website: [*uiza.io*](https://uiza.io/)

## License

UizaSDK is released under the BSD license. See [LICENSE](broken://pages/-M3_4hrkOaxtHSZEy18S) for details.


# Android Broadcast SDK

[![](https://camo.githubusercontent.com/9fa439d7b71a2a098a51dbe19a5c5b45e7074766/68747470733a2f2f6a69747061636b2e696f2f762f75697a61696f2f75697a612d616e64726f69642d62726f6164636173742d73646b2e737667)](https://jitpack.io/#uizaio/uiza-android-broadcast-sdk)

[![Play Store](https://camo.githubusercontent.com/e506ee96bbe6031926c6daebfaa3a07aebf8239b/68747470733a2f2f7777772e676f6f676c652e636f6d2f70686f746f732f61626f75742f7374617469632f696d616765732f62616467655f676f6f676c655f706c61795f333664702e737667)](https://play.google.com/store/apps/details?id=io.uiza.samplelive)

Link to the Source code here: <https://github.com/uizaio/snake.sdk.android-broadcast>

## Welcome to UIZA Android BroadCast SDK

Simple Streaming at scale.

Uiza is the complete toolkit for building a powerful video streaming application with unlimited scalability. We design Uiza so simple that you only need a few lines of codes to start streaming, but sophisticated enough for you to build complex products on top of it.

Read [CHANGELOG here](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/CHANGELOG.md).

## Importing the Library

**Step 1. Add the `JitPack` repository to your `build.gradle` file**

```
    allprojects {
          repositories {
             maven { url 'https://jitpack.io' }
          }
    }
```

**Step 2. Add the dependency**

```
    dependencies {
        implementation 'com.github.uizaio:uiza-android-broadcast-sdk:1.x.x'
    }
```

Get latest release number [HERE](broken://pages/-M3_6LKWh2CULmgDc05U).

**Turn on Java 8 support**

If not enabled already, you need to turn on Java 8 support in all `build.gradle` files depending on ExoPlayer, by adding the following to the `android` section:

```
compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}
```

## Init SDK

. If you want show log, install any `Tree` instances you want in the `onCreate` of your application class

```
if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    }
```

## How to broadcast with UZBroadCast?:

It's very easy, plz follow these steps below to implement:

XML:

```
<com.uiza.sdk.view.UZBroadCastView
    android:id="@+id/uz_broadcast"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:runInBackground="true" # support camera2 only
    app:startCamera="FRONT"
    app:useCamera2="true" />
```

In class [`UZBroadCastActivity`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/samplebroadcast/src/main/java/com/uiza/samplebroadcast/UZBroadCastActivity.java):

```
    public class UZBroadCastActivity extends AppCompatActivity implements UZBroadCastListener {
        // ...
    }
```

In `onCreate()`:

```
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
    uzBroadCast = (UZBroadCastView) findViewById(R.id.uz_broadcast);
    uzBroadCast.setUZBroadcastListener(this);
```

In `onResume()`:

```
    @Override
    protected void onResume() {
        uzBroadCast.onResume();
        super.onResume();
    }
```

Start a Stream: see [`VideoAttributes`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/uzbroadcast/src/main/java/com/uiza/sdk/profile/VideoAttributes.java) and [`AudioAttributes`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/uzbroadcast/src/main/java/com/uiza/sdk/profile/AudioAttributes.java)

```
    uzBroadCast.setVideoAttributes(VideoAttributes videoAttrs);
    uzBroadCast.setAudioAttributes(AudioAttributes audioAttrs);
    if (uzBroadCast.prepareBroadCast()) {
        uzBroadCast.startBroadCast("broadCastUrl");
    }
```

or

```
    if (uzBroadCast.prepareBroadCast(AudioAttributes audioAttrs, VideoAttributes videoAttrs, boolean isLandscape)) {
        uzBroadCast.startBroadCast("broadCastUrl");
    }
```

Stop streaming (It auto saves mp4 file in your gallery if you start a broadcast with option save local file)

```
    uzBroadCast.stopBroadCast();
```

Switch camera:

```
    uzBroadCast.switchCamera();
```

In case `runInBackground = false` But you want to allows streaming again after back from background:

```
    uzBroadCast.setBackgroundAllowedDuration(YOUR_ALLOW_TIME); // default time is 2 minutes
```

This sample help you know how to use all Uiza SDK for livestream, please refer to [THIS](broken://pages/-M3_6LKhguttfwbnc7Mp)

## How to broadcast your screen?

See example in class [`UZDisplayActivity`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/samplebroadcast/src/main/java/com/uiza/samplebroadcast/UZDisplayActivity.java):

## For contributors

Uiza Checkstyle configuration is based on the Google coding conventions from Google Java Style that can be found at [here](https://google.github.io/styleguide/javaguide.html).

Your code must be followed the rules that defined in our [`uiza_style.xml` rules](https://github.com/uizaio/uiza-android-broadcast-sdk/tree/master/configs/codestyle/uiza_style.xml)

You can setting the rules after import project to Android Studio follow below steps:

1. **File** > **Settings** > **Editor** > **Code Style**
2. Right on the `Scheme`, select the setting icon > **Import Scheme** > **Intellij IDEA code style XML**
3. Select the `uiza_style.xml` file path
4. Click **Apply** > **OK**, then ready to go

For apply check style, install [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea), then

1. **File** > **Settings** > **Other Settings** > **Checkstyle**
2. In Configuration file, select the **`+`** icon
3. Check `Use local checkstyle file` & select path to `uiza_check.xml` file
4. Select **OK** & you're ready to go

To run checkstyle for project

1. Right click on project
2. Select **Analyze** > **Inspect Code**

## Reference

[API Reference](https://uizaio.github.io/uiza-android-broadcast-sdk/)

## Supported devices

Support all devices which have ***Android 5.0 (API level 21) above.*** For a given use case, we aim to support UizaSDK on all Android devices that satisfy the minimum version requirement.

**Note:** Some Android emulators do not properly implement components of Android’s media stack, and as a result do not support UizaSDK. This is an issue with the emulator, not with UizaSDK. Android’s official emulator (“Virtual Devices” in Android Studio) supports UizaSDK provided the system image has an API level of at least 23. System images with earlier API levels do not support UizaSDK. The level of support provided by third party emulators varies. Issues running UizaSDK on third party emulators should be reported to the developer of the emulator rather than to the UizaSDK team. Where possible, we recommend testing media applications on physical devices rather than emulators.

## Support

If you've found an error in this sample, please file an [issue](broken://pages/-M3_6LKMJ7ptC5yTfrFY)

Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub. Please feel free to contact me anytime: <developer@uiza.io> for more details.

Address: *33 Ubi Avenue 3 #08- 13, Vertex Tower B, Singapore 408868* Email: [*developer@uiza.io*](mailto:developer@uiza.io) Website: [*uiza.io*](https://uiza.io/)

## License

UizaSDK is released under the BSD license. See [LICENSE](broken://pages/-M3_6LKY5iUHzNst8gRl) for details.


# iOS SDK

## Welcome to Uiza iOS SDK

Uiza provides iOS SDKs for broadcasting and playback. The SDKs helps you set up your mobile application using Uiza's platform. You can start building your application on top and let Uiza handle the backbone of video and live streaming.

{% content-ref url="/pages/-M3dAL50BcNrgonhZ-Sz" %}
[iOS Player SDK](/2022-06-22/sdk-reference/ios-sdk/ios-player-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-M3dAJ1BXOA4b5dSA6KQ" %}
[iOS Broadcast SDK](/2022-06-22/sdk-reference/ios-sdk/ios-broadcast-sdk)
{% endcontent-ref %}


# iOS Player SDK

&#x20;[![Swift](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)

UZPlayer is a framework allows you to play video with fully customizable controls.

Link to the Source code here: <https://github.com/uizaio/snake.sdk.ios-player>

## Compatibility

UZPlayer requires Swift 4.2+ and iOS 9+

## Installation

### CocoaPods

To integrate UZPlayer into your Xcode project using [CocoaPods](http://cocoapods.org/), specify it in your `Podfile`:

Then run the following command:

## Usage

```
let playerViewController = UZPlayerViewController()		
playerViewController.player.controlView.theme = UZTheme1()
playerViewController.player.loadVideo(url: VIDEO_URL)
present(playerViewController, animated: true, completion: nil)
```

You might have to add these lines to `Info.plist` to disable App Transport Security (ATS) to be able to play video:

```
<key>NSAppTransportSecurity</key>  
<dict>  
  <key>NSAllowsArbitraryLoads</key><true/>  
</dict>
```

## Change Player Themes

```
let playerViewController = UZPlayerViewController()
playerViewController.player.controlView.theme = UZTheme1()
```

UizaPlayer currently has 7 built-in themes:

[UZTheme1](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme1.jpg)

[UZTheme2](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme2.jpg)

[UZTheme3](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme3.jpg)

[UZTheme4](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme4.jpg)

[UZTheme5](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme5.jpg)

[UZTheme6](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme6.jpg)

[UZTheme7](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme7.jpg)

## Create CustomTheme

You can create your own custom theme by creating a class inheriting from [UZPlayerTheme Protocol](https://uizaio.github.io/uiza-sdk-player-ios/Protocols/UZPlayerTheme.html) following this template: [UZCustomTheme](https://github.com/uizaio/uiza-sdk-player-ios/blob/master/themes/UZCustomTheme.swift)

You can also create your custom end screen by subclassing `UZEndscreenView`, then set an instance to `player.controlView.endscreenView`

```
self.playerViewController.player.controlView.endscreenView = MyCustomEndScreen()
```

## Create Player with Floating Mode

You can create player with "drag down to floating mode" like Facebook or Youtube, by subclassing [UZFloatingPlayerViewController](https://uizaio.github.io/uiza-sdk-player-ios/Classes/UZFloatingPlayerViewController.html), then you can add more UI for displaying video details and add them to `detailsContainerView`

Then present using this code:

```
UZFloatingPlayerViewController().present(with: videoItem, playlist: playlist)
```

See [Example](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/UZPlayerExample)

For API details, check [API Document](https://uizaio.github.io/uiza-ios-player-sdk/)

## Google ChromeCast supports

If developing using Xcode 10 and targeting iOS devices running iOS 12 or higher, the "Access WiFi Information" capability is required in order to discover and connect to Cast devices [![](https://camo.githubusercontent.com/2afb576154d43dfaa77113c9c6ed95a82a4aeea7/68747470733a2f2f646576656c6f706572732e676f6f676c652e636f6d2f636173742f696d616765732f78636f64655f776966695f6361706162696c6974795f6572726f722e706e67)](https://camo.githubusercontent.com/2afb576154d43dfaa77113c9c6ed95a82a4aeea7/68747470733a2f2f646576656c6f706572732e676f6f676c652e636f6d2f636173742f696d616765732f78636f64655f776966695f6361706162696c6974795f6572726f722e706e67)

## Support

<namnh@uiza.io>

## License

UZPlayer is released under the BSD license. See [LICENSE](https://github.com/uizaio/uiza-sdk-player-ios/blob/master/LICENSE) for details.


# iOS Broadcast SDK

[![Swift](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)

UZBroadcast is a framework helps you to broadcast livestream

Link to the Source code here: <https://github.com/uizaio/snake.sdk.ios-broadcast>

## Compatibility

UZBroadcast requires Swift 4.2+ and iOS 9+

## Installation

### CocoaPods

To integrate UZBroadcast into your Xcode project using [CocoaPods](http://cocoapods.org/), specify it in your `Podfile`:

Then run the following command:

## Livestream

```
let broadcaster = UZBroadcastViewController()
let config = UZBroadcastConfig(cameraPosition: .front, videoResolution: ._720, videoBitrate: ._3000, videoFPS: ._30, audioBitrate: ._128Kbps, audioSampleRate: ._44_1khz, adaptiveBitrate: true)
broadcaster.prepareForBroadcast(withConfig: config)
//...
broadcaster.startBroadcast(broadcastURL: BROADCAST_URL)
present(broadcaster, animated: true, completion: nil)
```

## Screen broadcast

```
let broadcaster = UZScreenBroadcast.shared
let config = UZBroadcastConfig(cameraPosition: .front, videoResolution: ._720, videoBitrate: ._3000, videoFPS: ._30, audioBitrate: ._128Kbps, audioSampleRate: ._44_1khz, adaptiveBitrate: true)
broadcaster.prepareForBroadcast(withConfig: config)s
broadcaster.isMicrophoneEnabled = true
//broadcaster.isCameraEnabled = true
broadcaster.startBroadcast(broadcastURL: BROADCAST_URL)
```

Remember to add these usage description keys into `Info.plist` file:

```
<key>NSCameraUsageDescription</key>
<string>App needs access to camera for broadcasting</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs access to microphone for broadcasting</string>
```

## Reference

[API Reference](https://uizaio.github.io/uiza-ios-broadcast-sdk/)

## Support

<namnh@uiza.io>

## License

UZBroadcast is released under the BSD license. See [LICENSE](https://github.com/uizaio/uiza-sdk-broadcast-ios/blob/master/LICENSE) for details.


# Web Player SDK

## How to use Uiza's webSDK

1. Include css, js into html:

```
<!-- 1. Include UIZA library. -->
<link href='https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.css' rel='stylesheet' crossorigin='anonymous'> <!-- route to uiza.css -->
<script src='https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.min.js' crossorigin='anonymous'></script> <!-- route to uiza.min.js -->
```

&#x20;2\. The video player will prepend the player into this \<div> tag:

```
<video id='playerUiza' crossorigin playsinline autoplay muted></video>
```

&#x20;3\. This code creates an UIZA player:

```
<script>
  var videoSrc = "UIZA_PLAY_BACK_LINK"; // This may be PLAY_BACK_LINK (hls or dash)
  window.UZPlayer = new Uiza(document.getElementById("playerUiza"), {
    src: videoSrc,
  });
</script> 
```

4\. Full code example:

```
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <style>
      body {
        margin: 0;
        padding: 0;
      }
    </style>
    <link
      href="https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.css"
      rel="stylesheet"
      crossorigin="anonymous"
    />
    <script
      src="https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.min.js"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <video id="playerUiza" crossorigin playsinline autoplay muted></video>
    <script>
      var videoSrc = "UIZA_PLAY_BACK_LINK"; // This may be PLAY_BACK_LINK (hls or dash)
      window.UZPlayer = new Uiza(document.getElementById("playerUiza"), {
        src: videoSrc,
      });
    </script>
  </body>
</html>
```


# Flutter SDK

{% embed url="<https://github.com/uizaio/snake.sdk.flutter-player>" %}


# Release Notes

Release Notes is our update that we share with you our new features, improvements or why we change the API to serve you better so you can easily stay up to date on what’s new.

## 2022-06-22

### Uiza supports multiple ingest points

From this release, Uiza supports the broadcasters in choosing the nearly region from their location for sending the video signal (OBS, Uiza's SDK,...). So, the live entity's **ingest** will be changed to an array for including multiple ingest points. For more information about the supported ingestion, please contact us 🤗.

{% hint style="warning" %}
*Note that all the current ingest points are returning as an object, so before using this version, please help us to integrate with the changes, so your application can work perfectly without any issues.*
{% endhint %}

#### *Changes:*

<table><thead><tr><th>Live entity object</th><th>Before (object)</th><th>After (array)</th></tr></thead><tbody><tr><td><strong>ingest</strong></td><td><pre><code>{
  "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
  "key": "live_TB62vHgxSY"
}
</code></pre></td><td><pre><code>[
  {
    "url": "rtmp://f45dd07a0e-in.uiza.io/transcode",
    "key": "live_TB62vHgxSY"
  }, {
    "url": "rtmp://f45dd07a0e-sg.uiza.io/transcode",
    "key": "live_TB62vHgxSY"
  }
]
</code></pre></td></tr></tbody></table>

## 2022-06-06

### Auto load-balancing&#x20;

We now change the ingest point to use the 8099 port, which supports auto-choose a server to serve your stream with the best performance.

{% hint style="warning" %}
*Note that all the current ingest points have no port on the ingest URL (use port 1935 as default), so before we upgrade the system, please help us to integrate with the changes, so your application can work perfectly without any issues.*
{% endhint %}

#### *Integration: there are 2 options to do 💪*

1\. Uiza sends the new ingest info to the webhook endpoint: we will send the data to your webhook endpoint - send all the new ingest to the live\_entities.updated event. We can also provide the API to trigger it manually for your testing.

*Sample webhook data:*

<table><thead><tr><th>Event type</th><th>Data (ingest.url)</th></tr></thead><tbody><tr><td>live_entities.updated</td><td><pre><code>{
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Demo app 1",
    "description": "Demo application for documentation",
    "dvr": true,
    "encoding_template": "hd",
    "ingest": {
      "url": "rtmp://g-rtmp.gcpsg.uiza.io/live:8099",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "region": "in-mumbai-1",
    "relay": [],
    "status": "ready",
    "created_at": "2020-03-10T03:20:37.202Z",
    "updated_at": "2020-03-10T03:20:37.202Z"
  }
</code></pre></td></tr><tr><td></td><td></td></tr><tr><td></td><td></td></tr></tbody></table>

2\. The customer update all the ingest endpoint with port 8099, for example, `rtmp://ingest.uiza.io` -> `rtmp://ingest.uiza.io:8099`. Please contact us for more information.

*Live entity data changes:*

| Live entity object | Before                             | After                                         |
| ------------------ | ---------------------------------- | --------------------------------------------- |
| **ingest.url**     | `rtmp://g-rtmp.gcpsg.uiza.io/live` | `rtmp://g-rtmp.gcpsg.uiza.io/live`**`:8099`** |

## 2020-07-01

### Rewatch the last 30 minutes of a live stream!

We have built a Timeshift feature for maximum viewer experience. When you use an Uiza Player SDK, your viewer can switch between watching a live video and rewinding upto 30minutes with our Timeshift feature.&#x20;

### Reduced Latency

We have reduced the HLS Playback latency by up to 50%!

### Webhooks: performance and scalability improvements

We know that webhook is one of the most important features for the integration with Uiza APIs. In this release, by the focus on improving the throughput of our webhooks service, Uiza provides you a faster and more reliable webhooks ever.&#x20;

When your server responds to Uiza the bad status, an event now will be retried to send to your webhook endpoint every hour up to a day, instead of retry many times in minutes, which is too short for any action if your server has trouble.

### Uiza node-kafka-client

There are several problems to solve while enhancing the performance of our services. In the case of message broker enhancement, we decided to release the library of Kafka client run on NodeJS on Github [here](https://github.com/uizaio/node-kafka-client). Which is a wrapper library of [node-rdkafka](https://github.com/Blizzard/node-rdkafka) with extended features, easy to control the workflow, please feel free to use or give us feedback to improve.

## 2020-06-10

### More regions for better performance and more global reach

We have added following regions for your users to use as ingestion points:

{% hint style="success" %}
`us-oregon-1` (Oregon - USA)

`aus-sydney-1` (Sydney - Australia)

`ie-dublin-1` (Dublin - Ireland)
{% endhint %}

## 2020-05-28

### Get notified when we cannot allocate resources for your entity

We try our best to power your broadcasting session by allocating the dedicated resource, returning an RTMP server to ingest and delivering your stream in seconds. Furthermore, we know your time is wasted when you create a [live entity](https://docs.uiza.io/api-reference/live-entities) and the status `init` doesn't change.

So in this release, we added a new live entity status: `resource_allocate_fail` . When the allocating resources for an entity passes a threshold of time, we'll set the entity's status to `resource_allocate_fail` and delete it automatically after 15 minutes.&#x20;

In case the entity status becomes `resource_allocate_fail`,  ~~disaster 🌋🌊 may occur~~ it will not be counted on your usage data. You can create a new live entity afterwards.

### Suspended accounts <a href="#how-to-detect-suspended-account" id="how-to-detect-suspended-account"></a>

Uiza's invoice day is 3rd day of the month, we process to charge your invoice until the 16th day of the month. If the next day we still not charge your invoice successfully, your account will be set to suspend and we prevent your interaction with our core services via API calls.

### Support for MPEG-DASH Playback <a href="#how-to-detect-suspended-account" id="how-to-detect-suspended-account"></a>

Read more about MPEG-DASH [here](https://www.encoding.com/mpeg-dash/).

## 2020-05-07

### New region in Vietnam region is finally available!&#x20;

Provide your users with improved connectivity through our new region. The new region is:`vn-saigon-1`&#x20;

### Added PATCH methods to modify objects

Instead of replacing your resource for a simple modification, you can now update the resource using the PATCH method. We will deprecate the PUT methods in the future.

## 2020-04-21

### Track your encoding minutes!

You can now see how many minutes you have encoded using Uiza. For more details on how we calculate your encoding minutes, go to this [link](https://help.uiza.io/data-usage)

![Your total encoding minutes can be seen in the billing page](/files/-M5yoK-YlLDnFwWtBE2R)

### Uiza's Player for better viewer experience

Integrate Uiza's player into your website for optimal playback. Our player supports ABR, playback speed, and playback in a smaller window.

![](/files/-M5ytZ6u413oYyEG-ovT)

## 2020-03-26

### Behold! DVR <a href="#behold-emojis" id="behold-emojis"></a>

You can now rewatch your live stream with DVR. We record your live stream and convert it to a [video entity](https://docs.uiza.io/api-reference/video-entities), and your users can watch your live stream recording if they missed it.

![The DVR is created instantly while you stream](/files/-M5yYVqbDtAjjEag7OPN)

### Broadcast your moment to multiple destinations simultaneously&#x20;

Using our `Relay Destination` feature, you can broadcast your live stream to multiple social networks (Facebook, Youtube, Twitch, etc) or RTMP endpoint simultaneously. Update your fans on all platforms and let us handle the signal!

![Broadcasting the signal to Youtube](/files/-M5yYnxbwfUGIQWOX8ws)

### Give your end user the best experience with ABR

You can create up to 6 video profile outputs (Business Tier) with your stream, to cater towards different networks and mobile devices. Your viewer can choose different resolutions, or our Uiza player will recognize the most fitting profile depending on your user's bandwidth, and adjust their bitrate accordingly.

![Create your Preset and add your profiles](/files/-M5yYwcOIrWS-3DWGeb_)

![Choose your Video Resolution on playback](/files/-M5yZ-CNyeAZUeZ93Ig3)


# API Changelog

API changelog describes to you what we change on the newest API dated version we've made so you can easily stay up to date on what’s new.

## 2020-07-01

**What’s new**

* Support enable/disable of live relay destination and added the identity attributes to the relay object: id, status, created\_at , and updated\_at.
* Faster and more reliable Webhook service.
* Separate Delivery overusage to different regions with distinct costs. [Read more here.](https://help.uiza.io/data-usage)
* Adjust the overuse invoice template to include items for delivery regions, unit prices, and exceeded values.
* Support for enabling/disabling CCU display on Uiza’s WebSDK. [Read more here](https://github.com/uizaio/uiza-javascript-sdk-player#customizing-the-ui-button).

**Changes**

* Time interval to retry Webhook changed from multiple times per minute to an hourly basis for a duration of 24 hours.
* Update subscription plans according to the new pricing model ([Pricing](https://uiza.io/pricing)).

**Fixes**

* Fixed issue with user suspension in case of failed payment when changing the current subscription

## 2020-05-28

**What's new**

* User suspension - User’s who missed payment after the invoice period will be suspended.&#x20;
* New status when creating live entity: `resource_allocation_fail` - when the entity takes too long to look for resources. User’s will receive a message and will be prompted to create a new entity.
* SDK player updates
  * Live button to return to live moment
  * Analytics and CCU displayed on Uiza’s players
* Support for [MPEG-DASH](https://www.encoding.com/mpeg-dash/) playback .

**Fixes**

* Fixed bug when deleting a live entity assigned to a preset.
* Fixed minor bug with wrong message response when creating a webhook endpoint but missing url parameter.
* Fixed bug returning inconsistent playback.url of live entity in Live API and Event API.
* Fixed confusing error message when creating a [live entity](https://docs.uiza.io/api-reference/live-entities) with missing parameters.
* Fixed confusing error message when creating a [webhook endpoint](https://docs.uiza.io/api-reference/webhook_endpoints) with missing parameters.
* Fixed bug allowing Team & Business tier users to profiles to Uiza presets.
* Fixed bug with randomly returned error type when client calls APIs.
* Fixed issue with retry request live resource.

## 2020-05-07

### What's new

* Added new API: [Update a live entity](https://docs.uiza.io/v/2020-05-07/api-reference/live-entities/update-a-live-entity) using PATCH method&#x20;
* Added new API: [Update a webhook endpoint](https://docs.uiza.io/v/2020-05-07/api-reference/webhook_endpoints/update-webhook-endpoint) using PATCH method&#x20;

### Changed

* Deprecated [Update a live entity](https://docs.uiza.io/v/2020-05-07/api-reference/live-entities/deprecated-update-a-live-entityhttps://docs.uiza.io/v/2020-05-07/api-reference/live-entities/deprecated-update-a-live-entity) API using PUT method&#x20;
* Deprecated [Update a webhook endpoint](https://docs.uiza.io/v/2020-05-07/api-reference/webhook_endpoints/deprecated-update-webhook-endpoint) API using PUT method&#x20;

### Fixed

* Inconsistent entity status on events when update entity status to ready&#x20;
* Fixed bug when calling list events API returns `internal-error`&#x20;

## 2020-04-21

### What's new

* Expose new API to reset Ingest Key of a Live Entity.
* Expose new API to get Invoice Detail.
* Support clearing Live Entity's relay setting by updating relay parameter as empty
* Support exporting Invoice to PDF.
* Support deleting source files of video entity.

### Changes

* Replace field `type` by `input_type` in  `video_entity` event object.

### Fixes

* Fixed bug incorrect error response when updating invalid video preset/profile.
* Fixed bug where user can login without verifying email address.
* Fixed bug displaying empty `live_entity_id` in the `live_session` event object.

## 2020-03-26

### What's new

* Added new event `video_entities.created` in [Event Types](https://docs.uiza.io/api-reference/events/event-types).
* Added `video_entity_id` attribute to [Live Session](https://docs.uiza.io/api-reference/live-sessions) to link the live records with its video entity.
* Support DVR option in [Live Entity](https://docs.uiza.io/api-reference/live-entities). Included two new APIs to enable and disable DVR.
* Support login with Google.
* Support multiple destination broadcast and added `relay` attribute to [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Added `encode` attribute to [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Introduced [Video Profile](https://docs.uiza.io/api-reference/video-profiles) & [Video Preset](https://docs.uiza.io/api-reference/video-presets) to support live with `encode` option.
* Added new attribute `preset` in  [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Support filtering [Live Sessions](https://docs.uiza.io/api-reference/live-sessions) by DVR attribute and added new attribute `preset` in Live Session details
* Support filter live video by `live_entity_id`.
* Increase resource allocation speed up to 500 live entities per 5 seconds.
* Support categorize Ulas by `encode` feature.

### Changes

* Live Session attribute `entity_id` changed to `live_entity_id`  to differentiate with `video_entity_id`.
* Following [Google API Design guideline](https://cloud.google.com/apis/design/standard_methods#delete), all `DELETE` APIs should return empty body.
* Remove `Reset ingest key` API in version 2020-01-10. We no longer support resetting ingest key, because conflicts with the end of signal occurs when an user resets the ingest key while streaming. We are working on this problem.
* Remove emit event log form. All event logs related to entity should be executed in Live Entity server.
* Update submodule by removing `googleapis`. This update shortens the times of build time from 10 minutes to about 2 minutes.
* Support allocating request based on available vCPUs and Memory
* Enhance the performance of allocating by moving DNS logic part to be a DNS Service.

### Fixes

* Webhook endpoints can now send to Slack without error and return the valid error message.
* Delete DNS when deleting a live entity.
* Fixed bug where user ID is undefined when creating a live entity.
* Fixed inconsistency of API response between live entity API and webhook endpoints API.
* Fixed bug where updating the video entity returns bad request.
* Fixed inconsistency in boolean value in events API.
* Fixing crashing issue due to not handling case of Axios - fail on getting a response from Prometheus.
* Handle multi node down trigger fail over.
* Fixed bug where retrieving live entities causes long time to allocate resource.
* Cannot get Ulas disk metrics during scaling action.


# Hola! 👋

### **Welcome to Uiza, the video streaming as code!**&#x20;

We aim to provide developers with an end-to-end video streaming solution that offers simple integration and stable performance at scale. At the very beginning of our roadmap, we tackle the problem that is considered the most severe, ***video and live stream delivery***. The proximity between the infrastructure and the streamer/viewer is the key factor that influence the quality of the video streams. Setting up and managing a wide network of infrastructures that penetrates locally to reach out as closely as possible to the streamers and viewers in various cities are tough. The first version of our brand-new platform is created to solve this problem.

{% hint style="success" %}
Our **key differentiation** is that we are developing a diversified network of infrastructures that does not only rely on public cloud like Amazon Web Services, Google Cloud Platform, or Digital Ocean, but also a wide range of local infrastructures those are rooted in lower-tier cities like *Bengaluru, Kolkata, Chennai*... This means your viewers will most likely *watch the videos being streamed from the infrastructure located in the same city of theirs*, which improves the quality and scalability of the video streams significantly.
{% endhint %}

![](/files/-Lvy1ZLdD3Cbvz7i3WN8)


# Introduction

Uiza helps you broadcast your live stream to your audiences with literally a few lines of codes, or at least we are trying hard to get there:muscle::muscle::muscle:. But before experiencing the magic, let's make sure that you understand the terms correctly.

* ***`live_entity`***: Live entities are basically live events, with or without a live feed. A live entity contains the information required for Uiza to allocate resources to power the live event, and direct your live feed toward these resources for ingestion and broadcasting.
* ***`live_session`***: The duration of one session is counted from the moment Uiza receives the first signal until the last of that live feed. Therefore, one entity could contain multiple sessions. The durations of these sessions are calculated as *Live Minutes* in your billing.
* ***Streamer***: Streamers record the live events and are the source of the live  signals that Uiza receives.
* ***Viewer***: Viewers are the users who watch the live stream on their devices. They are the destination of the delivery of the live stream.

Now that we are on the same page, let's navigate to the **Quickstart** to start *live streaming*.

{% content-ref url="/pages/-LwqhgC-FZjkAy13MWg8" %}
[Authentication](/2022-06-06/getting-started/authentication)
{% endcontent-ref %}


# Authentication

Uiza APIs apply the [HTTP Basic Authentication Protocol](https://swagger.io/docs/specification/2-0/authentication/basic-authentication/), where the client sends HTTP requests with the API key in the Authorization header.

Once you have signed up, you can create applications (maximum of 2 applications) with an API Key assigned to each application.&#x20;

You can manage your applications and API Keys in the [Uiza Dashboard](https://app.uiza.io/).

All API requests to Uiza *must go* over HTTPS and include a valid API Key.


# Errors

This page describes the error statuses returned by the Uiza APIs

Whether an API request to Uiza is successful or not is indicated by conventional *HTTP* codes. In general, Uiza returns responses with equivalent *status codes* which are listed below.

> **200 - OK**
>
> The request is successful.

> **400 - Bad request**
>
> The request is inadequate. This is usually caused by missing required parameters or malformed syntax.

> **403 - Forbidden**
>
> The API key doesn't have permissions to perform the request.

> **404 - Not Found**
>
> The requested resource does not exist.

> **409 - Conflict**
>
> The request conflicts with the current state of the server. For example updating an immutable resource already present on the server.

> **500, 502, 503, 504 - Internal Server Error**
>
> Something went wrong on Uiza's end

> Errors are returned with format containing a `message` and an `error_type` to help you pinpoint what went wrong. While you can find all the possible error messages in our API Reference, these errors are categorized by the following `error_types`:

|       Error Types       |                           Definitions                           |
| :---------------------: | :-------------------------------------------------------------: |
|  `api_connection_error` |       Errors that occurred during the HTTP communication.       |
|       `api_error`       |            Errors occurred internally with Uiza API.            |
|  `authentication_error` |    The keys supplied to Uiza were either missing or invalid.    |
| `invalid_request_error` | The parameters supplied to Uiza were either missing or invalid. |
|    `rate_limit_error`   |         Too many requests were sent to Uiza too quickly.        |
|      `video_error`      |     There is something wrong with your video or live stream.    |


# Quick Starts

Welcome to the most exciting part of Uiza Documentation. Now, we will accompany you in streaming your first video, and live broadcasting your very first session with Uiza APIs. :partying\_face::partying\_face::partying\_face:

{% content-ref url="/pages/-LvsA4FyDRUwKP4Z7tjP" %}
[Live Streaming](/2022-06-06/getting-started/quick-starts/quickstart)
{% endcontent-ref %}

{% content-ref url="/pages/-Lwm3LFbLppQcOYeL\_pt" %}
[Video Streaming](/2022-06-06/getting-started/quick-starts/video-streaming)
{% endcontent-ref %}


# Live Streaming

Our *REST APIs* use standard *HTTP* response codes, authentication, and verbs, and return *JSON-encoded responses*. Using these APIs, you will be able to start a live event and stream the content to our network, which will deliver that content to your audiences. Once a live entity is created, Uiza allocates dedicated resources and return an *RTMP* server to ingest and deliver your stream. The overall framework is articulated in the diagram below.

![](/files/-LxVHSp0O-p10YRdBAom)

## **Step 1: Create a live entity**

To start streaming, you need a [`live_entity`](https://docs.uiza.io/api-reference/live-entities) to be created with resources allocated, ready to broadcast the live signal. You could create a live entity by using ***Create A Live Entity*** ***API***.&#x20;

## /v1/live\_entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/live_entities`

#### Request Body

| Name        | Type    | Description                                                                                                                                                                                          |
| ----------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | string  | The name of your live entity.                                                                                                                                                                        |
| region      | string  | Choose the region closest to the location of your streamer.                                                                                                                                          |
| description | string  | The description of your live entity (maximum is 1000 characters)                                                                                                                                     |
| dvr         | boolean | Indicates whether Digital Video Record (DVR) is enabled for the `live_entity`. Set as `true` to enable and as `false` to disable. The default value is false.                                        |
| encode      | boolean | Indicates whether encoding mode is enabled for the `live_entity`. Set as `true` to enable and as `false` to disable. The default value is false, when the encode is true, it required a `preset_id`. |
| preset\_id  | string  | The identifier of the `video_preset` to be applied when encoding your signal.                                                                                                                        |
| relay       | array   | A list of ingest servers to be relayed. Contains `url` and `key` and `name` (optional) in each ingest server.                                                                                        |

{% tabs %}
{% tab title="200 " %}
{% tabs %}
{% tab title=" live\_entities without encoding" %}

```

  "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
  "name": "Test event without encoding",
  "description": "Event for Test",
  "region": "in-bangalore-1",
  "status": "init",
  "dvr": false,
  "encode": false,
  "ingest": null,
  "playback": null,
  "relay": [
    {
      "url": "rtmp://youtu.be/live",
      "key": "Abco1",
      "name": "Youtube 1"
    }
  ],
  "preset": null,
  "created_at": "2020-03-23T07:22:34Z",
  "updated_at": "2020-03-23T07:22:34Z"
}
```

{% endtab %}

{% tab title=" live\_entities with encoding" %}

```
{
    "id": "b7f02d48-d0ec-4c34-86d1-247a38eda4e1",
    "name": "Test event with encoding",
    "description": "Event for Test",
    "ingest": null,
    "playback": null,
    "relay": [
        {
            "url": "rtmp://youtu.be/live",
            "key": "Abco1",
            "name": "Youtube 1"
        }
    ],
    "region": "in-bangalore-1",
    "status": "init",
    "dvr": false,
    "encode": true,
    "preset": {
        "id": "9432fa62-5988-11ea-883b-028fc5698662",
        "name": "Uiza LIVE 720p",
        "description": "",
        "is_default": true,
        "profiles": [
            {
                "id": "85844e8b-6281-11ea-883b-028fc5698662",
                "name": "720p H264 30fps Normal Latency",
                "segment_duration": 4,
                "orientation": "landscape",
                "video_profile": {
                    "video_resolution": "720",
                    "video_codec": "H264",
                    "video_bitrate": "2000K",
                    "video_frame_rate": "30"
                },
                "audio_profile": {
                    "audio_channel": "2",
                    "audio_codec": "AAC",
                    "audio_bitrate": "128K",
                    "audio_frame_rate": "1"
                }
            }
        ],
        "created_at": "2020-02-27T17:42:52Z",
        "updated_at": "2020-02-29T16:47:34Z"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```go
curl -X POST https://api.uiza.sh/v1/live_entities \
-H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' \
-d '{"name": "Test Event", "region": "in-bangalore-1", "description": "Test 1"}'
```

{% endcode %}

{% hint style="info" %}
Please pay attention that you entered a supported region, else the API will return an error message. Defining correct region helps Uiza allocates the resource that is closest to the streamer location. This will minimize the risks of network issues and reduce the impact on your business. While we are adding more and more regions to Uiza Network, please check the current available regions below:

`in-bangalore-1` (Bangalore - India)

`in-mumbai-1` (Mumbai - India)

`sg-singapore-1`(Singapore)

`vn-saigon-1` (Vietnam)
{% endhint %}

## **Step 2: Retrieve a live entity**

You will need the `ingest.key` and `ingest.url` to configure your broadcasting software. These 2 attributes could be retrieved by using the `id` you get in the response in ***Step 1*** for the ***Retrieve an entity*** API.

{% hint style="warning" %}
It is important that the value of the **`status`** you get from the response is **`ready`**, meaning that resources have been allocated and ready to ingest and broadcast your live feed. If the **`status`** of your entity is **`init`**, meaning that Uiza is still allocating resources for your entity and your live signal will not be able to be ingested and broadcasted during this process. Please, be patient and keep requesting for the entity's information until you get the **`ready`** status. This process may take up to 1 minute.
{% endhint %}

## /v1/live\_entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.sh/v1/live_entities/:id`

#### Path Parameters

| Name | Type   | Description                                                        |
| ---- | ------ | ------------------------------------------------------------------ |
| id   | string | The unique identifier of a live entity to be retrieved information |

{% tabs %}
{% tab title="200 " %}

```
{
 "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
 "name": "Test Event",
 "description": "Test 1",
 "ingest": {
   "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
   "key": "live_TB62vHgxSY"
 },
 "playback": {
   "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8"
 },
 "region": "in-bangalore-1",
 "status": "ready",
 "dvr": false,
 "broadcast": "offline",
 "created_at": "2019-12-11T02:47:04Z",
 "updated_at": "2019-12-16T02:53:30Z"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```go
curl -X GET https://api.uiza.sh/v1/live_entities/2b970a39-874a-4d2a-be8a-fd445646d74c \
-H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
```

{% endcode %}

{% hint style="info" %}
You could also set up a [webhook](https://docs.uiza.io/api-reference/webhook_endpoints) to be notified automatically when your `live_entity` is ready.
{% endhint %}

## **Step 3: Configure your broadcasting software and start broadcasting**

Most available broadcasting software uses [RTMP protocol](https://en.wikipedia.org/wiki/Real-Time_Messaging_Protocol) which requires a *server's URL* and a *Stream Key* to direct the live signal to the ingest servers. Use the `ingest.url` and `ingest.key` obtained at **Step 2** to configure your broadcasting software in their Settings. The following are the 2 most popular broadcasting software that we strongly recommend.

{% hint style="info" %}
**OBS Studio** (Available for Mac, Windows, and Linu&#x78;**)** - Get it [here](https://obsproject.com/).&#x20;
{% endhint %}

![](/files/-LvsDOpl_ledM1Slwgj7)

{% hint style="info" %}
**Streamlabs (**&#x54;he best live streaming app for iPhone & Androi&#x64;**)** - Get it [here](https://streamlabs.com/mobile-app).
{% endhint %}

![](/files/-LvsEXnmQmcXq5XxHRPt)

Once you have configured the `ingest.url` and `ingest.key`, you could start streaming right away.

## **Step 4: Configure the playback link to your player and start watching your live stream!**

The playback links (`hls` for HLS streaming and `mpd` for MPEG-dash streaming) of your live entity is the value of `playback` returned in ***Step 2*****.** With the HLS link obtained, you could play your live stream by these methods:&#x20;

1. Configure the HLS link to Player SDK.
2. Paste the HLS link to Safari and play directly with Apple's native player.
3. Install the HLS extension and play it on Google Chrome browser.

The `mpd` video format could be played natively by  [Microsoft Edge](https://www.microsoftedgeinsider.com/en-us/).

By following these *4 steps*, you will be able to live stream your event using Uiza:pray:. We understand that this beta version of ours requires quite some amount of manual involvement, but we are working hard to deliver a more delightful experience with more APIs and automation. If you are ready to live-stream your first event, let's move on to the ***API Reference***.


# Video Streaming

**Streaming videos** with Uiza is pretty straightforward where the whole process could be summarized in 4 simple steps:&#x20;

1. You give us the video,
2. You allow us to publish the video,
3. We let you know when your video is published, and
4. You tell your player to start streaming :nerd:&#x20;

![](/files/-LxQZO0_8W966JjHyU7S)

## Step 1: Create a video entity

You can create a [`video_entity`](https://docs.uiza.io/api-reference/video-entities) using HTTP/HTTPS URL links to your original video files. In case the video file is located in your PC, you can upload the video via the [Uiza Developer Console](https://app.uiza.io/) by following these steps:

1. Login to Uiza Developer Console
2. **Start** your application, then go to **Upload Video** page
3. Browse to your local video file or enter multiple HTTP/HTTPS URLs
4. Click **Proceed** to start uploading your selected video files

![Upload Video Selection Page](/files/-M4TeyQWizdpvWNf-YHt)

Successfully uploaded `video_entities` will be ingested and listed out in the Developer Console. To transcode the video, click on "Publish" or move to step 2.

![Upload Video Result Page](/files/-M4ThijWbsfQ-GAmQAf_)

Go to **Entities** page and select created video entity for checking `id` and other details.

## Step 2: Publish the video entity

The renditions of your video, as the output of transcoding, will be distributed to Uiza's [Content Delivery Network](https://en.wikipedia.org/wiki/Content_delivery_network) (CDN) through which it is delivered to viewers.&#x20;

To let Uiza know that you are ready to publish your video to your viewers, you can use [Uiza Developer Console](https://app.uiza.io/) or send a request to ***Publish a video entity*** API.

## /v1/video\_entities/:id/publish

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/video_entities/:id/publish`

#### Path Parameters

| Name | Type   | Description                                         |
| ---- | ------ | --------------------------------------------------- |
| id   | string | The identifier of the video entity to be published. |

{% tabs %}
{% tab title="200 " %}

```
{
 "message": "Video entity started to publish successfully"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.sh/v1/video_entities/f42b4ac3-869e-4010-8e21-042e40be7655/publish 
     -H 'Accept: */*' 
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
     -H 'Cache-Control: no-cache' 
     -H 'Connection: keep-alive'
```

{% endcode %}

## Step 3: Retrieve the video entity's information

The process of transferring the renditions of your video to Uiza's CDN takes time. You player can only start playing the video after it has been successfully published. To keep track of this process, retrieve the video entity's information. The `publish_to_cdn` argument indicates the publishing status of your video entity. If the value is `success`, you are good to go.

## /v1/video\_entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.sh/v1/video_entities/:id`

#### Path Parameters

| Name | Type   | Description                                         |
| ---- | ------ | --------------------------------------------------- |
| id   | string | The identifier of the video entity to be retrieved. |

{% tabs %}
{% tab title="200 " %}
{% tabs %}
{% tab title="The Video Entity has not been published" %}

```
{
 "id": "f42b4ac3-869e-4010-8e21-042e40be7655",
 "name": "Sample Demo-Video",
 "description": "Lorem ipsum dolor sit amet, vis odio oratio scripserit ut",
 "short_description": "Duo ad graeci principes, legimus mnesarchum scribentur ut pro",
 "view": 1000,
 "poster": "Lorem ipsum dolor",
 "thumbnail": "Lorem ipsum dolor",
 "type": "VOD",
 "duration": 11213,
 "publish_to_cdn": "queue",
 "created_at": "2019-12-11T02:47:04Z",
 "updated_at": "2019-12-11T02:47:04Z"
}
```

{% endtab %}

{% tab title="The Video Entity is published successfully" %}

```
{
    "id": "77123e09-a30b-456b-b954-c16fe81f97f7",
    "name": "test 998",
    "description": "Entity for Test",
    "short_description": "",
    "view": 0,
    "poster": "",
    "thumbnail": "",
    "input_type": "UNKNOWNVODINPUTTYPE",
    "duration": 269.588,
    "publish_to_cdn": "success",
    "playback": {
        "hls": "https://dvr-playback-secure.uizadev.io/05bb5869-e134-4e9e-a2d2-de5c77dd182f/77123e09-a30b-456b-b954-c16fe81f97f7/master.m3u8",
        "hls_ts": "",
        "mpd": ""
    },
    "created_at": "2020-02-12T12:28:00Z",
    "updated_at": "2020-02-12T12:32:30Z"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X GET https://api.uiza.sh/v1/live_entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
     -H 'Accept: */*' 
     -H 'Accept-Encoding: gzip, deflate' 
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64' 
     -H 'Cache-Control: no-cache' 
     -H 'Connection: keep-alive'
```

{% endcode %}

## Step 4: **Configure the playback link to your player and start streaming!**

Three playback links are returned in the response of Step 3. These playback links represent the 3 streaming protocols that Uiza currently supports:

* `hls` for HLS fMP4 streaming,
* `hls_ts` for HLS ts streaming, and
* `mpd` for MPEG-dash streaming.

Configure these playback links to your player will enable your player to get the video chunks from Uiza's CDN, decode and display them to your viewers. And that is How to stream your first video with Uiza in 4 simple steps. :wink:&#x20;


# Pagination

Uiza's List method is using page-based pagination, this is one of the simplest forms of paging. Initially, only a certain number of results will be returned at a time. The default is 50.

#### Arguments

> **`limit`** *number*
>
> The maximum number of objects to be returned per call, between 1 and 50. The default `limit` is 50.

> **`page`** *number*
>
> Indicates the page number, the page being the one requested. By default, this query parameter is equal to 1.

{% code title="Sample Response" %}

```
{
 "data": {
    "items": [
      {
        "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
        "name": "Demo app 1",
        "description": "Demo application for documentation",
        "dvr": true,
        "encoding_template": "none",
        "ingest": {
          "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
          "key": "live_TB62vHgxSY"
        },
        "playback": {
          "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
          "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
        },
        "region": "in-mumbai-1",
        "relay": [
          {
            "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
            "name": "Replay name3333",
            "url": "rtmp://a.rtmp.youtube.com/live2",
            "key": "0df3-76bz-6t4r-1by5xxxxxx",
            "status": "enable",
            "created_at": "2020-06-24T16:25:58Z",
            "updated_at": "2020-06-24T16:25:58Z"
          }
        ],
        "status": "ready",
        "created_at": "2020-03-10T03:20:37.202Z",
        "updated_at": "2020-03-10T03:20:37.202Z"
      }
    ],
    "total": 99
  }
}
```

{% endcode %}


# Recommended Specifications

*Live broadcasting*, especially in high resolution, consumes significant resources from your devices. Therefore, we recommend the following specifications for the *optimal* streaming experience.:metal:&#x20;

|                           | <p><strong>HD streaming on desktop</strong></p><p><strong>(720p)</strong></p> | <p><strong>Full-HD streaming on desktop</strong></p><p><strong>(1080p)</strong></p> |                 **Mobile streaming**                |
| :-----------------------: | :---------------------------------------------------------------------------: | :---------------------------------------------------------------------------------: | :-------------------------------------------------: |
|       **Processor**       |               <p>Intel Core i5 - 5th Gen</p><p>or AMD Ryzen</p>               |                 <p>Intel Core i7 - 5th Gen</p><p>or AMD Ryzen 2</p>                 |                 ARM Cortex-s 64 bit                 |
|         **Memory**        |                                      8GB                                      |                                         8GB                                         |       <p>2GB for iOS</p><p>4GB for Android</p>      |
|        **Graphics**       |                              Intel integrated GPU                             |                                    NVDIA GTX 1050                                   |                    Not applicable                   |
|        **Network**        |        <p>Wi-fi or Ethernet</p><p>(at least 5Mbps of upload speed)</p>        |               <p>Ethernet</p><p>(at least 10Mbps of upload speed)</p>               | <p>Wi-fi</p><p>(at least 5Mbps of upload speed)</p> |
|    **Operating System**   |         <p>Windows 10 and above</p><p>MacOS High Sierra and above</p>         |            <p>Windows 10 and above</p><p>MacOS High Sierra and above</p>            |  <p>Android 7 and above</p><p>iOS 10 and above</p>  |
| **Broadcasting Software** |                         [OBS](https://obsproject.com/)                        |                            [OBS](https://obsproject.com/)                           |        [Streamlabs](https://streamlabs.com/)        |


# Sample Streaming Apps

Uiza provides the video and live streaming API and SDK for your app. These samples introduce various applications based on Uiza API. Refer to the following applications.

* [NodeJS Basic Live Streaming App](/2022-06-06/getting-started/sample-streaming-apps/nodejs-live-streaming-app): The project is a sample application written in **NodeJS** and **React** composed of common live streaming features.&#x20;
* [Python Basic Live Streaming App](/2022-06-06/getting-started/sample-streaming-apps/python-live-streaming-app): The project is a sample application written in **Python** composed of common live streaming features.&#x20;
* [Java Basic Live Streaming App](/2022-06-06/getting-started/sample-streaming-apps/java-live-streaming-app): The project is a sample application written in **Java**  and **React** composed of common live streaming features.&#x20;

The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

This is just a head start! If there’s an integration or sample application you’d like to see or if you’d like to partner with us, [ping us!](mailto:kevin@uiza.io)


# NodeJS Live Streaming App

How to build your live streaming web app with Uiza’s API using React and NodeJS

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Javascript.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. The broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming app

### Step 1. Creating a new Project and install dependencies

To build a broadcast web app, we start with creating a new react web application. Let us create a brand new application. Open terminal / command prompt and execute the below lines to create a starter app:

1. Create a new project

   ```
   npx create-react-app uiza
   ```
2. Get into the project directory

   ```
   cd uiza
   ```
3. Start the development server.

   ```
   npm start
   ```

#### Getting started with Uiza

To start a broadcast with Uiza we will need to do two things:&#x20;

1\. Create a live entity in Uiza servers.&#x20;

2\. Get the ingest.url and ingest.key for this entity.

#### Install program dependencies

To increase the readability of this tutorial, we use the Axios library to send requests to the Uiza server. Install Axios with the following command:

```javascript
npm install axios
```

To play the video stream we will need a player control. Install react-player with the following command:

```javascript
npm install react-player
```

### Step 2. Make changes to the App.js

Open the `App.js` file in the `src` directory.

#### Import repositories

Import react, router, react video player and css file.

```javascript
import React, { Component } from 'react';
import ReactPlayer from 'react-player';
import './App.css';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useParams
} from "react-router-dom";
```

We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

The code snippet shows the constants:

```javascript
const authorization_key = "<<Your API key>>";
const url = "https://api.uiza.sh/api/v5/live/entities";
const default_headers = {
  "Content-Type": "application/json",
  "Authorization": authorization_key
}
```

Then we import Axios to send `GET` and `POST` requests:

```javascript
const  axios  =  require('axios').default;
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.&#x20;
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use application-wide states that can be displayed in the application, and manipulated at run-time. As you can see, we can set default values with states. Our default region value is `in-bangalore-1`

```javascript
state  = {
    message:  '',
    region_value:  'in-bangalore-1',
    broadcast_url:  '',
    broadcast_key:  ''
};
```

#### Define a function to start a broadcast

We define this function as `start_broadcast`. We clear the states and set the message state to `fetching`. Then we start loading the information.

```javascript
this.setState({message: "Fetching"});
this.setState({broadcast_url: ""});
this.setState({broadcast_key: ""});
```

Now we set the parameters, so that we can make the `create entity` call. The below structure contains all the information of the HTTP request that we pass to Axios. As you can see, we make use of the `region_value` state to set the region to a supported value.

```javascript
var broadcast_create_options = {
  "method": "post",
  "url": "https://development-api.uizadev.io/api/v5/live/entities",
  "headers": default_headers,
  "data": {
        "name": 'Demo app',
        "region": this.state.region_value,
        "description": 'Application description'
 }
};
```

Now let's create the polling call structure so that we don't end up creating the same structure from the loop. As you can see it will be a `GET` request. Authorization header will expect your API key.

```javascript
var broadcast_polling_options = {
  "method": "get",
  "headers": default_headers,
  "data": {
      "name": 'Demo app',
      "region": this.state.region_value,
      "description": 'Application description'
    }
};
```

We make a `POST` request to create an entity.

```javascript
var create_response = await axios(broadcast_create_options);
console.log('Response Received')
```

The call returns the entity `id` in the respone.

```javascript
 var broadcast_id = create_response.data.id;
 this.setState({message: 'broadcast Created: '+ broadcast_id});
```

The `GET` method takes the entity `id` and returns the broadcast information (including the stream URL and key).

```javascript
broadcast_polling_options["url"] = url + "/" + broadcast_id;
```

To get the stream URL and key, the entity has to be in a `ready` state. We use `setInterval` to poll the API every 3 seconds to check the status of the entity using `response.data.status`.

The initial status of an entity is `init`. When the server is ready with a stream URL and key, the status becomes `ready`.

If the status is not`ready` yet, we continue polling and the current state of `message` will be set to `Polling`.

Once the status is `ready` we can extract `url` and `key` from the response.

`self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });`

The above code creates a nice text animation so that we know the program is not stuck and is working.

```javascript
var counter = 0;
var self = this;
var poll_interval = setInterval(async function() {
  try {
    var response = await axios(broadcast_polling_options);
    if (response.data.status === "ready") {
      self.setState({ message: "Stream is now ready" });
      self.setState({ broadcast_url: "URL: " + response.data.ingest.url });
      self.setState({ broadcast_key: "Key: " + response.data.ingest.key });
      clearInterval(poll_interval);
    } else {
      self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });
    }
    counter = counter + 1;
  } catch (error) { console.log(error) }
}, 3000);
```

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the `region_value`. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

The first line displays the messages from the program's status: `Fetching`, `Polling` etc.

```javascript
{this.state.message}<br/>
```

The second line contains the stream URL (i.e. `stream_url`)

```javascript
{this.state.broadcast_url}<br/>
```

The third line contains the key for the stream key (i.e `stream_key`)

```javascript
{this.state.broadcast_key}<br/>
```

#### Putting the broadcast page UI together:

```javascript
render() {
    return (
      <div className='page'>
        <div className="App">
          <h1> Uiza Guide </h1>
          <header className="App-header">

            <div style={{ align: "left", float: 'left', width: "45%", margin: "10px", height: "220px", padding: '10px', border: "1px solid white" }}>
              <p> Start broadcast <br />
                <label>Pick your region: &nbsp;
                <select value={this.state.region_value} onChange={(event) => { this.setState({ region_value: event.target.value }); }}>
                    <option value="asia-southeast-1">asia-southeast-1</option>
                    <option value="do-bangalore-1">do-bangalore-1</option>
                    <option value="asia-south-1">asia-south-1</option>
                  </select>
                </label> &nbsp;
              <button onClick={this.start_broadcast}>Start broadcast</button> <br />
              {this.state.message}<br/>
              {this.state.broadcast_url}<br/>
              {this.state.broadcast_key}<br/>
              </p>
            </div>
            </header>
        </div></div>
    )
  }
}

export default App;
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams. Green tiles are online entities and red tiles are offline entities.

The following `load_alive_streams` function loads the streams. Available streams are loaded and saved to `state` so that they update automatically.

```javascript
load_alive_streams = async () => {
    var options = {
      "method": "get",
      "url": url,
      "headers": {
        "Content-Type": "application/json",
        "Authorization": authorization_key
      }
    };
    var response = await axios(options);
    var data = response.data.data;
    var streams = [];
    data.forEach(element => {
      try {
        streams.push({
          online: element.broadcast === 'online' ? true : false,
          stream_url: element.ingest.stream_url,
          stream_key: element.ingest.stream_key,
          playback_url: element.playback.hls
        })
      } catch (err) { }
    });
    this.setState({
      streams: streams,
      last_loaded: new Date()
    });
    console.log(`Completed reading data: ${streams.length} streams are online now!`);
  }
```

#### Rendering the view page UI

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

The above line sends the user to an `href` link which is understood by the router later. The regex removes the protocol from the URL (i.e http / https)

Following code shows the VideoTile component:

```javascript
class VideoTile extends Component {

  render() {
    return (
      <div style={{
        width: "240px", height: "200px", float: "left", margin: "10px", padding: "8px", display: "flex", flexDirection: "column",
        wordWrap: "break-word", fontSize: "16px", border: "2px solid white", backgroundColor: this.props._online ? 'MediumSeaGreen' : 'Tomato'
      }}>

        {/* remove http(s) */}
        <a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
          <span name='url'>URL: {this.props._url}</span><br /><br />
          <span name='key'>KEY: {this.props._key}</span><br /><br />
          <span name='playback_url'>PLAYBACK: {this.props._playback_url}</span>
        </a>
      </div>
    )
  }
}
```

As mentioned above, requests are only made every 5-seconds. We attach the parameters to the VideoTile element. After putting it all together:

```javascript
render() {
    try {

      if (typeof this.state.last_loaded === "string" || ((new Date() - this.state.last_loaded) / 1000) > 5) {
        var items = [];
        this.load_alive_streams().then((result) => {

          for (const [index, value] of this.state.streams.entries()) {
            items.push(<VideoTile key={index}
                                  _url={value.stream_url}
                                  _key={value.stream_key}
                                  _playback_url={value.playback_url}
                                  _online={value.online}></VideoTile>)
          }

          this.setState({ items: items });
          console.log('Loading complete');
        });
      }
    } catch (err) {
      this.setState({ last_loaded: new Date() });
    }

    return (
      <div className="App">
        <h1 style={{ padding: "8px" }}>  Uiza Online Videos </h1>
        <header className="App-header">
          <div name='tileContainer'>
            {this.state.items}
          </div></header>
      </div>
    )
  }
```

### Step 6. Playback the live stream

Now we have the video tiles ready but what do we show when this tile is clicked? This clever little view code launches the player on screen. We launched the player on the screen when the tile is clicked with the following code:

```javascript
function VideoPage() {
  let { videoid } = useParams();
  return (
    <div style={{ padding: "20px" }}>
      <ReactPlayer url={"https://" + videoid} playing={true} controls={true}></ReactPlayer>
    </div>)
}
```

#### Routing and overall APP UI

We make use of the `Router` component in react to create pagination in our app. We will have the link to broadcast and view page

To enable pagination in the app, we need to make use of react's routing. Following code does the routing:

```javascript
class App extends Component {

  render() {
    return (
      <Router>
        <div className='page'>
          <nav>
            <ul>
              <li>
                <Link to="/broadcast">Broadcast Page</Link>
              </li>
              <li>
                <Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>
              </li>
            </ul>
          </nav>

          {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
          <Switch>
            <Route path="/broadcast">
              <BroadcastPage />
            </Route>
            <Route path="/viewer">
              <ViewerPage />
            </Route>
            <Route path="/video/:videoid*">
              <VideoPage />
            </Route>
          </Switch>
        </div>
      </Router>
    )
  }
}
```

The streams are loaded when we click on the viewer with the below line. Following line loads the streams on click: `<Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>`

The routing path below with `*` wildcard enables video stream url to be parsed with `/` and to be sent to the video page. Otherwise, the videoid is split at the first occurence of `/`

```javascript
<Route path="/video/:videoid*">
              <VideoPage />
```

## Conclusion

That's all wasn't that fun? If you have any questions please check out our Github repo where this entire project has been uploaded with source code [here](https://github.com/uizaio/uiza-node-sample-app) and if you have any other questions please contact us here: <anhnh@uiza.io>


# Java Live Streaming App

How to build your live streaming web app with Uiza’s API using React and Java

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Javascript.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. Tha broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming JAVA app (Backend)

### Step 1. Getting started with Uiza Java application

To start a broadcast with Uiza Java App, we will need to configure stream\_url and stream\_key in application propeties file.

We need an API key to access Uiza's services. To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key. Configured your API key and URL in application properties as below.

We have created Java because we can not pass API key through browser. If we pass API key through browser then anyone can stole our API key and use Uiza api. So using JAVA app, we are storing this API key in the JAVA property file and calling Uiza api from Java App.

```
application.uiza.url= https://api.uiza./v1/live_entities
application.uiza.authorization-token="API Key"
```

### Step 2. Deploy/Run Java App

Download the Java sample code at [Github link](https://github.com/uizaio/uiza-live-java-server-integration)

1. Go To Project Directory

   ```
   cd uiza
   ```
2. Run below command

   ```
   mvn clean install
   ```
3. After step 2 finishes installation, go to `target` directory inside the project.&#x20;

   ```
   cd target
   ```
4. Run the below command to run java application. Java application will run 8080 port.

   ```
   java -jar uiza-0.0.1-SNAPSHOT.jar
   ```

### Step 3. This guide will help you create a simple REST service using Spring Boot.

In this guide, we will create three services using proper URIs and HTTP methods:

* @GetMapping("/app/live/entities"): You can retrieve the live entities using request method Get and example uri /app/live/entities.
* @GetMapping("/app/live/entities/{id}"): You can retrieve a specific live entity using request method Get and example uri /app/live/entities/1.
* @PostMapping("/app/live/entities") : You can create a live entity by sending a POST request to URI /app/live/entities

#### Using appropriate Request Methods

Always use HTTP Methods. Best practices with respect to each HTTP method is described below:

* `GET` : Should not update anything. Should be idempotent (same result in multiple calls). Possible Return Codes 200 (OK) + 404 (NOT FOUND) +400 (BAD REQUEST)
* `POST` : Should create new resource. Ideally return JSON with link to newly created resource. Same return codes as get possible. In addition : Return code 201 (CREATED) is possible.
* `PUT` : Update a known resource. ex: update client details. Possible Return Codes : 200(OK)
* `DELETE` : Used to delete a resource.

#### Project Structure

Following screenshot shows the structure of the project we have created. ![](https://i.imgur.com/Zvtz1E2.png) **A few details:**

* **LiveEntityResource.java** - Rest controller exposing all the three service methods discussed above.
* **LiveEntity.java** - Business Logic for the application.
* **UizaApplication.java** - Launcher for the Spring Boot Application. To run the application, just launch this file as Java Application.
* **pom.xml** - Contains all the dependencies needed to build this project. We will use Spring Boot Starter Web.

#### Adding Couple of GET Rest Services

The Rest Service LiveEntityResource exposes couple of get services.

@Autowired private RestTemplate restTemplate : We are using Spring Autowiring to wire the RestTemplate service into the LiveEntityResource. This rest template will use for call Uiza server api to get/create live entity. @Value("${application.uiza.url}") private String ulzaUrl : Use the uiza server url that we have configured in step1.

@PathVariable String id: Value of live entity id from the uri will be mapped to this parameter. package com.uiza.api.rest;

```
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.uiza.api.dto.GetLiveEntityResponse;
import com.uiza.api.dto.LiveEntity;

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/app/live/entities")
public class LiveEntityResource {

    @Autowired
    private RestTemplate restTemplate;

    @Value("${application.uiza.url}")
    private String ulzaUrl;

    @GetMapping
    public GetLiveEntityResponse getLiveEntities() {

        ResponseEntity<GetLiveEntityResponse> responseEntity = restTemplate.getForEntity(ulzaUrl,
                GetLiveEntityResponse.class);

        return responseEntity.getBody();
    }

    @GetMapping("/{id}")
    public LiveEntity getLiveEntities(@PathVariable String id) {

        ResponseEntity<LiveEntity> responseEntity = restTemplate.getForEntity(ulzaUrl + "/" + id, LiveEntity.class);

        return responseEntity.getBody();
    }

}
```

**Executing the Get Service for retrieve all live Using Postman.**

We will fire a request to <http://localhost:8080/app/live/entities> to test the service. Response is as shown below.

```
[{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}]
```

**Executing the Get Service to retrieve live entity by id Using Postman**

We will fire a request to <http://localhost:8080/app/live/entities/2b970a39-874a-4d2a-be8a-fd445646d74c> to test the service. Response is as shown below.

```
{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}
```

#### Adding a POST Rest Service

A POST Service should return a status of created (201) when the resource creation is successful.

@PostMapping("/app/live/entities"): Mapping a url for the POST Request @RequestBody LiveEntity liveEntity: Using Binding to bind the body of the request to LiveEntity object. responseEntity.getBody(): Return a status of created. Also return the location of created resource as a Response Header.

```
    @PostMapping
    public LiveEntity createLiveEntity(@RequestBody LiveEntity liveEntity) {

        ResponseEntity<LiveEntity> responseEntity = restTemplate.postForEntity(ulzaUrl, liveEntity, LiveEntity.class);

        return responseEntity.getBody();
    }
```

**Executing a POST Rest Service**

Example Request is shown below. It contains all the details to create a live entity.

```
{
  "name": "Demo",
  "description": "AFF CUP",
  "region": "in-bangalore-1"
}
```

Example Response is shown below. It contains all the details that has been created for live entity.

```
{
     "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
     "user_id": "uiza",
     "app_id": "uiza",
     "name": "Test Event",
     "description": "Event for Test",
     "region": "in-bangalore-1",
     "status": "init",
     "created_at": "2019-10-03T17:34:49Z",
     "updated_at": "2019-10-03T17:34:49Z"
}
```

#### Modification in live entity

* Suppose if we have to add new field in live entity then we have to do as below example.
* For example, If we have to add new field(abc) in live entity then we have to do below modification in LiveEntity.java

```javascript
private String abc;
public String getAbc(){ return abc; }
public void setAbc(String abc){ this.abc = abc; }
```

## Building the live streaming app (front-end part)

```


## Step 1. Creating a new Project and install dependencies
To build a broadcast web app, we start with creating a new react web application.
Let us create a brand new application. 
Open terminal / command prompt and execute the below lines to create a starter app: 

1. Create a new project
```

### Step 1. Creating a new Project and install dependencies

To build a broadcast web app, we start with creating a new react web application.

Let us create a brand new application.&#x20;

Open terminal / command prompt and execute the below lines to create a starter app:&#x20;

#### 1. Create a new project

To build a broadcast web app, we start with creating a new react web application. Let us create a brand new application. Open terminal / command prompt and execute the below lines to create a starter app:&#x20;

`npx create-react-app uiza`

#### 2. Get into the project directory

`cd uiza`

#### 3. Start the development server.

`npm start`

#### Getting started with Uiza

To start a broadcast with Uiza we will need to do two things:

1. Create a live entity in Uiza servers.
2. Get the stream\_url and stream\_key for this entity.

#### Install program dependencies

To increase the readability of this tutorial, we use the Axios library to send requests to the Uiza server. Install Axios with the following command:

`` `npm install axios` ``

To play the video stream we will need a player control. Install react-player with the following command:

`` `npm install react-player` ``

### Step 2. Make changes to the App.js

Open the \`App.js\` file in the \`src\` directory.

#### Import repositories

Import react, router, react video player and css file.

```javascript
import React, { Component } from 'react';
import ReactPlayer from 'react-player';
import './App.css';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link,
  useParams
} from "react-router-dom";
```

We need an JAVA API to access Uiza's services.

```javascript
const url = "https://api.uiza.sh/app/live/entities";
const default_headers = {
  "Content-Type": "application/json"
}
```

Then we import axios to send get and post requests:

```javascript
const  axios  =  require('axios').default;
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use application-wide states that can be displayed in the application, and manipulated at run-time. As you can see, we can set default values with states. Our default region value is `in-bangalore-1`

```javascript
state  = {
    message:  '',
    region_value:  'in-bangalore-1',
    broadcast_url:  '',
    broadcast_key:  ''
};
```

#### Define a function to start a broadcast

We define this function as `start_broadcast`. We clear the states and set the message state to `fetching`. Then we start loading the information.

```javascript
this.setState({message: "Fetching"});
this.setState({broadcast_url: ""});
this.setState({broadcast_key: ""});
```

Now we set the parameters, so that we can make the `create entity` call. The below structure contains all the information of the HTTP request that we pass to Axios. As you can see, we make use of the `region_value` state to set the region to a supported value.

```javascript
var broadcast_create_options = {
  "method": "post",
  "url": "https://api.uiza.sh/api/v5/live/entities",
  "headers": default_headers,
  "data": {
        "name": 'Demo app',
        "region": this.state.region_value,
        "description": 'Application description'
 }
};
```

Now let's create the polling call structure so that we don't end up creating the same structure from the loop. As you can see it will be a `GET` request. Authorization header will expect your API key.

```javascript
var broadcast_polling_options = {
  "method": "get",
  "headers": default_headers,
  "data": {
      "name": 'Demo app',
      "region": this.state.region_value,
      "description": 'Application description'
    }
};
```

We make a `POST` request to create an entity.

```javascript
var create_response = await axios(broadcast_create_options);
console.log('Response Received')
```

The call returns the entity `id` in the response.

```javascript
 var broadcast_id = create_response.data.id;
 this.setState({message: 'broadcast Created: '+ broadcast_id});
```

The `GET` method takes the entity `id` and returns the broadcast information (including the stream URL and key).

```javascript
broadcast_polling_options["url"] = url + "/" + broadcast_id;
```

To get the stream URL and key, the entity has to be in a `ready` state. We use setInterval to poll the API every 3 seconds to check the status of the entity using `response.data.status` The initial status of an entity is `init`. When the server is ready with a stream URL and key, the status becomes `ready`

If the status is not`ready` yet, we continue polling and the current state of `message` will be set to `Polling`

Once the status is `ready` we can extract `url` and `key` from the response.

`self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });`

The above code creates a nice text animation so that we know the program is not stuck and is working.

```javascript
var counter = 0;
var self = this;
var poll_interval = setInterval(async function() {
  try {
    var response = await axios(broadcast_polling_options);
    if (response.data.status === "ready") {
      self.setState({ message: "Stream is now ready" });
      self.setState({ broadcast_url: "URL: " + response.data.ingest.url });
      self.setState({ broadcast_key: "Key: " + response.data.ingest.key });
      clearInterval(poll_interval);
    } else {
      self.setState({ message: 'Polling' + '.'.repeat(1 + counter%3) });
    }
    counter = counter + 1;
  } catch (error) { console.log(error) }
}, 3000);
```

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the `region_value`. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

The first line displays the messages from the program's status: `Fetching`, `Polling` etc.

```javascript
{this.state.message}<br/>
```

The second line contains the stream URL (i.e. `stream_url`)

```javascript
{this.state.broadcast_url}<br/>
```

The third line contains the key for the stream key (i.e `stream_key`)

```javascript
{this.state.broadcast_key}<br/>
```

#### Putting the broadcast page UI together:

```javascript
render() {
    return (
      <div className='page'>
        <div className="App">
          <h1> Uiza Guide </h1>
          <header className="App-header">

            <div style={{ align: "left", float: 'left', width: "45%", margin: "10px", height: "220px", padding: '10px', border: "1px solid white" }}>
              <p> Start broadcast <br />
                <label>Pick your region: &nbsp;
                <select value={this.state.region_value} onChange={(event) => { this.setState({ region_value: event.target.value }); }}>
                    <option value="in-bangalore-1">in-bangalore-1</option>
                    <option value="in-mumbai-1">in-mumbai-1</option>
                  </select>
                </label> &nbsp;
              <button onClick={this.start_broadcast}>Start broadcast</button> <br />
              {this.state.message}<br/>
              {this.state.broadcast_url}<br/>
              {this.state.broadcast_key}<br/>
              </p>
            </div>
            </header>
        </div></div>
    )
  }
}

export default App;
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams. Green tiles are online entities and red tiles are offline entities.

The following `load_alive_streams` function loads the streams. Available streams are loaded and saved to `state` so that they update automatically.

```javascript
load_alive_streams = async () => {
    var options = {
      "method": "get",
      "url": url,
      "headers": {
        "Content-Type": "application/json"
      }
    };
    var response = await axios(options);
    var data = response.data.data;
    var streams = [];
    data.forEach(element => {
      try {
        streams.push({
          online: element.broadcast === 'online' ? true : false,
          stream_url: element.ingest.url,
          stream_key: element.ingest.key,
          playback_url: element.playback.hls
        })
      } catch (err) { }
    });
    this.setState({
      streams: streams,
      last_loaded: new Date()
    });
    console.log(`Completed reading data: ${streams.length} streams are online now!`);
  }
```

#### Rendering the view page UI

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

The above line sends the user to an `href` link which is understood by the router later. The regex removes the protocol from the URL (i.e http / https)

Following code shows the VideoTile component:

```javascript
class VideoTile extends Component {

  render() {
    return (
      <div style={{
        width: "240px", height: "200px", float: "left", margin: "10px", padding: "8px", display: "flex", flexDirection: "column",
        wordWrap: "break-word", fontSize: "16px", border: "2px solid white", backgroundColor: this.props._online ? 'MediumSeaGreen' : 'Tomato'
      }}>

        {/* remove http(s) */}
        <a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
          <span name='url'>URL: {this.props._url}</span><br /><br />
          <span name='key'>KEY: {this.props._key}</span><br /><br />
          <span name='playback_url'>PLAYBACK: {this.props._playback_url}</span>
        </a>
      </div>
    )
  }
}
```

As mentioned above, requests are only made every 5-seconds. We attach the parameters to the VideoTile element. After putting it all together:

```javascript
render() {
    try {

      if (typeof this.state.last_loaded === "string" || ((new Date() - this.state.last_loaded) / 1000) > 5) {
        var items = [];
        this.load_alive_streams().then((result) => {

          for (const [index, value] of this.state.streams.entries()) {
            items.push(<VideoTile key={index}
                                  _url={value.stream_url}
                                  _key={value.stream_key}
                                  _playback_url={value.playback_url}
                                  _online={value.online}></VideoTile>)
          }

          this.setState({ items: items });
          console.log('Loading complete');
        });
      }
    } catch (err) {
      this.setState({ last_loaded: new Date() });
    }

    return (
      <div className="App">
        <h1 style={{ padding: "8px" }}>  Uiza Online Videos </h1>
        <header className="App-header">
          <div name='tileContainer'>
            {this.state.items}
          </div></header>
      </div>
    )
  }
```

### Step 6. Playback the live stream

Now we have the video tiles ready but what do we show when this tile is clicked? This clever little view code launches the player on screen. We launched the player on the screen when the tile is clicked with the following code:

```javascript
function VideoPage() {
  let { videoid } = useParams();
  return (
    <div style={{ padding: "20px" }}>
      <ReactPlayer url={"https://" + videoid} playing={true} controls={true}></ReactPlayer>
    </div>)
}
```

#### Routing and APP overall UI

We make use of the `Router` component in react to create pagination in our app. We will have the link to broadcast and view page

To enable pagination in the app, we need to make use of react's routing. Following code does the routing:

```javascript
class App extends Component {

  render() {
    return (
      <Router>
        <div className='page'>
          <nav>
            <ul>
              <li>
                <Link to="/broadcast">Broadcast Page</Link>
              </li>
              <li>
                <Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>
              </li>
            </ul>
          </nav>

          {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
          <Switch>
            <Route path="/broadcast">
              <BroadcastPage />
            </Route>
            <Route path="/viewer">
              <ViewerPage />
            </Route>
            <Route path="/video/:videoid*">
              <VideoPage />
            </Route>
          </Switch>
        </div>
      </Router>
    )
  }
}
```

The streams are loaded when we click on the viewer with the below line. Following line loads the streams on click: `<Link to="/viewer" onClick={ViewerPage.load_alive_streams}>Viewer Page</Link>`

The routing path below with `*` wildcard enables video stream url to be parsed with `/` and to be sent to the video page. Otherwise, the videoid is split at the first occurence of `/`

```javascript
<Route path="/video/:videoid*">
              <VideoPage />
```

## Conclusion

That's all wasn't that fun? If you have any questions please check out our Github repo where this entire project has been uploaded with the Java source code [here](https://github.com/uizaio/uiza-live-java-server-integration) and the Javascript source code [here](https://github.com/uizaio/uiza-node-sample-app). If you have any other questions please contact us here: <anhnh@uiza.io>


# Python Live Streaming App

How to build your live streaming web app with Uiza’s API using Python

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming app with Uiza’s APIs. The web app will have two components: the broadcaster web app, to start a stream, and the viewer app, to list all broadcasts and playback the broadcast.

## Components of our live streaming app

Sample code is provided below on how to build a simple web app to call on Uiza’s API. The language used for web app is Python.

#### Uiza Streaming Concept

To understand the flow of the this tutorial, following terminologies are explained by the graph below.&#x20;

![](https://i.imgur.com/HQeo1jG.png)

During this documentation, broadcast, live streaming and streaming will be usede interchangeably.

#### Building a Live streaming Web App with Uiza

To have a live streaming app, we have to distinguish between a broadcaster and a viewer. A broadcaster streams the live stream and a viewer watches the live stream - this is a one way interaction channel, hence we have to build 2 separate pages: a broadcasting page and a viewer page. Tha broadcaster needs to start a broadcast through a stream URL and key, while the viewer sees the active live streams and can watch them through the web app.

## Building the live streaming app

### Prerequisites

Install following dependencies in terminal

### Step 1. Creating a new Project and install dependencies

#### Dependencies

`pip install python`&#x20;

`pip install django`&#x20;

`pip install json`

To build a broadcast web app, we start with creating a new python project.

#### Creating a new Project

1. Open your favorite editor
2. Open the terminal&#x20;
3. Type: django-admin createproject (this makes a directory with your project name) in the terminal
4. Go to your project directory `cd project name`
5. To create your app, type: `django-admin createApp <AppName>`(this creates an app inside your project)
6. Create a templates folder in which your html files will be held.Templates folder will be in project folder.

   <img src="/files/-LxUJIirbZ84tgk_Pn5x" alt="your project directory structure should look like this" data-size="original">

   your project directory structure should look like this &#x20;

   **Don't worry about the project and app name, as any name will work.**
7. Open `setting.py` and add the app name to the installed apps list. Also add templates path to templates dir.

![](https://i.imgur.com/C6vAgtS.png)

![](https://i.imgur.com/PQ9pSaN.png)

#### Setting up the templates folder

Create 4 html files in templates folder:&#x20;

1. `base.html`&#x20;
2. `homepage.html`&#x20;
3. `viewspage.html`&#x20;
4. `broadcastpage.html`

For now leave these empty.

#### Django connects and renders:

We will define some urls in the `urls.py` file in project directory. There we write the view name, which performs some functions and renders a html file.

`url eg: path('viewers/', views.viewerspage, name = 'viewers')` so here 'viewers/' is the url that will be added to localhost, views.viewerspage is name of views which will perform some functions on this url and name = 'viewers' is used to redirect to another view from html file after submission which we will use later.

### &#x20;Step 2. Setting up the URLS

You must have noticed the `urls.py` file in the project directory. Lets open it and see what it does. In the file we see some imports and a list named url patterns. As discussed we need to connect urls and views, so we will import views to `urls.py` file

`from app name import views`

We will make some urls in url patterns list like this. &#x20;

![](/files/-LxUKfUOLnyngow_c-sb)

`admin/` was defined already, that is the default url provided by Django and Django is known for this feature of providing an admin portal which keeps all the database of your website. But let's take example of `viewers/` url. Lets divide this into 3 parts: url, view, and name

**URL** - what URL should appear at the URL bar&#x20;

**View** - what view to call when user puts this URL in the URL bar.

**Name** - this is name of url which we will use when talking about templates to redirect to             other urls from html pages.(don't worry if it is not clear now)

````
now we will make some urls in url patterns list like this.
![](https://i.imgur.com/omMT2p2.png)

so 'admin/' was defined already, that is the default url provided by django and django is known for this feature of providing an admin portal which keeps all the database of your website.
But let's take example of 'viewers/' url.
so lets divide this into 3 parts url,view,name
**Url** - what url should appear at the url bar 
**View** - what view to call when user puts this url in        the url bar.
**Name** - this is name of url which we will use when           talking about templates to redirect to             other urls from html pages.(don't worry if it is not clear now)

## Step 2. Setting up authorization


We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

Following code shows the constants:
```python=
Authorization_key = "<<Your API key>>"
url = 'https://development-api.uizadev.io/v1/live_entities'
````

### Step 2. Setting up authorization

We need an API key to access Uiza's services. The URL to access the services will be the same, so we're saving it as a constant. The default headers will be common for every API call.

To get your API key, create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). Once you are in the developer console, you will see your API key.

Following code shows the constants:

```python
Authorization_key = "<<Your API key>>"
url = 'https://development-api.uizadev.io/v1/live_entities'
```

#### Paging and navigation.

We divide the app into two parts:&#x20;

1. Broadcast Page: Will contain the functionality to create a new broadcast.
2. View Page: This will display all broadcasts currently in the system, with online broadcasts as a green tile and offline broadcasts as an orange-red.

### Step 3. Building the Broadcast Page

Let us start with the broadcast page design.

#### Creating default states

We use global variables that can be displayed in the application, and manipulated at run-time.

```python
stream_key = ''
stream_url = ''
stream_hls = ''
NotPlayable = True
```

#### Define a view to start a broadcast

**Note:** a function in python is called a view in Django. The below structure contains all the information of the HTTP request.

As you can see, we make use of the `region` state to set the region to a supported value.

We will create an Entity using the `POST` method:

So what below view does?

First, it checks if the request method is a POST method. If it is not, then a simple html page is rendered.

Otherwise, the if condition is triggered and the POST method will be called after the submit button of form is clicked, which we will see in the html file.

Then we make a POST request using the parameters and get back a json response from the Uiza API

The parameter are defined in Uiza's API documentation.

```python
#when broadcast button is click post method is triggered

def create_event(request):
    if request.method == "POST":
        region = request.POST['region']

        # necessary headers and data for the post request 
        headers = {'Authorization': Authorization_key ,
                'Content-Type': 'application/json',
                'cache-control': 'no-cache' }   
        data = {
                "name":"Demo",
                "region":region,
                "description":"AFF CUP"
                }
        #post request for the id of live stream    
        response = requests.post(url = url, headers = headers, params= data)
        print(response.text)
        #convert the response to json
        live_response = json.loads(response.text)
        #retrieved id from json
        created_id = live_response["id"]
```

Using the retrieved entity, we call the 'GET' method with `id` as value. The authorization header expects your API key.

```python
# Now make the get request using the headers and using the id retrieve the     stream_key,stream_url and playback
get_headers = {
    'Accept': '*/*',
    'Accept-Encoding': 'gzip, deflate',
    'Authorization': Authorization_key,
    'Cache-Control': 'no-cache',
    'Connection': 'keep-alive'
}

newUrl = url+'/' + created_id
```

Now let's create the polling call structure. This loop will run until the 'status' returned is 'ready'. As soon as the status becomes 'ready', the global variables for `stream_url`, `stream_key`, and `stream_hls` are retrieved from the GET request.

```python
        #This while loop will make the get request from the uiza UPI till the status is     not ready and retrieve the necessary info and then will render the homepage
        while True:
            retrieve_entity = requests.get(url = newUrl, headers=get_headers)
            retrieve_entity_json = json.loads(retrieve_entity.text)
            status = retrieve_entity_json["status"]
            print(status)
            print(i)
            if status == "ready":
                print(retrieve_entity_json)
                global stream_url
                stream_url = retrieve_entity_json["ingest"]["url"]
                global stream_key
                stream_key = retrieve_entity_json["ingest"]["key"]
                global stream_hls
                stream_hls = retrieve_entity_json['playback']['hls']
                global NotPlayable
                NotPlayable = False

                return render(request,'homepage.html')
return render(request,'broadcastpage.html') #This render will be called if post request is not made.
```

Now we go to our html pages which we created earlier:

### Step 4. Building the broadcast page UI

We build a very simple user interface. The front page will have a drop-down menu to select the regions. This drop-down contains the following regions (you can find the available regions here: [Regions](https://starboy.gitbook.io/uiza-doc/getting-started/regions)):

* in-bangalore-1
* in-mumbai-1

We create a `Start broadcast` button to call the `start_broadcast` function. The three lines below are important. They leverage the state value to display current states.

Now what does this html page do?

It uses some html tags and Django template tagging. Template tagging is used to insert logic into html. Basically this implements a html form and a Javascript polling function. Now have a look at `action` in form. This is a template tag which tells when form is submitted, then goes to a url whose name is broadcast. Remember we gave names to url paths in the `urls.py` file. Under that you will see csrf token which is cross-site request forgery used with forms always.

Now button tag contains value="submit". This means the value selected by user from the drop down will be attached with submit button so that we can use that value in views.

Polling function is just to give animation, so that when broadcast button is clicked, `Polling...` starts till we get response from the Uiza API. Consider it as loading of another html page.

Also consider: `{% extends 'base.html' %}` . This inherits all the html tags from `base.html` . Writing of repetitive html code for every page is prevented with this; the uniformity of the code is maintained as well.

Everything inside

```markup
{% block body_block %}
{% endblock %}
```

is unique to this html file.

```markup
{% extends 'base.html' %}
<!-- form for the broadcasting page which lets user to select the region and start broadcasting -->
{% block body_block %}
<h1>UIZA GUIDE</h1>
<div style="align-content:left;float:left;width:'45%';margin:'10px';height:'220px';padding:'10px'; border:'1px solid red'"></div>
<!-- the template tag in action will take us to create_event view because in urls.py the views name is broadcast -->
<!-- onsubmit of form StartPolling js function is called -->
<form action="{% url 'broadcast' %}"  method="POST" onSubmit="StartPolling();">
    {% csrf_token %}
    <p> Start broadcast <br /><p>
        <label>Pick your region: &nbsp;
                <select name="region" id="region">
                    <option value="in-bangalore-1">in-bangalore-1</option>
                    <option value="in-mumbai-1">in-mumbai-1</option>
                  </select>
                </label> &nbsp;
                <!-- after submission the selected value from the dropdown will go to the create event view -->
              <button  type="submit" value="select" >Start broadcast</button> <br />
              <span id="wait"></span>
            </form>              
            <!-- this js function will play as loading screen until we get the response of our request from the API  -->
              <script>
                  function StartPolling() {
                  setInterval(function Polling() {

                  var wait = document.getElementById("wait");
                  if(wait.innerHTML.length==0)
                    wait.innerHTML = "Polling";
                  if ( wait.innerHTML.length > 10 ) 
                    wait.innerHTML = "Polling";
                  else 
                    wait.innerHTML += ".";
                  }, 1000);
                  }

              </script>
    </p>

</div>
</div> 
{% endblock %}
```

### Step 5. Building the View Page

The view page contains tiles that correspond to available streams.

This view will render simple html page when `NotPlayable` is false; when true, it will send the list of responses to `viewerspage.html`in a context dictionary.

Context dictionary is just the information passed to the html page from the view.

```python
def viewerspage(request):
    # if broadcast button is not clicked then this view is rendered
    if NotPlayable: 
        print('got here')
        list_of_videos = []
        return render(request,'viewerspage.html')
    else:    
        # if broadcast button is clicked then this view is rendered and a context         dictionary is passed with stream_key, stream_url, playback link

        stream_dict=    {'stream_key':stream_key,'stream_url':stream_url,'playback':stream_hls}
        list_of_videos.append(stream_dict)
    #The last parameter of render is the context dictionary, these are the variables     which store useful info that we would want to use in out templates
    return render(request,'viewerspage.html',{'list_of_videos':list_of_videos})
```

#### Rendering the view page html

We create a dynamic list of VideoTiles, and populate it on every render(). We use a 5-second interval between each render, to not overdo it. Then we access the details from the properties of the Video at the time of creation. We use the properties to pass values to the inner components of the tile and make it look functional.

For example: `{this.props._url}` accesses the `_url` parameter from `<VideoTile>` The same approach is used for the key and the playback URL.

The tile has to be clickable and take the viewer to the live stream. For that, we make use of routing in our application and send the user to a page with video playback url. The playback page is dynamically generated and plays the video.

```javascript
<a href={"./video/" + this.props._playback_url.replace(/(^\w+:|^)\/\//, '')}>
```

Following code shows the VideoTile component:

In this html we inherit from base.html, then we go to our body block and apply a for loop, which will give us 3 keys, and we need the playback key's url that we have put into the video tag which plays the video on click.

In the following code block we inherit from base.html. The body block contains a for loop, which gives us 3 keys; the playback key's URL from the video tag is needed, to play the video on click.

```markup
{% extends 'base.html' %}
{% block body_block %}
<h1>UIZA ONLINE VIDEOS</h1>

     <!-- the list of videos got by the context dictionary will be displayed here with stream url, stream key and playback  -->
    {% for each in list_of_videos %}  

    <div class = 'tileContainer' style="width: 240px; height: 200px;float: left; margin: 10px; padding: 8px; display: flex; flex-Direction: column;
    word-Wrap: break-word; font-Size: 16px; border: 2px solid white; background-Color:Tomato;">    
      {% for key, value in each.items %}

      <!-- play the video when playback link is found else just print the link in the video tile -->
      {% if key == 'playback' %}
        <video src="key" type="application/x-mpegURL"></video>
      {% else %}
      <p><a href="{{value}}">{{key}}</a></p>
      {% endif %}

      </div>
    {% endfor %}
  {% endfor %}  
{% endblock %}
```

## Conclusion

That's how you can integrate live streaming into your app using Uiza's APIs. With just two API methods, you will have your stream key and stream URL to start a live stream. If you have any questions please check out our Github repo where this entire project has been uploaded with source code [here](https://github.com/info3g/python-uiza) and if you have any other questions please contact us here: <anhnh@uiza.io>


# How to integrate live streaming into an Android App using Uiza’s Live API

## Introduction

Uiza provides intuitive APIs, which simplifies the integration of live streaming functionality into your platform. This guide is a step-by-step tutorial on how to build your live streaming Android app with Uiza’s APIs. The full sample code can be downloaded at the end of the tutorial.

### Integrating live streaming into android application

For this tutorial, we build two separate apps: The streaming app, where a video is captured over the phone's camera and streamed; the viewer app, where all the live entities are listed and can be watched on mobile. Step 1 to Step 4 is for the Streaming App, and Step 5 to Step 7 is for the Viewer app.

### Uiza Terminologies

Throughout the tutorial we will be mentioning live entities, streamers and viewers.

`live entities` are basically live events, with or without a live feed. A live entity contains the information required for Uiza to allocate resources to power the live event, and direct your live feed toward these resources for ingestion and streaming.

`Streamer`: Streamers record the live events and are the source of the live signals that Uiza receives.

`Viewer`: Viewers are the users who watch the live stream on their devices. They are the destination of the delivery of the live stream.

## Prerequisite

* Android Studio 3.3 or above
* Min API 19 (Android KitKat)
* Real devices (Nexus 5X or other devices)

### Uiza Account

We need an API key to access Uiza’s services. To get your API key follow these steps: 1. create an account at Uiza here: [Sign Up Link](https://id.uiza.io/register). 2. In the developer console, go to your application 3. Save the API Key 4. Update API key at `samplelive/src/main/java/io/uiza/samplelive/SampleLiveApplication.java`

```java
private static final String API_TOKEN = <<API Key>>; // dynamic
```

## Step 1 - Streaming app - Dependencies and Permissions

We start with setting the permissions in the manifest file.

### Permissions

```java
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.CAMERA" /> <!-- needed by background Rtp service to keep service alive -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- Optional for play store -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- for record -->
```

### Dependencies

Add the `Jitpack` repository to your `build.gradle` file

```java
allprojects {
      repositories {
         maven { url 'https://jitpack.io' }
      }
}
```

Add the Uiza live streaming and playback SDK as follow:

```java
defaultConfig {  
    multiDexEnabled  true
}  
dependencies {  
    // for playing VOD, LIVE video  
    implementation 'com.github.uizaio.uiza-android-sdk-player:uizacoresdk:[latest-release-number]'        

    // for broadcasting / live streaming
    implementation 'com.github.uizaio.uiza-android-sdk-player:uizalivestream:[latest-release-number]'  
}
```

You can get the latest release number [HERE](https://github.com/uizaio/uiza-android-sdk-player/releases)

If you are using uiza\_android\_sdk\_player (version 4.0.9 and above), you will need to import following dependencies:

```java
// for playing VOD, LIVE video
implementation 'com.github.uizaio.uiza-android-sdk-player:uizacoresdk:4.0.9'
implementation 'com.google.android.exoplayer:exoplayer:2.10.8'
implementation 'com.google.android.exoplayer:exoplayer-dash:2.10.8'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.10.8'
```

## Step 2 - Creating a live entity

We pass on the parameters to `createEntity`.

```java
        CreateLiveBody body = new CreateLiveBody(
                "<streamName>",
                "<Description>",
                "<region>"
        );
        UizaLiveService liveService = UizaClientFactory.getLiveService();
        RxBinder.bind(
                liveService.createEntity(body),
                liveEntity -> {
                    // onSuceess
                }, throwable -> {
                    // onError
                    Timber.e(throwable);
                }, () -> {
                    // onComple
                }
        )
```

This step returns us a live entity ID; the ID is used for the following step.

## Step 3 - Getting the live entity info

We will use the live entity ID to retrieve the key & URL.

```java
RxBinder.bind(UizaClientFactory.getLiveService().getEntity("<entityId>"), liveEntity -> {
        // onSuccess
    }, throwable -> {
        //onError
    }, () -> {
        // onComplete
    });
```

## Step 4 - Making a live stream

We capture the live stream using the Android camera In layout xml

```markup
    <io.uiza.live.UizaLiveView
        android:id="@+id/uiza_live_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:audioBitrate="64"
        app:audioSampleRate="32000"
        app:audioStereo="true"
        app:fps="24"
        app:frame_interval="2"
        app:videoSize="p720"
        app:useCamera2="true"
        app:AAEnabled="false"
        app:isFlipHorizontal="false"
        app:isFlipVertical="false"
        app:keepAspectRatio="true"
        app:numFilters="1"/>
```

In java code:

```java
    UizaLiveView liveView = findViewById(R.id.uiza_live_view);
```

To Start: We pass the URL and Key from the API call to `startStream`

```java
    if (liveView.isRecording() || liveView.prepareStream()) {
        liveView.startStream(liveStreamUrl);
    }
```

To Stop

```java
    liveView.stopStream();
```

To Switch Camera

```
    try {
        liveView.switchCamera();
    } catch (UizaCameraOpenException e) {
        // error
    }
```

## Step 5 - Viewer app - listing he entities

### Viewer App - list out all entities

The viewer app will display all active live streams for the viewer.

```java
RxBinder.bind(
    UizaClientFactory.getLiveService()
        .getEntities()
        .map(ListWrap::getData),
    entities -> {
        //onSuccess
    }, throwable -> {
        // onError
    }
);
```

Currently a dummy thumbnail is in use. When the thumbnail API is added, this part of the code will be updated to include the thumbnail.

## Step 6 - playback a live stream

### Viewer App - playback feature

Using the Uiza player, we will playback the stream

In layout xml we set the video dimensions.

In Java code:

```java
    UZUtil.setCasty(activity);
    UZVideo uzVideo = findViewById(R.id.uiza_video);
    uzVideo.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_HEIGHT);
    UZUtil.initLiveEntity(this, uzVideo, liveEntity.getPlaybackInfo());
            uzVideo.setFreeSize(true);
```

## Step 7 - adding chat functionality

To create a communication channel between viewer and streamer, we enable chat. We will use Google's Firebase for this sample code, as it is very well supported and intuitive.

### Google Firebase integration

```
// authenticate to firebase
implementation 'com.google.firebase:firebase-auth:19.2.0'
implementation 'com.google.android.gms:play-services-auth:17.0.0'
// database to storage message
implementation 'com.google.firebase:firebase-database:19.2.0'
```

To detail: <https://firebase.google.com/docs/android/setup>

Following code shows the chat integration into our sample app.

```java
    private void setupChatConnection() {
        if (liveEntity != null) {
            FirebaseDatabase database = FirebaseDatabase.getInstance();
            DatabaseReference reference = database.getReference(liveEntity.getId());

            reference.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    Timber.d("SUCCESS!");
                    handleReturn(dataSnapshot);
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    Timber.e("ERROR: %s", databaseError.getDetails());
                }
            });
        }
    }
```

## Conclusion

Our API provides simple and intuitive integration into any Android app. You can focus on your application and let Uiza do the hard work. The source code to this tutorial can be found here: [Github](https://github.com/uizaio/uiza-android-sdk-player/tree/v5)


# Versioning

Uiza API current version is 2020-05-07

When we release a new API version, by default, all requests to our backend will be served with the newest API specs. We tagged which version is the main version on our documentation page.

Now we still developing the backward-compatible way to make sure that your code will work fine when Uiza updates the API version. Because of the situation, when we make changes to the API, we release a new dated version, but to avoid breaking your code, we will inform you one month before the change by email.

Read our [Release notes](https://docs.uiza.io/api-upgrades/release-notes) to learn more about the new features we serve our customers, the bug fixes and how we improve our performance. Also, read the [API changelog](https://docs.uiza.io/api-upgrades/api-changelog) to stay up to date on the API changes.


# Live Entities

A **`live_entity`** contains the information required for Uiza to successfully allocate resources to power the `live_entity`'s live broadcasting sessions. You can reuse a `live_entity` and broadcast multiple live sessions sequentially.&#x20;

The API allows you to create, delete, reset your `ingest.key`, and update the `name` and `description` of the `live_entity`. Individual entities and a list of all your entities are retrievable via these APIs too.

### The live entity object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the live entity.

> **`name`** *string*
>
> The name of your live entity. (limit 100 characters)

> **`description`** *string*
>
> Describes the content of the live entity. Often useful for displaying to viewers. You could update this accordingly to suit different sessions of a single live entity.

> **`encoding_template`** *string*&#x20;
>
> Specify the template that our ingest server will process your stream source, from SD to Full-HD for the output singal. There are 4 values that Uiza currently support:
>
> `none` We keep the output stream same as your source.
>
> `sd` The output contains 1 video profile with 480p resolution.
>
> `hd` The output contains 2 video profile with 480p and 720p resolutions.
>
> `fhd` The output contains 3 video profile with 480p, 720p, and 1080p resolutions.

> **`ingest`** *array*
>
> Contains the information required to access to Uiza's ingest servers. Use the `key` and `url` to configure your broadcasting software.

> **`playback`** *object*
>
> Contains the playback URL for different streaming protocols including HLS fMP4 (`hls`) and MPEG-dash (`mpd`). Use this URL to configure your player to play the live stream.

> **`region`** *string*
>
> The geographical region where your live streams are broadcasted from. In case your region is not yet supported, try the nearest available one. Here are the regions that Uiza currently supports:
>
> `in-bangalore-1` Bangalore, India.
>
> `in-mumbai-1` Mumbai, India.
>
> `sg-singapore-1` Singapore

> **`status`** *string*
>
> Once the request to create a `live_entity` is received, Uiza will allocate resources in the requested `region`. While the process may take up to 1 minute, the `status` of the `live_entity` is `init`. This will be updated to `ready` once resources are successfully allocated and to `broadcasting` during a broadcasting session.

> **`dvr`** *string*
>
> Indicates whether Digital Video Record (DVR) is enabled for the `live_entity`. Set to `true` to enable and to `false` to disable this feature.

> **`relay`** *array*
>
> A list of ingesting object contains the information required to access to 3rd ingest servers. Use the `key` and `url` to configure your broadcasting destination. Uiza will relay your signal to our server to list of ingest servers in `relay` array.

> **`created_at`** *string*
>
> The timestamp, at which the `live_entity` is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `live_entity` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Create a live entity

To start live streaming, you need to create an Entity object. Once the request is received, Uiza will allocate resources to serve your live stream.

## /v1/live-entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities`

#### Request Body

| Name               | Type    | Description                                                                                                                                                  |
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| name               | string  | The entity's name.                                                                                                                                           |
| description        | string  | An arbitrary string attached to the object. Often useful for displaying to users.                                                                            |
| dvr                | boolean | Indicates whether Digital Video Record (DVR) is enabled for the live\_entity. Set as `true` to enable and as `false` to disable. The default value is false. |
| encoding\_template | string  | Indicates whether encoding mode is enabled for the live\_entity. Set as `sd, hd` or `fhd` to enable and as `none` to disable.                                |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "Test event without encoding",
    "description": "Event for Test",
    "region": "in-bangalore-1",
    "status": "init",
    "dvr": false,
    "encoding_template": "none",
    "ingest": null,
    "playback": null,
    "relay": [],
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="Missing region" %}

```
{
  "message": "Your request is missing region parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="Invalid region" %}

```
{
  "message": "The requested region is invalid. See the list of available regions here: docs.uiza.io/getting-started/regions.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-live/owner/v1/live-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>' \
--data-raw '{
    "name": "Test event with encoding",
    "description": "Event for Test",
    "encoding_template": "sd"
}'
```

{% endcode %}


# Retrieve a live entity

Retrieves the details of an existing Live Entity. The entity’s id that was returned upon entity creation is required for identifying the exact live entity to be retrieved.

## /v1/live-entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                        |
| ---- | ------ | -------------------------------------------------- |
| id   | string | The identifier of your live entity to be retrieved |

{% tabs %}
{% tab title="200 Live entity successfully retrieved." %}

```
{
  "data": {
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Demo app 1",
    "description": "Demo application for documentation",
    "dvr": true,
    "encoding_template": "hd",
    "ingest": {
      "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "region": "in-mumbai-1",
    "relay": [
      {
        "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
        "name": "Replay name3333",
        "url": "rtmp://a.rtmp.youtube.com/live2",
        "key": "0df3-76bz-6t4r-1by5xxxxxx",
        "status": "enable",
        "created_at": "2020-06-24T16:25:58Z",
        "updated_at": "2020-06-24T16:25:58Z"
      }
    ],
    "status": "ready",
    "created_at": "2020-03-10T03:20:37.202Z",
    "updated_at": "2020-03-10T03:20:37.202Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```http
curl -X GET https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Update a live entity

Updates a specified live entity's name, description, dvr setting.

## /v1/live-entities/:id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                      |
| ---- | ------ | ------------------------------------------------ |
| id   | string | The identifier of the live entity to be updated. |

#### Request Body

| Name        | Type    | Description                                                                                                                                                                                                              |
| ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| dvr         | boolean | Indicates whether Digital Video Record (DVR) is enabled for the live\_entity. Set as `true` to enable and as `false` to disable.                                                                                         |
| name        | string  | The new name of live entity to be updated. This parameter cannot be empty in your body request.                                                                                                                          |
| description | string  | The new description of the live entity to be updated. This version does not support update description as an empty string, in case your old description is incorrect, replace it with the new one that makes more sense. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Test Event Updated",
    "description": "Event for Test",
    "ingest": {
      "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "relay": [
      {
        "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
        "name": "Replay name3333",
        "url": "rtmp://a.rtmp.youtube.com/live2",
        "key": "0df3-76bz-6t4r-1by5xxxxxx",
        "status": "enable",
        "created_at": "2020-06-24T16:25:58Z",
        "updated_at": "2020-06-24T16:25:58Z"
      }
    ],
    "preset": null,
    "region": "in-bangalore-1",
    "status": "ready",
    "dvr": false,
    "encode": false,
    "created_at": "2019-12-11T02:47:04Z",
    "updated_at": "2019-12-16T02:53:30Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X PUT https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "Test Event Updated", "description": "Event for Test"}'
```

{% endcode %}


# Delete a live entity

Permanently deletes a live entity. You need to stop broadcasting from your end to be able to delete a live entity. Once a live entity is deleted, it cannot be undone.

## /v1/live-entities/:id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id`

#### Path Parameters

| Name | Type   | Description                                    |
| ---- | ------ | ---------------------------------------------- |
| id   | string | The identifier if the live event to be deleted |

{% tabs %}
{% tab title="200 " %}

```
{}
```

{% endtab %}

{% tab title="400 " %}

```
{
  "message": "The live entity is fail on allocating resource and will be deleted by system.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 Could not find a cake matching this query." %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="409 " %}
{% tabs %}
{% tab title="Delete a broadcasting entity" %}

```
{
  "message": "The live entity is broadcasting and could not be deleted. Please, stop the live session and try again.",
  "error_type": "video_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X DELETE https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# List all live entities

Returns a list of existing live entities in descending order by creation date (the most recently created one is on top)

## /v1/live-entities

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities`

#### Query Parameters

| Name  | Type   | Description                                                     |
| ----- | ------ | --------------------------------------------------------------- |
| limit | number | The maximum number of objects to be returned, between 1 and 20. |
| page  | string | The pagination number of the result page to be retrieved.       |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "items": [
      {
        "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
        "name": "Demo app 1",
        "description": "Demo application for documentation",
        "dvr": true,
        "encoding_template": "none",
        "ingest": {
          "url": "rtmp://f45dd07a0e-in.uizadev.io/transcode",
          "key": "live_TB62vHgxSY"
        },
        "playback": {
          "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
          "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
        },
        "region": "in-mumbai-1",
        "relay": [
          {
            "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
            "name": "Replay name3333",
            "url": "rtmp://a.rtmp.youtube.com/live2",
            "key": "0df3-76bz-6t4r-1by5xxxxxx",
            "status": "enable",
            "created_at": "2020-06-24T16:25:58Z",
            "updated_at": "2020-06-24T16:25:58Z"
          }
        ],
        "status": "ready",
        "created_at": "2020-03-10T03:20:37.202Z",
        "updated_at": "2020-03-10T03:20:37.202Z"
      }
    ],
    "total": 99
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X GET https://api.uiza.io/api-live/owner/v1/live-entities 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Create a live relay

A Relay is ingesting object that contains the information required to access 3rd ingest servers (a.k.a RTMP/broadcast destination). Use the key and url to configure it.

## /v1/live-entities/:id/relays

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays`

#### Path Parameters

| Name | Type   | Description                                                               |
| ---- | ------ | ------------------------------------------------------------------------- |
| id   | String | The identifier of the live entity you want to create a new relay into it. |

#### Request Body

| Name | Type   | Description                                                                             |
| ---- | ------ | --------------------------------------------------------------------------------------- |
| name | String | The name of your broadcast destination.                                                 |
| url  | string | The new RTMP server endpoint to be updated, make sure it included the `rtmp://` prefix. |
| key  | string | The key of your new RTMP server that you want the live entity relay to.                 |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
    "name": "Replay name3333",
    "url": "rtmp://a.rtmp.youtube.com/live2",
    "key": "0df3-76bz-6t4r-1by5xxxxxx",
    "status": "enable",
    "created_at": "2020-06-24T16:25:58Z",
    "updated_at": "2020-06-24T16:25:58Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
The relay information is included in a [live entity](/2022-06-06/api-reference/live-entities).
{% endhint %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "A Relay Updated", "url": "rtmp://youtu.be/live", "key": "test-key"}'
```

{% endcode %}


# Update a live relay

## /v1/live-entities/:id/relays/:relay\_id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays/:relay_id`

#### Path Parameters

| Name      | Type   | Description                                               |
| --------- | ------ | --------------------------------------------------------- |
| id        | string | The identifier of the live entity you want to be updated. |
| relay\_id | string | The identifier of the relay object.                       |

#### Request Body

| Name | Type   | Description                                                                             |
| ---- | ------ | --------------------------------------------------------------------------------------- |
| name | string | The new name of relay to be updated.                                                    |
| url  | string | The new RTMP server endpoint to be updated, make sure it included the `rtmp://` prefix. |
| key  | string | The key of your new RTMP server that you want the live entity relay to.                 |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "8cf47749-1fa4-40e9-8303-580b34f14683",
    "name": "Replay name3333",
    "url": "rtmp://a.rtmp.youtube.com/live2",
    "key": "0df3-76bz-6t4r-1by5xxxxxx",
    "status": "enable",
    "created_at": "2020-06-24T16:25:58Z",
    "updated_at": "2020-06-24T16:25:58Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X PUT https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays/8cf47749-1fa4-40e9-8303-580b34f14683 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive' 
    -d '{"name": "A Relay Updated", "url": "rtmp://youtu.be/live", "key": "test-key"}'
```

{% endcode %}


# Delete a live relay

## /v1/live-entities/:id/relays/:relay\_id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-live/owner/v1/live-entities/:id/relays/:relay_id`

#### Path Parameters

| Name      | Type   | Description                                               |
| --------- | ------ | --------------------------------------------------------- |
| id        | string | The identifier of the live entity you want to be updated. |
| relay\_id | string | The identifier of the relay object.                       |

{% tabs %}
{% tab title="200 " %}

```
{}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="404 " %}

```
{
  "message": "The live entity you requested does not exist.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X DELETE https://api.uiza.io/api-live/owner/v1/live-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/relays/8cf47749-1fa4-40e9-8303-580b34f14683 
    -H 'Accept: */*' 
    -H 'Authorization: <token>' 
    -H 'uiza-app-id: <your_app_id>' 
    -H 'Cache-Control: no-cache' 
    -H 'Connection: keep-alive'
```

{% endcode %}


# Video Entities

A **`video_entity`** is created every time a video is uploaded to Uiza via a URL which redirects Uiza to your video storage to retrieve the video file. This URL could be either a *direct HTTP/HTTPS* link or a URL that leads to your *FTP or S3 storage*.&#x20;

Once the video has been successfully retrieved, Uiza transcodes the file into several renditions that have different resolutions and are compatible to different streaming protocol such as *HLS, fMP4*... These renditions are made available to your viewers by you publishing them to Uiza's *Content Delivery Network (CDN)* via Uiza APIs.

The APIs allow you to create, delete, publish, update the information of the video\_entities and retrieve your entities individually or collectively.

### The video entity object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the video entity.

> **`name`** *string*
>
> The name of your video entity.

> **`description`** *string*
>
> Describes the content of the video entity. Often useful for displaying to viewers.

> **`input_url`** *string*
>
> The source file URL of the video entity.

> **`encoding_template`** *string*&#x20;
>
> Specify the template that our ingest server will process your stream source, from SD to Full-HD for the output singal. There are 4 values that Uiza currently support:
>
> `none` We keep the output stream same as your source.
>
> `sd` The output contains 1 video profile with 480p resolution.
>
> `hd` The output contains 2 video profile with 480p and 720p resolutions.
>
> `fhd` The output contains 3 video profile with 480p, 720p, and 1080p resolutions.

> **`status`** *string*
>
> The status indicates whether your video entity had been published to Uiza's CDN or not. There are 4 possible statuses:
>
> > **`processing`** is returned when your video entity is in the queue to be published.
> >
> > **`ready`** is returned when your video entity has been successfully published and your viewers are able to watch the video.
> >
> > **`error`** is returned when something goes wrong during the publishing process of your video entity.

> **`playback`** *object*
>
> Contains the playback URL for different streaming protocols including HLS fMP4 (`hls`), and MPEG-dash (`dash`). Use this URL to configure your player to play the video.

> **`created_at`** *string*
>
> The timestamp, at which the `video_entity` is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `video_entity` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Create a video entity

To create your video streaming, you need to create an Entity object.

## /v1/video-entities

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities`

#### Request Body

| Name                                   | Type   | Description                                                                                                                   |
| -------------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------- |
| name<mark style="color:red;">\*</mark> | string | The entity's name.                                                                                                            |
| description                            | string | An arbitrary string attached to the object. Often useful for displaying to users.                                             |
| encoding\_template                     | string | Indicates whether encoding mode is enabled for the live\_entity. Set as `sd, hd` or `fhd` to enable and as `none` to disable. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    "content_policy": "public",
    "status": "processing",
    "playback": null,
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>' \
--data-raw '{
    "name": "My video 1",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd"
}'
```

{% endcode %}


# Retrieve a video entity

Retrieves the details of an existing Video Entity. The entity’s id that was returned upon entity creation is required for identifying the exact live entity to be retrieved.

## /v1/video-entities/:id

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                         |
| ---------------------------------- | ------ | --------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be retrieved |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    "content_policy": "public",
    "status": "ready",
    "playback": {
      "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
      "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Update a video entity

Updates a specified Video entity's name, description,...

## /v1/video-entities/:id

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                       |
| ---------------------------------- | ------ | ------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be updated |

#### Request Body

| Name        | Type   | Description                                                                                                                                                                                                                      |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name        | String | The new name of the video entity is to be updated. This parameter cannot be empty in your body request.                                                                                                                          |
| description | String | The new description of the video entity is to be updated. This version does not support updating a description as an empty string, in case your old description is incorrect, replace it with the new one that makes more sense. |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
    "name": "My video 1",
    "description": "Oops",
    "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
    "encoding_template": "hd",
    content_policy: "public",
    "status": "ready",
    "playback": {
      "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
      "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
    },
    "created_at": "2020-03-23T07:22:34Z",
    "updated_at": "2020-03-23T07:22:34Z"
  }
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request PUT 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Delete a video entity

Permanently deletes a video entity. Once a video entity is deleted, it cannot be undone.

## /v1/video-entities/:id

<mark style="color:red;">`DELETE`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities/:id`

#### Path Parameters

| Name                               | Type   | Description                                       |
| ---------------------------------- | ------ | ------------------------------------------------- |
| <mark style="color:red;">\*</mark> | String | The identifier of your video entity to be deleted |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {}
}
```

{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request DELETE 'https://api.uiza.io/api-vod/owner/v1/video-entities/22013d8a-d5fa-48f0-9a63-1f471ca9e81d' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# List all video entities

Returns a list of existing Video entities in descending order by creation date (the most recently created one is on top)

## /v1/video-entities

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-vod/owner/v1/video-entities`

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "items": [
      {
        "id": "2b970a39-874a-4d2a-be8a-fd445646d74c",
        "name": "My video 1",
        "description": "Oops",
        "input_url": "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
        "encoding_template": "hd",
        "content_policy": "public",
        "status": "ready",
        "playback": {
          "dash": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/manifest.mpd?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=1dxLAz2ZOX59Qj0w3h5paUmc2Cw",
          "hls": "https://vod.gcpsg.uizadev.io/videoplayback0/7cdaa860-808f-40b5-832e-2f90dd46fb19/b38669d1-f5fd-495e-8d78-3b59c0b6f180/master.m3u8?Expires=1649422743&KeyName=development-snake-vod-private-sg-signature&Signature=ZGInxqY3no1265MUuap8WiARj6I"
        },
        "created_at": "2020-03-23T07:22:34Z",
        "updated_at": "2020-03-23T07:22:34Z"
      }
    ]
  }
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing name" %}

```
{
  "message": "Your request is missing name parameter. Please, verify and resubmit.",
  "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
  "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
  "error_type": "invalid_request_error"
}5
```

{% endtab %}

{% tab title="500 " %}

```
{
  "message": "An unexpected error occurred on Uiza's end.",
  "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl --location --request POST 'https://api.uiza.io/api-vod/owner/v1/video-entities' \
--header 'Authorization: <token>' \
--header 'uiza-app-id: <your_app_id>'
```

{% endcode %}


# Events

Uiza  creates **`event`** objects containing data of the events occurred in your Uiza account that your applications might be interested in, for instance, a `live_entity` is created, a `ingest.key` is reset or a `video_entity` is deleted, etc.&#x20;

While some API requests do not cause any `event` to be created such as *Retrieve a live entity*, other APIs may generate more than one `event`. For example, when you create a live entity, a `live_entity.created`, a `live_entity.resource.accepted` and a `live_entity.ready` events will be created consecutively.

Fundamentally, an `event` is created whenever there is a change in the state of an API resource. Therefore, there are `events` created without the trigger of any API request. A `live_entity.publish` created when Uiza receives your live feed signal is triggered by your broadcasting software, not as the result of an API request.


# Event Types

Our event types are designed following the `resource.event` format for your intuitive coding. As new event types will be added as we roll out more features or make updates to existing ones, we recommend you to revisit this list whenever you receive a new event type.

#### Live entity and session related

> **`live_entities.created`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is created.

> **`live_entities.updated`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is updated.

> **`live_entities.deleted`**    *`data.object` is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity is deleted.

> **`live_entities.ready`**    *`data.object`* *is a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever the `status` of a live entity is changed to `ready`. This event indicates that the live entity you created is ready to ingest and broadcast.

> **`live_entities.publish`**    *`data.object`* *contains a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live entity receives the first live signal of a live session.

> **`live_entities.publish_done`**    *`data.object`* *contains a* [*`live_entity`*](broken://pages/-M2fvQqA5TyxMyGUAgw-)*.*
>
> Occurs whenever a live session ends.


# Webhook Endpoints

**Webhook** provides a mechanism for Uiza to notifies you about the `events` that happen in your Uiza account. When something interesting happens (a `live_entity` is created, a `ingest.key` is reset, a `video_entity` is deleted, etc.) Uiza creates an `event` object which contains the details of what just occurred. This `event` will then be sent to the webhook endpoint, a pre-configured URL where Uiza makes HTTP POST requests to.

A single `event` could be be sent to multiple webhook endpoints. You could generate endpoint URLs for your tests [here](https://webhook.site/).

### The webhook endpoint object

#### Attributes

> **`id`** *string*
>
> The unique identifier for the object.

> **`url`** *string*
>
> The URL of the `webhook_endpoint`.

> **`status`** *string*
>
> Indicates the current status of the `webhook_endpoint`, which is either `disabled` or `enabled`.

> **`signing_secret`** *string*
>
> SThe endpoint’s secret, used to generate webhook signature. Only returned at creation.

> **`event_type`** *array*
>
> The list of events to enable for this endpoint. `[’*’]` indicates that all events are enabled, except those that require explicit selection.

> **`created_at`** *string*
>
> The timestamp, at which the `webhook_endpoint`is created, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).

> **`updated_at`** *string*
>
> The timestamp, at which the most recent update to the `webhook_endpoint` occurred, follows the [ISO 8601 standard](https://www.w3.org/TR/NOTE-datetime-970915).


# Verifying signatures

The `Uiza-Signature` header included in each signed event contains a timestamp and one or more signatures. The timestamp is prefixed by `t=`, and each signature is prefixed by a *scheme*. Schemes start with `v`, followed by an integer. Currently, the only valid live signature scheme is `v1`

```
Uiza-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd
```

Note that newlines have been added for clarity, but a real `Uiza-Signature` header is on a single line.

Uiza generates signatures using a hash-based message authentication code ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) with [SHA-256](https://en.wikipedia.org/wiki/SHA-2). To prevent [downgrade attacks](https://en.wikipedia.org/wiki/Downgrade_attack), you should ignore all schemes that are not `v1`.

It is possible to have multiple signatures with the same scheme-secret pair. This can happen when you roll an endpoint’s secret from the Dashboard, and choose to keep the previous secret active for up to 24 hours. During this time, your endpoint has multiple active secrets and Uiza generates one signature for each secret.

Although it’s recommended to use our official libraries to verify webhook event signatures, you can create a custom solution by following these steps.

#### Step 1: Extract the timestamp and signatures from the header  <a href="#extract-timestamp" id="extract-timestamp"></a>

Split the header, using the `,` character as the separator, to get a list of elements. Then split each element, using the `=` character as the separator, to get a prefix and value pair.

The value for the prefix `t` corresponds to the timestamp, and `v1` corresponds to the signature (or signatures). You can discard all other elements.

#### Step 2: Prepare the `signed_payload` string  <a href="#prepare-payload" id="prepare-payload"></a>

The `signed_payload` string is created by concatenating:

* The timestamp (as a string)
* The character `.`
* The actual JSON payload (i.e., the request body)

#### Step 3: Determine the expected signature  <a href="#determine-expected-signature" id="determine-expected-signature"></a>

Compute an HMAC with the SHA256 hash function. Use the endpoint’s signing secret as the key, and use the `signed_payload` string as the message.

#### Step 4: Compare the signatures  <a href="#compare-signatures" id="compare-signatures"></a>

Compare the signature (or signatures) in the header to the expected signature. For an equality match, compute the difference between the current timestamp and the received timestamp, then decide if the difference is within your tolerance.

To protect against timing attacks, use a constant-time string comparison to compare the expected signature to each of the received signatures.

#### Code Example: Create a lib webhook.js file with content below

```javascript
'use strict';
const crypto = require('crypto');
const utils = {
  secureCompare: (a, b) => {
    a = Buffer.from(a);
    b = Buffer.from(b);
    if (a.length !== b.length) {
      return false;
    }
    if (crypto.timingSafeEqual) {
      return crypto.timingSafeEqual(a, b);
    }
    const len = a.length;
    let result = 0;
    for (let i = 0; i < len; ++i) {
      result |= a[i] ^ b[i];
    }
    return result === 0;
  },
}

const Webhook = {
  DEFAULT_TOLERANCE: 300, // 5 minutes
  constructEvent(payload, header, secret, tolerance) {
    this.signature.verifyHeader(
      payload,
      header,
      secret,
      tolerance || Webhook.DEFAULT_TOLERANCE
    );

    const jsonPayload = JSON.parse(payload);
    return jsonPayload;
  },

  /**
   * Generates a header to be used for webhook mocking
   *
   * @typedef {object} opts
   * @property {number} timestamp - Timestamp of the header. Defaults to Date.now()
   * @property {string} payload - JSON stringified payload object, containing the 'id' and 'object' parameters
   * @property {string} secret - Webhook secret 'webhook_...'
   * @property {string} scheme - Version of API to hit. Defaults to 'v1'.
   * @property {string} signature - Computed webhook signature
   */
};

const signature = {
  EXPECTED_SCHEME: 'v1',
  _computeSignature: (payload, secret) => {
    return crypto
      .createHmac('sha256', secret)
      .update(payload, 'utf8')
      .digest('hex');
  },

  verifyHeader(payload, header, secret, tolerance) {
    payload = Buffer.isBuffer(payload) ? payload.toString('utf8') : payload;
    if (Array.isArray(header)) {
      throw new Error(
        'Unexpected: An array was passed as a header, which should not be possible for the uiza-signature header.'
      );
    }

    header = Buffer.isBuffer(header) ? header.toString('utf8') : header;

    const details = parseHeader(header, this.EXPECTED_SCHEME);

    if (!details || details.timestamp === -1) {
      throw {message:'Unable to extract timestamp and signatures from header',name:'unable_to_extract_timestamp_and_signature_from_header'}
    }

    if (!details.signatures.length) {
      throw {message:'No signatures found with expected scheme',name:'signature_not_found'}
    }

    const expectedSignature = this._computeSignature(
      `${details.timestamp}.${payload}`,
      secret
    );

    const signatureFound = !!details.signatures.filter(
      utils.secureCompare.bind(utils, expectedSignature)
    ).length;
    if (!signatureFound) {
      throw { message: "No signatures found matching the expected signature for payload.", name: 'signature_not_found' }
    }

    const timestampAge = Math.floor(Date.now() / 1000) - details.timestamp;

    if (tolerance > 0 && timestampAge > tolerance) {
      throw {message:'Timestamp outside the tolerance zone',name:'timestamp_outside_zone'}
    }

    return true;
  },
};

function parseHeader(header, scheme) {
  if (typeof header !== 'string') {
    return null;
  }

  return header.split(',').reduce(
    (accum, item) => {
      const kv = item.split('=');

      if (kv[0] === 't') {
        accum.timestamp = kv[1];
      }

      if (kv[0] === scheme) {
        accum.signatures.push(kv[1]);
      }

      return accum;
    },
    {
      timestamp: -1,
      signatures: [],
    }
  );
}

Webhook.signature = signature;

module.exports = Webhook;
```

Verify

```javascript
    async (req,res)=>{
      const webhook = require('./webhook.js')
      const signature = req.headers['uiza-signature']
      const signing_secret = <Your signing_secret>
      const payload =req.body
      let payloadString = JSON.stringify(payload, null, 2)
      const event = webhook.constructEvent(payloadString, signature, signing_secret);
    }
```


# Create a webhook endpoint

A URL and a secret are required for webhook endpoint creation. While URLs are endpoints where Uiza sends the events to, secrets are used to generate webhook signatures.

## /v1/webhook

<mark style="color:green;">`POST`</mark> `https://api.uiza.io/api-account/owner/v1/webhook`

Set up your webhook endpoint to receive live events from Uiza

#### Headers

| Name           | Type   | Description                     |
| -------------- | ------ | ------------------------------- |
| Authentication | string | Authentication token or Api Key |

#### Request Body

| Name        | Type   | Description                                                                                                                                  |
| ----------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| url         | string | The URL of the webhook endpoint.                                                                                                             |
| event\_type | array  | The list of events to enable for this endpoint. `[’*’]` indicates that all events are enabled, except those that require explicit selection. |
| status      | string | The status of the webhook. It can be `enabled` or `disabled`.                                                                                |

{% tabs %}
{% tab title="200 Cake successfully retrieved." %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "signing_secret":"webhook_8fCc3HaU0a-aJT2szrU7",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}

> ```
> Sample Request
>
>
> curl --location --request POST 'https://api.uiza.io/api-account/owner/v1/webhook/'        
> --header 'Content-Type: application/json'  --header 'Authorization: '    
> --data-raw '{
>   "url": "https://uiza-example.com/webhook",
>   "status": "enabled",
>   "event_type": [
>     "live_entities.created"
>   ]
> }'
> ```

## /v1/webhook\_endpoints

<mark style="color:green;">`POST`</mark> `https://api.uiza.sh/v1/webhook_endpoints`

#### Request Body

| Name   | Type   | Description                                                                         |
| ------ | ------ | ----------------------------------------------------------------------------------- |
| secret | string | The token used to validate the communication between Uiza and the webhook endpoint. |
| url    | string | The URL of the webhook endpoint.                                                    |

{% tabs %}
{% tab title="200 " %}

```
{
 "id": "f0f207af-b338-4b7f-8d32-fe9cfa9566eb",
 "url": "https://webhook-test.com/live/created",
 "status": "enabled",
 "created_at": "2019-12-16T10:57:32Z",
 "updated_at": "2019-12-16T10:57:32Z"
}
```

{% endtab %}

{% tab title="400 " %}
{% tabs %}
{% tab title="Missing URL" %}

```
{
 "message": "Your request is missing url parameter. Please, verify and resubmit.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}
{% endtabs %}
{% endtab %}

{% tab title="401 " %}

```
{
 "message": "You are unauthorized to access the requested resource. Please verify and resubmit.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="409 " %}

```
{
 "message": "The requested app_id already registered with a webhook.",
 "error_type": "invalid_request_error"
}
```

{% endtab %}

{% tab title="500 " %}

```
{
 "message": "An unexpected error occurred on Uiza's end.",
 "error_type": "api_error"
}
```

{% endtab %}
{% endtabs %}

{% code title="Sample Request" %}

```
curl -X POST https://api.uiza.sh/v1/webhook_endpoints
     -H 'Authorization: uap-c1ffbff4db954ddcb050c6af0b43ba56-41193b64'
     -d '{"url": "https://webhook-test.com/live/created", "secret": "a-secret"}'
```

{% endcode %}


# Update a webhook endpoint

Updates the URL or secret of a webhook endpoint. You could also use this API to enable or disable your webhook endpoints. Any parameters not provided will be left unchanged.

## /v1/webhook/:id&#x20;

<mark style="color:orange;">`PUT`</mark> `https://api.uiza.io/api-account/owner/v1/webhook/:id`

#### Path Parameters

| Name | Type   | Description           |
| ---- | ------ | --------------------- |
| id   | string | The webhook entity id |

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

#### Request Body

| Name        | Type   | Description |
| ----------- | ------ | ----------- |
| event\_type | array  |             |
| status      | string |             |
| url         | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data":{
    "id":"e9d49e8e-4b9b-4693-974a-76e177edb21a"
  }
}
```

{% endtab %}
{% endtabs %}


# Get a webhook endpoint

## /v1/webhook/:id&#x20;

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-account/owner/v1/webhook/:id`

#### Path Parameters

| Name | Type   | Description           |
| ---- | ------ | --------------------- |
| id   | string | The webhook entity id |

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}


# List all webhook endpoint

## /v1/webhook

<mark style="color:blue;">`GET`</mark> `https://api.uiza.io/api-account/owner/v1/webhook`

#### Headers

| Name          | Type   | Description |
| ------------- | ------ | ----------- |
| Authorization | string |             |

{% tabs %}
{% tab title="200 " %}

```
{
  "data": {
    "event_type":["live_entities.created", "live_entities.ready"],
    "id":"960d2199-f8a2-4f68-99db-3a688bda5db1",
    "url":"https://uiza-example.com/webhook",
    "app_id":"095c81e1-8be8-46f1-9dcb-0f8ad54eac8a",
    "created_by":"fe57cb55-d73f-4a2a-ada6-280248e995af",
    "updated_at":"2021-09-07T14:22:23.183Z",
    "created_at":"2021-09-07T14:22:23.183Z"
  }
}
```

{% endtab %}
{% endtabs %}


# Introduction

{% content-ref url="/pages/-LxZwMIn5rPMsm9D2nrv" %}
[Android SDK](/2022-06-06/sdk-reference/android-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-LxZyPlIaA9pX\_2im0g\_" %}
[iOS SDK](/2022-06-06/sdk-reference/ios-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-LxRNC97ltOAoqq4CIFV" %}
[Web Player SDK](/2022-06-06/sdk-reference/web-player-sdk)
{% endcontent-ref %}


# Android SDK

## Welcome to Uiza Android SDK

Uiza provides Android SDKs for broadcasting and playback. The SDKs helps you set up your mobile application using Uiza's platform. You can start building your application on top and let Uiza handle the backbone of video and live streaming.

{% content-ref url="/pages/-M3\_4RDrQ-UwqSNON6AU" %}
[Android Player SDK](/2022-06-06/sdk-reference/android-sdk/android-player-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-M3\_6DPhhfxTUzRDy9Jd" %}
[Android Broadcast SDK](/2022-06-06/sdk-reference/android-sdk/android-broadcast-sdk)
{% endcontent-ref %}


# Android Player SDK

[![](https://camo.githubusercontent.com/d9251a4a27b44035616a8defef539fe459d66136/68747470733a2f2f6a69747061636b2e696f2f762f75697a61696f2f75697a612d616e64726f69642d706c617965722d73646b2e737667)](https://jitpack.io/#uizaio/uiza-android-player-sdk)

[![Play Store](https://camo.githubusercontent.com/e506ee96bbe6031926c6daebfaa3a07aebf8239b/68747470733a2f2f7777772e676f6f676c652e636f6d2f70686f746f732f61626f75742f7374617469632f696d616765732f62616467655f676f6f676c655f706c61795f333664702e737667)](https://play.google.com/store/apps/details?id=com.uiza.sampleplayer)

Link to the Source code here: <https://github.com/uizaio/snake.sdk.android-player>

## Welcome to UIZA Android Player SDK

Simple Streaming at scale.

Uiza is the complete toolkit for building a powerful video streaming application with unlimited scalability. We design Uiza so simple that you only need a few lines of codes to start streaming, but sophisticated enough for you to build complex products on top of it.

Read [CHANGELOG here](https://github.com/uizaio/uiza-android-sdk/blob/master/CHANGELOG.md).

## Importing the Library

**Step 1. Add the `JitPack` repository to your `build.gradle` file**

```
    allprojects {
          repositories {
             maven { url 'https://jitpack.io' }
          }
    }
```

**Step 2. Add the dependency**

```
    implementation 'com.github.uizaio:uiza-android-player-sdk:1.1.x'
```

For **Android Support Compat** (Support until January 2021)

```
    implementation 'com.github.uizaio:uiza-android-player-sdk:1.0.x'
```

Get latest release number [HERE](broken://pages/-M3_4hri1XaNb8ZQQSb3).

* Additionally, if you want to use the Chromecast feature, add the following dependencies to your project:

```
        // for ChromeCast
        implementation 'androidx.mediarouter:mediarouter:1.0.0'
        implementation 'com.google.android.gms:play-services-cast-framework:18.1.0'
```

if you use `android support compat`

```
        // for ChromeCast
        implementation 'com.android.support:mediarouter-v7:28.0.0'
        implementation 'com.google.android.gms:play-services-cast-framework:16.2.0' // from 17.x support androidx only
```

* If advertising support should be enabled, also add the following dependencies to your project:

```
        // for IMA Ads
        implementation 'com.google.android.exoplayer:extension-ima:2.10.8'
        implementation 'com.google.android.gms:play-services-ads:19.0.1' // from 18.x support androidx only
```

**Note:**

* The version of the ExoPlayer Extension IMA must match the version of the ExoPlayer library being used.
* If you are using both ChromeCast and IMA Ads dependencies, we recommend using dependency `com.google.android.gms:play-services-cast-framework:$version` with `version >= 18.1.0` or `version=16.2.0` (support compat) to avoid dependency version conflicts

Check [example here](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/build.gradle).

**Turn on Java 8 support**

If not enabled already, you need to turn on Java 8 support in all `build.gradle` files depending on ExoPlayer, by adding the following to the `android` section:

```
compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}
```

> Node, Inside v1:
>
> * Use [androidx](https://developer.android.com/jetpack/androidx)
> * Use [Timber](https://github.com/JakeWharton/timber) for logger

## Init SDK

1. Init UZPlayer

   ```
   public class App extends MultiDexApplication {
          @Override
          public void onCreate() {
              super.onCreate();
              UZPlayer.init();
          }
   }
   ```
2. If you want show log, install any `Tree` instances you want in the `onCreate` of your application class

```
	if (BuildConfig.DEBUG) {
            Timber.plant(new Timber.DebugTree());
        }
```

### Manifest

```
    <application
      android:name=".App"
    >
```

## How to play the video?:

**XML**

```
    <com.uiza.sdk.view.UZVideoView
      android:id="@id/uiza_video"
      android:layout_width="match_parent"
      android:layout_height="wrap_content" />
```

**JAVA**

```
Create java file MainActivity:

    public class MainActivity extends AppCompatActivity implements UZCallback {
       ...
    }
```

Manifest

```
    <activity
      android:name=".MainActivity "
      android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" />
```

In your `activity` or `fragment`

* Play with entity:

  ```
  uzVideo = (UZVideoView) findViewById(R.id.uiza_video);
  uzVideo.setUZCallback(this);
  uzVideo.play(UZPlayback playback);
  // or 
  UZPlayer.setCurrentPlayback(UZPlayback playback);
  uzVideo.play();
  // or playlist
  uzVideo.play(List<UZPlayback> playlist);
  ```

Don't forget to add in activity life cycle event:

```
    @Override
    public void onDestroy() {
        uzVideo.onDestroy();
        super.onDestroy();
    }

    @Override
    public void onResume() {
        uzVideo.onResume();
        super.onResume();
    }

    @Override
    public void onPause() {
        uzVideo.onPause();
        super.onPause();
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        uzVideo.onActivityResult(resultCode, resultCode, data);
        super.onActivityResult(requestCode, resultCode, data);
    }
```

## How to customize your skin?

Only 3 steps, you can customize everything about player skin.

**Step 1:** Create layout ***uzplayer\_skin\_custom.xml*** like [THIS](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/src/main/res/layout/uzplayer_skin_custom.xml):

Please note *`app:controller_layout_id="@layout/uz_controller_custom_layout"`*

**Step 2:** Create layout ***uz\_controller\_custom\_layout.xml*** like [THIS](https://github.com/uizaio/uiza-android-sdk/blob/master/sampleplayer/src/main/res/layout/uz_controller_custom_layout.xml):

* In this xml file, you can edit anything you like: position, color, drawable resouces...
* You can add more view (TextView, Button, ImageView\...).
* You can remove any component which you dont like.
* Please note: Don't change any view `id`s if you are using it.

**Step 3:** On function `onCreate()` of `Activity`, put this code:

```
    UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
```

Ex:

```
    @Override
    protected void onCreate(@Nullable Bundle savedState) {
		UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
        super.onCreate(savedState);
    }
```

**Note:** If you are using Chromecast, please use UZPlayer.setCasty(Activity activity) on function onCreate() of Activity

```
    @Override
    protected void onCreate(@Nullable Bundle savedState) {
        UZPlayer.setCasty(this);
        UZPlayer.setUZPlayerSkinLayoutId(R.layout.uzplayer_skin_custom);
        super.onCreate(savedState);
    }
```

Ex: findView from your custom layout:

```
    TextView tvSample = uzVideo.findViewById(R.id.tv_sample);
```

That's enough! This code above will change the player's skin quickly. You can build and run your app now.

But if you wanna change the player's skin when the player is playing, please you this function:

```
    uzVideo.changeSkin(R.layout.uzplayer_skin_custom);
```

***Note:***

* You should not change the id of the view. Ex: `android:id="@id/player_view"` Do not change `android:id="@id/player_view_0"` or `android:id="@+id/player_view_0"` ...

## Picture In Picture (PIP)

1. You can use `UZDragView`, review [`PlayerActivity`](https://github.com/uizaio/uiza-android-player-sdk/blob/master/sampleplayer/src/main/java/com/uiza/sampleplayer/PlayerActivity.java)
2. From `Android Nougat` (Android SDK >= 24) Google supported `PIP`. To implement, in `AndroidManifest.xml` add `android:supportsPictureInPicture="true"` inside `Your Activity` and review [`PIPPlayerActivity`](https://github.com/uizaio/uiza-android-player-sdk/blob/master/sampleplayer/src/main/java/com/uiza/sampleplayer/PipPlayerActivity.java).

## R8 / ProGuard

***Do not support R8***

```
    buildTypes {
    release {
        minifyEnabled true
        shrinkResources true
        useProguard true
        proguardFiles = [
            getDefaultProguardFile('proguard-android.txt'),
            'proguard-rules.pro'
        ]
    }
    }
```

## For contributors

Uiza Checkstyle configuration is based on the Google coding conventions from Google Java Style that can be found at [here](https://google.github.io/styleguide/javaguide.html).

Your code must be followed the rules that defined in our [`uiza_style.xml` rules](https://github.com/uizaio/uiza-android-player-sdk/tree/master/configs/codestyle/uiza_style.xml)

You can setting the rules after import project to Android Studio follow below steps:

1. **File** > **Settings** > **Editor** > **Code Style**
2. Right on the `Scheme`, select the setting icon > **Import Scheme** > **Intellij IDEA code style XML**
3. Select the `uiza_style.xml` file path
4. Click **Apply** > **OK**, then ready to go

For apply check style, install [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea), then

1. **File** > **Settings** > **Other Settings** > **Checkstyle**
2. In Configuration file, select the **`+`** icon
3. Check `Use local checkstyle file` & select path to `uiza_check.xml` file
4. Select **OK** & you're ready to go

To run checkstyle for project

1. Right click on project
2. Select **Analyze** > **Inspect Code**

## Reference

[API Reference](https://uizaio.github.io/uiza-android-player-sdk/)

## Supported devices

Support all devices which have ***Android 5.0 (API level 21) above.*** For a given use case, we aim to support UizaSDK on all Android devices that satisfy the minimum version requirement.

**Note:** Some Android emulators do not properly implement components of Android’s media stack, and as a result do not support UizaSDK. This is an issue with the emulator, not with UizaSDK. Android’s official emulator (“Virtual Devices” in Android Studio) supports UizaSDK provided the system image has an API level of at least 23. System images with earlier API levels do not support UizaSDK. The level of support provided by third party emulators varies. Issues running UizaSDK on third party emulators should be reported to the developer of the emulator rather than to the UizaSDK team. Where possible, we recommend testing media applications on physical devices rather than emulators.

## Error message

Check this [class](https://github.com/uizaio/uiza-android-sdk/blob/master/uzplayer/src/main/java/com/uiza/sdk/exceptions/ErrorConstant.java) you can know error code and error message when use UZPlayer.

## Support

If you've found an error in this sample, please file an [issue](broken://pages/-M3_4hr_f9wc2YPGPtTI)

Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub. Please feel free to contact me anytime: <developer@uiza.io> for more details.

Address: *33 Ubi Avenue 3 #08- 13, Vertex Tower B, Singapore 408868* Email: [*developer@uiza.io*](mailto:developer@uiza.io) Website: [*uiza.io*](https://uiza.io/)

## License

UizaSDK is released under the BSD license. See [LICENSE](broken://pages/-M3_4hrkOaxtHSZEy18S) for details.


# Android Broadcast SDK

[![](https://camo.githubusercontent.com/9fa439d7b71a2a098a51dbe19a5c5b45e7074766/68747470733a2f2f6a69747061636b2e696f2f762f75697a61696f2f75697a612d616e64726f69642d62726f6164636173742d73646b2e737667)](https://jitpack.io/#uizaio/uiza-android-broadcast-sdk)

[![Play Store](https://camo.githubusercontent.com/e506ee96bbe6031926c6daebfaa3a07aebf8239b/68747470733a2f2f7777772e676f6f676c652e636f6d2f70686f746f732f61626f75742f7374617469632f696d616765732f62616467655f676f6f676c655f706c61795f333664702e737667)](https://play.google.com/store/apps/details?id=io.uiza.samplelive)

Link to the Source code here: <https://github.com/uizaio/snake.sdk.android-broadcast>

## Welcome to UIZA Android BroadCast SDK

Simple Streaming at scale.

Uiza is the complete toolkit for building a powerful video streaming application with unlimited scalability. We design Uiza so simple that you only need a few lines of codes to start streaming, but sophisticated enough for you to build complex products on top of it.

Read [CHANGELOG here](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/CHANGELOG.md).

## Importing the Library

**Step 1. Add the `JitPack` repository to your `build.gradle` file**

```
    allprojects {
          repositories {
             maven { url 'https://jitpack.io' }
          }
    }
```

**Step 2. Add the dependency**

```
    dependencies {
        implementation 'com.github.uizaio:uiza-android-broadcast-sdk:1.x.x'
    }
```

Get latest release number [HERE](broken://pages/-M3_6LKWh2CULmgDc05U).

**Turn on Java 8 support**

If not enabled already, you need to turn on Java 8 support in all `build.gradle` files depending on ExoPlayer, by adding the following to the `android` section:

```
compileOptions {
  targetCompatibility JavaVersion.VERSION_1_8
}
```

## Init SDK

. If you want show log, install any `Tree` instances you want in the `onCreate` of your application class

```
if (BuildConfig.DEBUG) {
        Timber.plant(new Timber.DebugTree());
    }
```

## How to broadcast with UZBroadCast?:

It's very easy, plz follow these steps below to implement:

XML:

```
<com.uiza.sdk.view.UZBroadCastView
    android:id="@+id/uz_broadcast"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:runInBackground="true" # support camera2 only
    app:startCamera="FRONT"
    app:useCamera2="true" />
```

In class [`UZBroadCastActivity`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/samplebroadcast/src/main/java/com/uiza/samplebroadcast/UZBroadCastActivity.java):

```
    public class UZBroadCastActivity extends AppCompatActivity implements UZBroadCastListener {
        // ...
    }
```

In `onCreate()`:

```
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
    uzBroadCast = (UZBroadCastView) findViewById(R.id.uz_broadcast);
    uzBroadCast.setUZBroadcastListener(this);
```

In `onResume()`:

```
    @Override
    protected void onResume() {
        uzBroadCast.onResume();
        super.onResume();
    }
```

Start a Stream: see [`VideoAttributes`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/uzbroadcast/src/main/java/com/uiza/sdk/profile/VideoAttributes.java) and [`AudioAttributes`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/uzbroadcast/src/main/java/com/uiza/sdk/profile/AudioAttributes.java)

```
    uzBroadCast.setVideoAttributes(VideoAttributes videoAttrs);
    uzBroadCast.setAudioAttributes(AudioAttributes audioAttrs);
    if (uzBroadCast.prepareBroadCast()) {
        uzBroadCast.startBroadCast("broadCastUrl");
    }
```

or

```
    if (uzBroadCast.prepareBroadCast(AudioAttributes audioAttrs, VideoAttributes videoAttrs, boolean isLandscape)) {
        uzBroadCast.startBroadCast("broadCastUrl");
    }
```

Stop streaming (It auto saves mp4 file in your gallery if you start a broadcast with option save local file)

```
    uzBroadCast.stopBroadCast();
```

Switch camera:

```
    uzBroadCast.switchCamera();
```

In case `runInBackground = false` But you want to allows streaming again after back from background:

```
    uzBroadCast.setBackgroundAllowedDuration(YOUR_ALLOW_TIME); // default time is 2 minutes
```

This sample help you know how to use all Uiza SDK for livestream, please refer to [THIS](broken://pages/-M3_6LKhguttfwbnc7Mp)

## How to broadcast your screen?

See example in class [`UZDisplayActivity`](https://github.com/uizaio/uiza-android-broadcast-sdk/blob/master/samplebroadcast/src/main/java/com/uiza/samplebroadcast/UZDisplayActivity.java):

## For contributors

Uiza Checkstyle configuration is based on the Google coding conventions from Google Java Style that can be found at [here](https://google.github.io/styleguide/javaguide.html).

Your code must be followed the rules that defined in our [`uiza_style.xml` rules](https://github.com/uizaio/uiza-android-broadcast-sdk/tree/master/configs/codestyle/uiza_style.xml)

You can setting the rules after import project to Android Studio follow below steps:

1. **File** > **Settings** > **Editor** > **Code Style**
2. Right on the `Scheme`, select the setting icon > **Import Scheme** > **Intellij IDEA code style XML**
3. Select the `uiza_style.xml` file path
4. Click **Apply** > **OK**, then ready to go

For apply check style, install [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea), then

1. **File** > **Settings** > **Other Settings** > **Checkstyle**
2. In Configuration file, select the **`+`** icon
3. Check `Use local checkstyle file` & select path to `uiza_check.xml` file
4. Select **OK** & you're ready to go

To run checkstyle for project

1. Right click on project
2. Select **Analyze** > **Inspect Code**

## Reference

[API Reference](https://uizaio.github.io/uiza-android-broadcast-sdk/)

## Supported devices

Support all devices which have ***Android 5.0 (API level 21) above.*** For a given use case, we aim to support UizaSDK on all Android devices that satisfy the minimum version requirement.

**Note:** Some Android emulators do not properly implement components of Android’s media stack, and as a result do not support UizaSDK. This is an issue with the emulator, not with UizaSDK. Android’s official emulator (“Virtual Devices” in Android Studio) supports UizaSDK provided the system image has an API level of at least 23. System images with earlier API levels do not support UizaSDK. The level of support provided by third party emulators varies. Issues running UizaSDK on third party emulators should be reported to the developer of the emulator rather than to the UizaSDK team. Where possible, we recommend testing media applications on physical devices rather than emulators.

## Support

If you've found an error in this sample, please file an [issue](broken://pages/-M3_6LKMJ7ptC5yTfrFY)

Patches are encouraged, and may be submitted by forking this project and submitting a pull request through GitHub. Please feel free to contact me anytime: <developer@uiza.io> for more details.

Address: *33 Ubi Avenue 3 #08- 13, Vertex Tower B, Singapore 408868* Email: [*developer@uiza.io*](mailto:developer@uiza.io) Website: [*uiza.io*](https://uiza.io/)

## License

UizaSDK is released under the BSD license. See [LICENSE](broken://pages/-M3_6LKY5iUHzNst8gRl) for details.


# iOS SDK

## Welcome to Uiza iOS SDK

Uiza provides iOS SDKs for broadcasting and playback. The SDKs helps you set up your mobile application using Uiza's platform. You can start building your application on top and let Uiza handle the backbone of video and live streaming.

{% content-ref url="/pages/-M3dAL50BcNrgonhZ-Sz" %}
[iOS Player SDK](/2022-06-06/sdk-reference/ios-sdk/ios-player-sdk)
{% endcontent-ref %}

{% content-ref url="/pages/-M3dAJ1BXOA4b5dSA6KQ" %}
[iOS Broadcast SDK](/2022-06-06/sdk-reference/ios-sdk/ios-broadcast-sdk)
{% endcontent-ref %}


# iOS Player SDK

&#x20;[![Swift](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)

UZPlayer is a framework allows you to play video with fully customizable controls.

Link to the Source code here: <https://github.com/uizaio/snake.sdk.ios-player>

## Compatibility

UZPlayer requires Swift 4.2+ and iOS 9+

## Installation

### CocoaPods

To integrate UZPlayer into your Xcode project using [CocoaPods](http://cocoapods.org/), specify it in your `Podfile`:

Then run the following command:

## Usage

```
let playerViewController = UZPlayerViewController()		
playerViewController.player.controlView.theme = UZTheme1()
playerViewController.player.loadVideo(url: VIDEO_URL)
present(playerViewController, animated: true, completion: nil)
```

You might have to add these lines to `Info.plist` to disable App Transport Security (ATS) to be able to play video:

```
<key>NSAppTransportSecurity</key>  
<dict>  
  <key>NSAllowsArbitraryLoads</key><true/>  
</dict>
```

## Change Player Themes

```
let playerViewController = UZPlayerViewController()
playerViewController.player.controlView.theme = UZTheme1()
```

UizaPlayer currently has 7 built-in themes:

[UZTheme1](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme1.jpg)

[UZTheme2](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme2.jpg)

[UZTheme3](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme3.jpg)

[UZTheme4](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme4.jpg)

[UZTheme5](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme5.jpg)

[UZTheme6](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme6.jpg)

[UZTheme7](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/themes/theme7.jpg)

## Create CustomTheme

You can create your own custom theme by creating a class inheriting from [UZPlayerTheme Protocol](https://uizaio.github.io/uiza-sdk-player-ios/Protocols/UZPlayerTheme.html) following this template: [UZCustomTheme](https://github.com/uizaio/uiza-sdk-player-ios/blob/master/themes/UZCustomTheme.swift)

You can also create your custom end screen by subclassing `UZEndscreenView`, then set an instance to `player.controlView.endscreenView`

```
self.playerViewController.player.controlView.endscreenView = MyCustomEndScreen()
```

## Create Player with Floating Mode

You can create player with "drag down to floating mode" like Facebook or Youtube, by subclassing [UZFloatingPlayerViewController](https://uizaio.github.io/uiza-sdk-player-ios/Classes/UZFloatingPlayerViewController.html), then you can add more UI for displaying video details and add them to `detailsContainerView`

Then present using this code:

```
UZFloatingPlayerViewController().present(with: videoItem, playlist: playlist)
```

See [Example](https://github.com/uizaio/uiza-ios-player-sdk/blob/master/UZPlayerExample)

For API details, check [API Document](https://uizaio.github.io/uiza-ios-player-sdk/)

## Google ChromeCast supports

If developing using Xcode 10 and targeting iOS devices running iOS 12 or higher, the "Access WiFi Information" capability is required in order to discover and connect to Cast devices [![](https://camo.githubusercontent.com/2afb576154d43dfaa77113c9c6ed95a82a4aeea7/68747470733a2f2f646576656c6f706572732e676f6f676c652e636f6d2f636173742f696d616765732f78636f64655f776966695f6361706162696c6974795f6572726f722e706e67)](https://camo.githubusercontent.com/2afb576154d43dfaa77113c9c6ed95a82a4aeea7/68747470733a2f2f646576656c6f706572732e676f6f676c652e636f6d2f636173742f696d616765732f78636f64655f776966695f6361706162696c6974795f6572726f722e706e67)

## Support

<namnh@uiza.io>

## License

UZPlayer is released under the BSD license. See [LICENSE](https://github.com/uizaio/uiza-sdk-player-ios/blob/master/LICENSE) for details.


# iOS Broadcast SDK

[![Swift](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)](https://camo.githubusercontent.com/066a529725eadc4f422543c3500d924fe5dfc6e1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f253230696e2d7377696674253230352e302d6f72616e67652e737667)

UZBroadcast is a framework helps you to broadcast livestream

Link to the Source code here: <https://github.com/uizaio/snake.sdk.ios-broadcast>

## Compatibility

UZBroadcast requires Swift 4.2+ and iOS 9+

## Installation

### CocoaPods

To integrate UZBroadcast into your Xcode project using [CocoaPods](http://cocoapods.org/), specify it in your `Podfile`:

Then run the following command:

## Livestream

```
let broadcaster = UZBroadcastViewController()
let config = UZBroadcastConfig(cameraPosition: .front, videoResolution: ._720, videoBitrate: ._3000, videoFPS: ._30, audioBitrate: ._128Kbps, audioSampleRate: ._44_1khz, adaptiveBitrate: true)
broadcaster.prepareForBroadcast(withConfig: config)
//...
broadcaster.startBroadcast(broadcastURL: BROADCAST_URL)
present(broadcaster, animated: true, completion: nil)
```

## Screen broadcast

```
let broadcaster = UZScreenBroadcast.shared
let config = UZBroadcastConfig(cameraPosition: .front, videoResolution: ._720, videoBitrate: ._3000, videoFPS: ._30, audioBitrate: ._128Kbps, audioSampleRate: ._44_1khz, adaptiveBitrate: true)
broadcaster.prepareForBroadcast(withConfig: config)s
broadcaster.isMicrophoneEnabled = true
//broadcaster.isCameraEnabled = true
broadcaster.startBroadcast(broadcastURL: BROADCAST_URL)
```

Remember to add these usage description keys into `Info.plist` file:

```
<key>NSCameraUsageDescription</key>
<string>App needs access to camera for broadcasting</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs access to microphone for broadcasting</string>
```

## Reference

[API Reference](https://uizaio.github.io/uiza-ios-broadcast-sdk/)

## Support

<namnh@uiza.io>

## License

UZBroadcast is released under the BSD license. See [LICENSE](https://github.com/uizaio/uiza-sdk-broadcast-ios/blob/master/LICENSE) for details.


# Web Player SDK

## How to use Uiza's webSDK

1. Include css, js into html:

```
<!-- 1. Include UIZA library. -->
<link href='https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.css' rel='stylesheet' crossorigin='anonymous'> <!-- route to uiza.css -->
<script src='https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.min.js' crossorigin='anonymous'></script> <!-- route to uiza.min.js -->
```

&#x20;2\. The video player will prepend the player into this \<div> tag:

```
<video id='playerUiza' crossorigin playsinline autoplay muted></video>
```

&#x20;3\. This code creates an UIZA player:

```
<script>
  var videoSrc = "UIZA_PLAY_BACK_LINK"; // This may be PLAY_BACK_LINK (hls or dash)
  window.UZPlayer = new Uiza(document.getElementById("playerUiza"), {
    src: videoSrc,
  });
</script> 
```

4\. Full code example:

```
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <title></title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <style>
      body {
        margin: 0;
        padding: 0;
      }
    </style>
    <link
      href="https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.css"
      rel="stylesheet"
      crossorigin="anonymous"
    />
    <script
      src="https://cdn.jsdelivr.net/npm/@uizaio/playerjs@5.20.7-rc8/dist/uiza.min.js"
      crossorigin="anonymous"
    ></script>
  </head>
  <body>
    <video id="playerUiza" crossorigin playsinline autoplay muted></video>
    <script>
      var videoSrc = "UIZA_PLAY_BACK_LINK"; // This may be PLAY_BACK_LINK (hls or dash)
      window.UZPlayer = new Uiza(document.getElementById("playerUiza"), {
        src: videoSrc,
      });
    </script>
  </body>
</html>
```


# Flutter SDK

{% embed url="<https://github.com/uizaio/snake.sdk.flutter-player>" %}


# Release Notes

Release Notes is our update that we share with you our new features, improvements or why we change the API to serve you better so you can easily stay up to date on what’s new.

## 2022-06-06

### Auto load-balancing&#x20;

We now change the ingest point to use the 8099 port, which supports auto-choose a server to serve your stream with the best performance.

{% hint style="warning" %}
*Note that all the current ingest points have no port on the ingest URL (use port 1935 as default), so before we upgrade the system, please help us to integrate with the changes, so your application can work perfectly without any issues.*
{% endhint %}

#### *Integration: there are 2 options to do 💪*

1\. Uiza sends the new ingest info to the webhook endpoint: we will send the data to your webhook endpoint - send all the new ingest to the live\_entities.updated event. We can also provide the API to trigger it manually for your testing.

*Sample webhook data:*

<table><thead><tr><th>Event type</th><th>Data (ingest.url)</th></tr></thead><tbody><tr><td>live_entities.updated</td><td><pre><code>{
    "id": "22013d8a-d5fa-48f0-9a63-1f471ca9e81d",
    "name": "Demo app 1",
    "description": "Demo application for documentation",
    "dvr": true,
    "encoding_template": "hd",
    "ingest": {
      "url": "rtmp://g-rtmp.gcpsg.uiza.io/live:8099",
      "key": "live_TB62vHgxSY"
    },
    "playback": {
      "hls": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/master.m3u8",
      "dash": "https://f45dd07a0e.uizadev.io/fmp4/22013d8a-d5fa-48f0-9a63-1f471ca9e81d/manifest.mpd"
    },
    "region": "in-mumbai-1",
    "relay": [],
    "status": "ready",
    "created_at": "2020-03-10T03:20:37.202Z",
    "updated_at": "2020-03-10T03:20:37.202Z"
  }
</code></pre></td></tr><tr><td></td><td></td></tr><tr><td></td><td></td></tr></tbody></table>

2\. The customer update all the ingest endpoint with port 8099, for example, `rtmp://ingest.uiza.io` -> `rtmp://ingest.uiza.io:8099`. Please contact us for more information.

*Live entity data changes:*

| Live entity object | Before                             | After                                         |
| ------------------ | ---------------------------------- | --------------------------------------------- |
| **ingest.url**     | `rtmp://g-rtmp.gcpsg.uiza.io/live` | `rtmp://g-rtmp.gcpsg.uiza.io/live`**`:8099`** |

## 2020-07-01

### Rewatch the last 30 minutes of a live stream!

We have built a Timeshift feature for maximum viewer experience. When you use an Uiza Player SDK, your viewer can switch between watching a live video and rewinding upto 30minutes with our Timeshift feature.&#x20;

### Reduced Latency

We have reduced the HLS Playback latency by up to 50%!

### Webhooks: performance and scalability improvements

We know that webhook is one of the most important features for the integration with Uiza APIs. In this release, by the focus on improving the throughput of our webhooks service, Uiza provides you a faster and more reliable webhooks ever.&#x20;

When your server responds to Uiza the bad status, an event now will be retried to send to your webhook endpoint every hour up to a day, instead of retry many times in minutes, which is too short for any action if your server has trouble.

### Uiza node-kafka-client

There are several problems to solve while enhancing the performance of our services. In the case of message broker enhancement, we decided to release the library of Kafka client run on NodeJS on Github [here](https://github.com/uizaio/node-kafka-client). Which is a wrapper library of [node-rdkafka](https://github.com/Blizzard/node-rdkafka) with extended features, easy to control the workflow, please feel free to use or give us feedback to improve.

## 2020-06-10

### More regions for better performance and more global reach

We have added following regions for your users to use as ingestion points:

{% hint style="success" %}
`us-oregon-1` (Oregon - USA)

`aus-sydney-1` (Sydney - Australia)

`ie-dublin-1` (Dublin - Ireland)
{% endhint %}

## 2020-05-28

### Get notified when we cannot allocate resources for your entity

We try our best to power your broadcasting session by allocating the dedicated resource, returning an RTMP server to ingest and delivering your stream in seconds. Furthermore, we know your time is wasted when you create a [live entity](https://docs.uiza.io/api-reference/live-entities) and the status `init` doesn't change.

So in this release, we added a new live entity status: `resource_allocate_fail` . When the allocating resources for an entity passes a threshold of time, we'll set the entity's status to `resource_allocate_fail` and delete it automatically after 15 minutes.&#x20;

In case the entity status becomes `resource_allocate_fail`,  ~~disaster 🌋🌊 may occur~~ it will not be counted on your usage data. You can create a new live entity afterwards.

### Suspended accounts <a href="#how-to-detect-suspended-account" id="how-to-detect-suspended-account"></a>

Uiza's invoice day is 3rd day of the month, we process to charge your invoice until the 16th day of the month. If the next day we still not charge your invoice successfully, your account will be set to suspend and we prevent your interaction with our core services via API calls.

### Support for MPEG-DASH Playback <a href="#how-to-detect-suspended-account" id="how-to-detect-suspended-account"></a>

Read more about MPEG-DASH [here](https://www.encoding.com/mpeg-dash/).

## 2020-05-07

### New region in Vietnam region is finally available!&#x20;

Provide your users with improved connectivity through our new region. The new region is:`vn-saigon-1`&#x20;

### Added PATCH methods to modify objects

Instead of replacing your resource for a simple modification, you can now update the resource using the PATCH method. We will deprecate the PUT methods in the future.

## 2020-04-21

### Track your encoding minutes!

You can now see how many minutes you have encoded using Uiza. For more details on how we calculate your encoding minutes, go to this [link](https://help.uiza.io/data-usage)

![Your total encoding minutes can be seen in the billing page](/files/-M5yoK-YlLDnFwWtBE2R)

### Uiza's Player for better viewer experience

Integrate Uiza's player into your website for optimal playback. Our player supports ABR, playback speed, and playback in a smaller window.

![](/files/-M5ytZ6u413oYyEG-ovT)

## 2020-03-26

### Behold! DVR <a href="#behold-emojis" id="behold-emojis"></a>

You can now rewatch your live stream with DVR. We record your live stream and convert it to a [video entity](https://docs.uiza.io/api-reference/video-entities), and your users can watch your live stream recording if they missed it.

![The DVR is created instantly while you stream](/files/-M5yYVqbDtAjjEag7OPN)

### Broadcast your moment to multiple destinations simultaneously&#x20;

Using our `Relay Destination` feature, you can broadcast your live stream to multiple social networks (Facebook, Youtube, Twitch, etc) or RTMP endpoint simultaneously. Update your fans on all platforms and let us handle the signal!

![Broadcasting the signal to Youtube](/files/-M5yYnxbwfUGIQWOX8ws)

### Give your end user the best experience with ABR

You can create up to 6 video profile outputs (Business Tier) with your stream, to cater towards different networks and mobile devices. Your viewer can choose different resolutions, or our Uiza player will recognize the most fitting profile depending on your user's bandwidth, and adjust their bitrate accordingly.

![Create your Preset and add your profiles](/files/-M5yYwcOIrWS-3DWGeb_)

![Choose your Video Resolution on playback](/files/-M5yZ-CNyeAZUeZ93Ig3)


# API Changelog

API changelog describes to you what we change on the newest API dated version we've made so you can easily stay up to date on what’s new.

## 2020-07-01

**What’s new**

* Support enable/disable of live relay destination and added the identity attributes to the relay object: id, status, created\_at , and updated\_at.
* Faster and more reliable Webhook service.
* Separate Delivery overusage to different regions with distinct costs. [Read more here.](https://help.uiza.io/data-usage)
* Adjust the overuse invoice template to include items for delivery regions, unit prices, and exceeded values.
* Support for enabling/disabling CCU display on Uiza’s WebSDK. [Read more here](https://github.com/uizaio/uiza-javascript-sdk-player#customizing-the-ui-button).

**Changes**

* Time interval to retry Webhook changed from multiple times per minute to an hourly basis for a duration of 24 hours.
* Update subscription plans according to the new pricing model ([Pricing](https://uiza.io/pricing)).

**Fixes**

* Fixed issue with user suspension in case of failed payment when changing the current subscription

## 2020-05-28

**What's new**

* User suspension - User’s who missed payment after the invoice period will be suspended.&#x20;
* New status when creating live entity: `resource_allocation_fail` - when the entity takes too long to look for resources. User’s will receive a message and will be prompted to create a new entity.
* SDK player updates
  * Live button to return to live moment
  * Analytics and CCU displayed on Uiza’s players
* Support for [MPEG-DASH](https://www.encoding.com/mpeg-dash/) playback .

**Fixes**

* Fixed bug when deleting a live entity assigned to a preset.
* Fixed minor bug with wrong message response when creating a webhook endpoint but missing url parameter.
* Fixed bug returning inconsistent playback.url of live entity in Live API and Event API.
* Fixed confusing error message when creating a [live entity](https://docs.uiza.io/api-reference/live-entities) with missing parameters.
* Fixed confusing error message when creating a [webhook endpoint](https://docs.uiza.io/api-reference/webhook_endpoints) with missing parameters.
* Fixed bug allowing Team & Business tier users to profiles to Uiza presets.
* Fixed bug with randomly returned error type when client calls APIs.
* Fixed issue with retry request live resource.

## 2020-05-07

### What's new

* Added new API: [Update a live entity](https://docs.uiza.io/v/2020-05-07/api-reference/live-entities/update-a-live-entity) using PATCH method&#x20;
* Added new API: [Update a webhook endpoint](https://docs.uiza.io/v/2020-05-07/api-reference/webhook_endpoints/update-webhook-endpoint) using PATCH method&#x20;

### Changed

* Deprecated [Update a live entity](https://docs.uiza.io/v/2020-05-07/api-reference/live-entities/deprecated-update-a-live-entityhttps://docs.uiza.io/v/2020-05-07/api-reference/live-entities/deprecated-update-a-live-entity) API using PUT method&#x20;
* Deprecated [Update a webhook endpoint](https://docs.uiza.io/v/2020-05-07/api-reference/webhook_endpoints/deprecated-update-webhook-endpoint) API using PUT method&#x20;

### Fixed

* Inconsistent entity status on events when update entity status to ready&#x20;
* Fixed bug when calling list events API returns `internal-error`&#x20;

## 2020-04-21

### What's new

* Expose new API to reset Ingest Key of a Live Entity.
* Expose new API to get Invoice Detail.
* Support clearing Live Entity's relay setting by updating relay parameter as empty
* Support exporting Invoice to PDF.
* Support deleting source files of video entity.

### Changes

* Replace field `type` by `input_type` in  `video_entity` event object.

### Fixes

* Fixed bug incorrect error response when updating invalid video preset/profile.
* Fixed bug where user can login without verifying email address.
* Fixed bug displaying empty `live_entity_id` in the `live_session` event object.

## 2020-03-26

### What's new

* Added new event `video_entities.created` in [Event Types](https://docs.uiza.io/api-reference/events/event-types).
* Added `video_entity_id` attribute to [Live Session](https://docs.uiza.io/api-reference/live-sessions) to link the live records with its video entity.
* Support DVR option in [Live Entity](https://docs.uiza.io/api-reference/live-entities). Included two new APIs to enable and disable DVR.
* Support login with Google.
* Support multiple destination broadcast and added `relay` attribute to [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Added `encode` attribute to [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Introduced [Video Profile](https://docs.uiza.io/api-reference/video-profiles) & [Video Preset](https://docs.uiza.io/api-reference/video-presets) to support live with `encode` option.
* Added new attribute `preset` in  [Live Entity](https://docs.uiza.io/api-reference/live-entities) .
* Support filtering [Live Sessions](https://docs.uiza.io/api-reference/live-sessions) by DVR attribute and added new attribute `preset` in Live Session details
* Support filter live video by `live_entity_id`.
* Increase resource allocation speed up to 500 live entities per 5 seconds.
* Support categorize Ulas by `encode` feature.

### Changes

* Live Session attribute `entity_id` changed to `live_entity_id`  to differentiate with `video_entity_id`.
* Following [Google API Design guideline](https://cloud.google.com/apis/design/standard_methods#delete), all `DELETE` APIs should return empty body.
* Remove `Reset ingest key` API in version 2020-01-10. We no longer support resetting ingest key, because conflicts with the end of signal occurs when an user resets the ingest key while streaming. We are working on this problem.
* Remove emit event log form. All event logs related to entity should be executed in Live Entity server.
* Update submodule by removing `googleapis`. This update shortens the times of build time from 10 minutes to about 2 minutes.
* Support allocating request based on available vCPUs and Memory
* Enhance the performance of allocating by moving DNS logic part to be a DNS Service.

### Fixes

* Webhook endpoints can now send to Slack without error and return the valid error message.
* Delete DNS when deleting a live entity.
* Fixed bug where user ID is undefined when creating a live entity.
* Fixed inconsistency of API response between live entity API and webhook endpoints API.
* Fixed bug where updating the video entity returns bad request.
* Fixed inconsistency in boolean value in events API.
* Fixing crashing issue due to not handling case of Axios - fail on getting a response from Prometheus.
* Handle multi node down trigger fail over.
* Fixed bug where retrieving live entities causes long time to allocate resource.
* Cannot get Ulas disk metrics during scaling action.


# Hola! 👋

### **Welcome to Uiza, the video streaming as code!**&#x20;

We aim to provide developers with an end-to-end video streaming solution that offers simple integration and stable performance at scale. At the very beginning of our roadmap, we tackle the problem that is considered the most severe, ***video and live stream delivery***. The proximity between the infrastructure and the streamer/viewer is the key factor that influence the quality of the video streams. Setting up and managing a wide network of infrastructures that penetrates locally to reach out as closely as possible to the streamers and viewers in various cities are tough. The first version of our brand-new platform is created to solve this problem.

{% hint style="success" %}
Our **key differentiation** is that we are developing a diversified network of infrastructures that does not only rely on public cloud like Amazon Web Services, Google Cloud Platform, or Digital Ocean, but also a wide range of local infrastructures those are rooted in lower-tier cities like *Bengaluru, Kolkata, Chennai*... This means your viewers will most likely *watch the videos being streamed from the infrastructure located in the same city of theirs*, which improves the quality and scalability of the video streams significantly.
{% endhint %}

![](/files/-Lvy1ZLdD3Cbvz7i3WN8)


# Introduction

Uiza helps you broadcast your live stream to your audiences with literally a few lines of codes, or at least we are trying hard to get there:muscle::muscle::muscle:. But before experiencing the magic, let's make sure that you understand the terms correctly.

* ***`live_entity`***: Live entities are basically live events, with or without a live feed. A live entity contains the information required for Uiza to allocate resources to power the live event, and direct your live feed toward these resources for ingestion and broadcasting.
* ***`live_session`***: The duration of one session is counted from the moment Uiza receives the first signal until the last of that live feed. Therefore, one entity could contain multiple sessions. The durations of these sessions are calculated as *Live Minutes* in your billing.
* ***Streamer***: Streamers record the live events and are the source of the live  signals that Uiza receives.
* ***Viewer***: Viewers are the users who watch the live stream on their devices. They are the destination of the delivery of the live stream.

Now that we are on the same page, let's navigate to the **Quickstart** to start *live streaming*.

{% content-ref url="/pages/-LwqhgC-FZjkAy13MWg8" %}
[Authentication](/2021-09-21/getting-started/authentication)
{% endcontent-ref %}




---

[Next Page](/llms-full.txt/1)

