Create a simple video distribution platform service using Amazon IVS

Sep 4, 2020 PHP AWS IVS lumen

Overview

In this article, simple video distribution using Amazon Interactive Video Service(hereinafterIVS), which became GA on 2020/07/15. Create a platform service. The implementation is implemented using PHP / Lumen.

What is #IVS? It is a managed live streaming service that can be easily set up, and one of its features is a low-latency video experience. We also provide a player SDK optimized for IVS, which makes it possible to provide services without being aware of functional differences between platforms. https://aws.amazon.com/jp/ivs/features/

#Configuration for platform implementation In order to create a simple video distribution platform, it can be realized with the following configuration.

Untitled (6) .png

Events that start and end the stream from IVS can be received using Amazon EventBridge, and the contents of the event can be passed to SNS and Lambda. In addition, the configuration diagram shows the configuration of EventBridge and Lambda. By executing the API on the platform side from Lambda according to the content of the event, it is possible to grasp the distribution status of each channel on the platform service side.

The IVS API is available in the following regions: The Tokyo region is currently unavailable, but You can use the CDN to distribute and watch videos from anywhere in the world.

This time, the instance for platform implementation was created in the Tokyo region, and for EventBrigde, Lambda, IVS, it was created in the Oregon region. We also defined a table (stream) to manage channel creation and distribution status.

name type description
id int
uuid varchar identification ID
name varchar title
ivs_arn varchar ivs ARN
playback_url text viewing URL
rtmp_url varchar Delivery URL
stream_key varchar Stream key for distribution
is_live boolean Judgment flag being delivered
is_delete boolean Delete flag
created_at datetime
updated_at datetime

The migration file is as follows.

        Schema :: create ('stream', function (Blueprint $ table) {
            $ table-> id ();
            $ table-> string ('uuid')-> unique ();
            $ table-> string ('name');
            $ table-> string ('ivs_arn');
            $ table-> text ('playback_url');
            $ table-> string ('rtmp_url');
            $ table-> string ('stream_key');
            $ table-> boolean ('is_live')-> default (false);
            $ table-> boolean ('is_delete')-> default (false);
            $ table-> timestamps ();
        });

#Channel issuance / registration Issuing a channel stream key from IVS uses the CreateChannel API. When creating a channel, it is necessary to set type to specify the type to deliver and latencyMode to decide whether to use the low latency function. If not set, it will be registered with type: STANDARD, latencyMode: LOW. In addition, it is possible to set a name for the channel, and setting the name makes it easier to manage on the mannequin.

There are two types of delivery, STANDARD and BASIC.

STANDARD: Multiple qualities are generated from the original input, to automatically give viewers the best experience for their devices and network conditions. Vertical resolution can be up to 1080 and bitrate can be up to 8.5 Mbps.

BASIC: Amazon IVS delivers the original input to viewers. The viewer ’s video-quality choice is limited to the original input. Vertical resolution can be up to 480 and bitrate can be up to 1.5 Mbps.

In the case of STANDARD, transcoding is performed on the delivered video, and multiple renditions are included in addition to the source image quality (1080p). (Maximum bit rate that can be delivered is 8.5 Mbps) BASIC, on the other hand, does not transcode and only provides source quality up to 480p. (Maximum deliverable bit rate is 1.5Mbps)

Since the charge on the input side changes greatly depending on the type, it is necessary to set the type according to the service provision. (The input fee is STANDARD: 2.00 USD / h, BASIC: 0.20 USD / h, so BASIC is 1/10 of the price without transcoding.)

When you execute the API, a response will be returned in the following format. Since the stream key is also issued at the timing of creation, the information necessary for distribution only by issuing the channel will be available. Regarding arn, register it in the DB etc. for the information necessary for operating the channel and receiving the notification of the start of distribution. In addition, if you also register ingestEndpoint, streamKey, which is necessary for distribution, and playbackUrl, which is necessary for viewing. You can also save the trouble of acquiring the url required for viewing via the API.

{
   "channel": {
      "arn": "string",
      "authorized": boolean,
      "ingestEndpoint": "string",
      "latencyMode": "string",
      "name": "string",
      "playbackUrl": "string",
      "tags": {
         "string": "string"
      },
      "type": "string"
   },
   "streamKey": {
      "arn": "string",
      "channelArn": "string",
      "tags": {
         "string": "string"
      },
      "value": "string"
   }
}

