WebページのボタンからAWS MediaLiveを起動させる

##はじめに
ライブ配信で利用するAWS MediaLiveの起動・停止は
通常、AWSコンソールやCLIから操作することが多いと思います。

ただ、開発者以外の人に操作してもらう場合は、それだとハードルが高いため、
Webページに配置したボタンから起動・停止を操作できるような仕組みを考えてみました。

##構成図
S3にHTMLを配置して、CloudFrontで配信します。

Web利用者はHTML上に配置されたボタンを押します。
すると、APIが実行され、Lambdaがキックされて、MediaLiveが起動・停止する仕組みになります。
![ScreenShot 2020-08-19 19.56.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/0fcc7cbd-7709-7c2c-fb19-6e6f01b1ac67.png)

##MediaLive
今回、操作対象とするMediaLiveチャンネルは、1つとします。

##IAM
Lambda用のIAM Roleを作成しておきます。
必要なポリシーは下記になります。

- AWSLambdaBasicExecutionRole
- AWSElementalMediaLiveFullAccess

##Lambda

ランタイム：Python3.8
環境変数：**「channel_id」**で、MediaLiveのチャンネルIDを設定します。

- start関数

※すでにチャンネルが起動していた場合、strat処理を実行しないようにしています。

```python:lambda_function.py
import boto3
import os

channelid = os.environ['channel_id']
medialive = boto3.client('medialive')

def lambda_handler(event, context):
    
    channels = medialive.describe_channel(ChannelId=channelid)

    if channels['State'] == 'RUNNING':
        ngmsg = ("チャンネルはすでに起動されています")
        return ngmsg
        pass
    
    else:
        medialive.start_channel(ChannelId=channelid)
        okmsg = ("チャンネルを起動しています")
        return okmsg
```

- stop関数

※start関数と同様、すでにチャンネルが停止していた場合、stop処理を実行しないようにしています。

```python:lambda_function.py
import boto3
import os

channelid = os.environ['channel_id']
medialive = boto3.client('medialive')

def lambda_handler(event, context):
    
    channels = medialive.describe_channel(ChannelId=channelid)

    if channels['State'] == 'IDLE':
        ngmsg = ("チャンネルはすでに停止されています")
        return ngmsg
        pass
    
    else:
        medialive.stop_channel(ChannelId=channelid)
        okmsg = ("チャンネルを停止しています")
        return okmsg
```

##API Gateway

- 1. APIの作成
- 2. リソースの作成：startとstopをそれぞれ作成します。
- 3. メソッドの作成：POSTやPUTなど
- 4. CORSの有効化
- 5. メソッドレスポンス：実行結果を日本語で表示させるため、**application/json;charset=UTF-8**を追記します。
- 6. APIのデプロイ

すると、下記ようなURLが発行されます。

https://xxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage名]

（詳しい設定方法は、本ページ最下部の参考文献の記事が参考になりました）

##HTML

次にHTMLを作成します。

私はHTMLに詳しくなく、もっといい書き方がある気がしますので、
参考程度に載せておきます。

「 **url:** 」には、先ほどのAPI Gatewayで発行したURLの最後に、
startやstopのリソース名を加えたURLを記入します。

例：
>url:"https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/start"


```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta http-equiv="Content-Script-Type" content="text/javascript" />
  <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <title>MediaLive操作Web</title>
</head>
<script>
  $(function(){
    // ボタンを押すと処理を開始する
    $("#btn1").on("click", function() {
    $.ajax({
        type: "POST",
        url: "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/start",
        cache : false,
    })
        .done(function(result) {
            console.log(result);
    })
        .fail(function(result) {
            console.log(result);
    })
            console.log = function (log) {
    
        // API実行結果と実行日時を表示させる
        var date = new Date();
        document.getElementById('console_log1').innerHTML = log + "<br>" + "（"　+ date.toLocaleString() + "）" + "<br>";
        }
    })
})

   function stop(){
    // ボタンを押下すると確認ダイアログを表示する
    ret = confirm("本当にチャンネル停止してよろしいですか？");
    if (ret == true){
    $.ajax({
        type: "PUT",
        url: "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/[stage]/stop",
        cache : false,
    })
        .done(function(result) {
            console.log(result);
    })
        .fail(function(result) {
            console.log(result);
    })
            console.log = function (log) {

        // API実行結果と実行日時を表示させる
        var date = new Date();
        document.getElementById('console_log2').innerHTML = log + "<br>" + "（"　+ date.toLocaleString() + "）" + "<br>";
        }
    }
}
</script>
<button type="button" id="btn1" style="width:150px;height:50px">チャンネル起動</button>
<div id="console_log1" div class="disp-area" style="width:400px;height:50px;padding:15px;background-color: #f0f18b2c;"></div>
<br>
<button type="button" onClick="stop()" style="width:150px;height:50px">チャンネル停止</button>
<div id="console_log2" div class="disp-area" style="width:400px;height:50px;padding:15px;background-color: #f0f18b2c;"></div>
</html>
```

##S3とCloudFront
HTMLを置くだけなので、この部分は省略します。

##動作確認
- トップページ
→ 起動・停止ボタンと実行結果ログを表示する枠を用意しています。
![ScreenShot 2020-08-20 22.57.32c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/341da6c2-b0f1-b559-592b-b9bc8dd0a3e4.png)

- 「チャンネル起動」ボタンを押します。
→ メッセージと実行日時が表示されます。
![ScreenShot 2020-08-20 23.14.02c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/98ca4025-aa50-92ee-4a21-ebbdc8ea02e7.png)
- MediaLiveチャンネルが起動されました。
![ScreenShot 2020-08-20 23.08.30c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277934/120afc96-7e48-96b5-febc-bda1301527c6.png)

- 「チャンネル停止」ボタンも同様に動作確認します。
##参考文献

- [AWS API Gateway から Lambda 関数を使って EC2 インスタンスを起動・終了する](https://mseeeen.msen.jp/start-ec2-instance-by-aws-lambda-through-api-gateway/)