If the issuing part of the channel is implemented in PHP, it will look like this. Regarding the name on the IVS side, a UUID is issued and registered for easy management. The URL to be delivered will be in the format rtmps: // $ {ingestEndpoint} / app, so match the format when registering in the DB.

  public function createStream (Request $ request)
  {
    $ request = $ request-> json ()-> all ();

    if (empty ($ request ['name'])) {
      return response ()-> json (['message' =>'empty name'], 400);
    }

    $ uuid = Uuid :: uuid4 ();
    $ ivs = App :: make ('aws')-> createClient ('ivs');
    $ result = $ ivs-> createChannel ([[
      'latencyMode'=>'LOW',
      'name' => $ uuid-> toString (),
      'type' =>'STANDARD',
    ]);

    $ stream = Stream :: create ([[
      'uuid' => $ uuid-> toString (),
      'name' => $ request ['name'],
      'ivs_arn' => $ result ['channel'] ['arn'],
      'playback_url' => $ result ['channel'] ['playbackUrl'],
      'rtmp_url' =>' rtmps: //'. $ result ['channel'] ['ingestEndpoint'].'/ app',
      'stream_key' => $ result ['streamKey'] ['value']
    ]);

    return response ()-> json ($ stream-> makeVisible (['rtmp_url','stream_key']), 201);
  }

https://docs.aws.amazon.com/ivs/latest/APIReference/API_CreateChannel.html

#Receiving the start / end of distributionYou need to use Amazon EventBridge to receive the start and end of distribution from IVS. There are three types of notifications from IVS to EventBridge: IVS Stream State Change (status change notification), IVS Stream Health Change (health status change notification), and IVS Limit Breach (limit excess notification). ..

Since IVS Stream State Change will notify you about the start / end of distribution, use this event type. There are three types of events sent from the event type of IVS Stream State Change.

| Event name | Contents | |: —: |: —: | | Stream Start | Events that make streams available | | Stream End | Event that makes the stream unviewable | | Stream Failure | Events that failed to stream for some reason |

Regarding the start / end of distribution, processing is performed in response to the events of Stream Start and Stream End. When you receive an event from IVS, you will receive it in the following format.

{
   "version": "0",
   "id": "01234567-0123-0123-0123-012345678901",
   "detail-type": "IVS Stream State Change",
   "source": "aws.ivs",
   "account": "aws_account_id",
   "time": "2017-06-12T10: 23: 43Z",
   "region": "us-east-1",
   "resources": [
     "arn: aws: ivs: us-east-1: aws_account_id: channel / 12345678-1a23-4567-a1bc-1a2b34567890"
   ],,
   "detail": {
     "event_name": "Stream Start"
   }
}

Since the event name to be notified is described in event_name, it will be necessary to process it at the notification destination according to the event. Also, since the target ARN is described in resources, the process of starting distribution is performed for the ARN. The above example is an example of Stream Start, but other events also contain information in detail. Note that information other than event_name is not included for Stream Start and Stream End. Examples of other events are provided in the documentation, but are omitted in this article.

Regarding the lambda function of the notification destination, the implementation is done so that the API to be executed is changed according to the contents of event_name. Created before registering for EventBrigde.


var request = require ('request');

const HOST ='';
const EVENT_STREAM_START ='Stream Start';
const EVENT_STREAM_END ='Stream End';
const LIVE_START_ENDPOINT ='/ api / v1 / live / start';
const LIVE_STOP_ENDPOINT ='/ api / v1 / live / stop';

exports.handler = function (event, context) {

    var actionEndpoint = null;
    const params = {
      arn: event.resources [0]
    }

    switch (event.detail.event_name) {
      case EVENT_STREAM_START:
        actionEndpoint = LIVE_START_ENDPOINT;
        break;
      case EVENT_STREAM_END:
        actionEndpoint = LIVE_STOP_ENDPOINT;
        break;
      default: default:
        return;
    }

    const options = {
      uri: HOST + actionEndpoint,
      headers: {
        "Content-type": "application / json",
      },
      json: params
    };

    request.post (options, function (error, response, body) {});
}

Configure EventBridge to receive the IVS Stream State Change configuration. By setting the event type to all events, it is possible to receive all three event types, but this time it is only for the IVS Stream State Change event, so set it in the following form.

Comment 2020-08-16 235518.jpg

For the target, specify the lambda function created earlier. Comment 2020-08-16 235419.jpg

Finally, implement the API executed from lambda. For both the start and end of distribution, the ARN information registered on the service side is acquired and the distribution status is switched. However, since there is an API (stopStream) that can stop the stream on the IVS side when it comes with an ARN that is not registered at the start of distribution, the process of executing the API to stop the distribution is included.

  public function postLiveStart (Request $ request)
  {
    $ request = $ request-> json ()-> all ();

    $ condition = [
      'ivs_arn' => $ request ['arn'],
      'is_delete' => false,
      'is_live' => false
    ];;

    $ stream = Stream :: where ($ condition)
              -> orderBy ('updated_at','desc')
              -> first ();

    if (! $ stream) {
      $ ivs = App :: make ('aws')-> createClient ('ivs');
      $ ivs-> stopStream ([[
        'channelArn' => $ request ['arn']
      ]);
      return response ()-> json (['message' =>'not found streams'], 404);
    }

    $ stream-> is_live = true;
    $ stream-> save ();

    return response ()-> json ([]);
  }
  public function postLiveStop (Request $ request)
  {
    $ request = $ request-> json ()-> all ();

    $ condition = [
      'ivs_arn' => $ request ['arn'],
      'is_delete' => false,
      'is_live' => true
    ];;

    $ stream = Stream :: where ($ condition)
              -> orderBy ('updated_at','desc')
              -> first ();

    if (! $ stream) {
      return response ()-> json (['message' =>'not found streams'], 404);
    }

    $ stream-> is_live = false;
    $ stream-> save ();

    return response ()-> json ([]);
  }

https://docs.aws.amazon.com/ivs/latest/userguide/SUE.html https://docs.aws.amazon.com/ivs/latest/APIReference/API_StopStream.html

#Actually deliver Create a channel using API, register the generated URL and stream key (StreamName), and start distribution. Comment 2020-08-23 175805.jpg

When the distribution starts, the lambda function is invoked via EventBridge. After that, the distribution start process is performed and viewing becomes possible. Although not introduced in this article, if you create a page by incorporating the player SDK or adding the API to acquire the registered channel in the view part, you will finally be able to watch the distribution on the browser like this. .. Inked comment 2020-08-17 231932_LI.jpg

Finally

In this article, we created a simple video distribution platform using IVS. By using the API provided by IVS, it can be used without preparing a distribution platform on its own, so it seems that the threshold has become very low for those who want to create a video distribution platform. IVS also has various features such as registering time-specified metadata and Playback Auth function that gives authentication function to URL at the time of viewing, so by utilizing it according to the purpose. I’m hoping that the service will continue to grow.

#Reference https://aws.amazon.com/jp/ivs/https://docs.aws.amazon.com/ivs/latest/userguide/what-is.html

Implementation code

https://github.com/clom/yu-streaming