JavaScript
Chrome
AI
人工知能
MicrosoftCognitiveServices

AI連携FW『シンプルエーアイ』を使ってみた(4):より「魔法の鏡」らしく

はじめに

AI連携フレームワーク『シンプルエーアイ』を使って遊ぶ、第4回目です。
(1)準備編
(2):AIっぽい事をさせてみたい(その1)
(2):AIっぽい事をさせてみたい(その2)
(3):「魔法の鏡」を作るぞ

公式サイトはこちら:https://smartaifw.com/simpleai-trial/

実用性も大事ですが…

前回の『(3):「魔法の鏡」を作るぞ』では、起動したら現在日時が表示されている鏡が表示され、「人物判断して」と声を掛けると、結果が鏡に表示されるようにしました。
続いては、前回の前書きに書いた「前にどんなお化粧をしたかが判れば便利」という要素の実現を考えていましたが…
折角のお遊びですので、今回は更に”魔法の鏡”っぽい、使う楽しみを上乗せする方向で進めたいと思います。

”魔法の鏡らしさ”とは何ぞや

とは言うものの、”らしさ”って何だろう?
色々考えてみましたが、やはりここは『シンプルエーアイ』の使いやすさを生かした、お遊び要素を加える事にします。

『シンプルエーアイ』は、AIの返答の仕方等も柔軟に変更することができます。
今は「了解」と返事をしてくれるのですが、これを変えてしまいます。
そもそも「人物判断」という言葉も、実際の機能が分かり辛いので、一緒に変更します。

それから、お化粧する時に音楽が流れていたら、作業が捗るのではないでしょうか。
ですので、「音楽をかけて」等と呼びかけると、音楽を流すようにしたいと思います。
ついでと言っては何ですが、天気予報やニュースも見られるようにしてしまいましょう。

やりたい事

今回の記事では、以下のような機能を追加します。

  • AIの応答の言葉を変える
  • 人物判断の言葉の変更
  • 「音楽をかけて」と呼びかけると、鏡の上部に画面を開いて音楽を流す(Youtube起動)
  • 「天気教えて」や「ニュースを見たい」と呼びかけると、鏡の上部に天気予報やニュースを表示する(Youtube起動)

AIの応答の言葉を変える

それでは、本記事で想定しているサンプルプログラムの動作を説明します。
まず、鏡に呼びかけた時に「かしこまりました」と返答をしてくれるようにします。

『シンプルエーアイ』のスマートエージェント機能には様々なパラメータがあります。
サンプルプログラムでは「SimpleAI.param.SmartAgent」と記述している部分が、そのパラメータ部分です。
このうちの「Prompt」が応答の言葉なので、この値を設定しましょう。スマートエージェント開始処理の後に行って下さい。

またAIのお喋りの語尾を変えることも出来ます。「PromptEnd」というパラメータです。
ここで冒頭に「、」を入れているのは、お喋りする際に一泊置いてもらう為です。
ここでは、語尾に「ご主人様」と言うようにしました。

追加部分のソースは以下の通りです。

//AIの応答の言葉を変更する
SimpleAI.param.SmartAgent.Prompt = "かしこまりました、";
//AIの語尾の言葉を変更する
SimpleAI.param.SmartAgent.PromptEnd = "、ご主人様";

人物判断の言葉の変更

続けて、人物判断を呼び出す言葉・音声キーを変更します。
お化粧情報も含めて表示するので、「メイクチェック」などの言葉にしましょう。

まず、以前に設定した、人物判断処理追加部分のソースがこちら。

//人物判断(スマートエージェントコマンド追加サンプル)
var cmd;
cmd=SimpleAI.getSmartAgentCommand();
cmd.MainCommand.push(
    {
        //人物判断の音声キーを追加する
        label: "PersonalJudgment",
        labelname: "人物判断",              //ラベル名称、現在のモード読み上げ等に使用
                word:[/人物/,/判断/],
                message:"人物判断を行います",

おさらいになりますが、音声キーそのものは「word:」の部分を設定すればOKです。
ただし「message:」の部分にも”人物判断”という言葉が入っているので、今回は併せて変更します。

変更後のソースはこちらです。

//人物判断の音声キーを追加する
label: "PersonalJudgment",
labelname: "人物判断",              //ラベル名称、現在のモード読み上げ等に使用
word:[/メイク|make|化粧|けしょう|仕上げ/,/check|確認|判断|判定|見て/],
message:"しばらくお待ちください",

余談:AIが聞き取り辛い言葉がある

当初は「幾つに見える?」という言葉にしようとしたのですが、AIにとっては大変聞き取り辛い言葉らしく、うまく判定してくれませんでした。
「メイク」という言葉も同様で、なぜか違う言葉に判断されてしまいがちです。

では、AIが言葉をどのように聞き取ったかを、どうやって確認すればいのでしょう。
ブラウザの機能の一つである開発ツールを使えば、AIがどのように判断したかを見る事ができます。

Chromeの場合は、画面右上のメニューより「その他のツール」→「デベロッパーツール」を開いて下さい。
「Console」欄が開いていない場合は、クリックして開きます。

すると、以下のように処理ログが表示されるようになります。
下図の場合で言うと、上の赤枠部分は「メイクチェック」と呼びかけた場合、下の赤枠は「メイク判断」と呼びかけた場合です。
「メイクチェック」という言葉が、うまく聞き取られていない事が判りますね。
4-1.png

 

ですので今回は、「メイク」だけではなく「化粧」など、幾つかの言葉を設定しました。
このように、AIにとって聞き取り易い/聞き取り辛い言葉がありますので、キーワードを設定する際は、何度か試す必要があるでしょう。

「音楽をかけて」と呼びかけると、鏡の上部に画面を開いて音楽を流す(Youtube起動)

それでは次に、音楽を流す処理を追加したいと思います。

サンプルプログラムの動作を説明します。
「音楽をかけて」「音楽ききたい」といった呼びかけをすると、Youtubeの小さな画面を鏡の右上に上乗せして開き、指定したキーワードに該当する音楽を流してくれるようにします。
音楽呼び出し後の画面は、こんな風になります。画面右上の赤枠部分がYoutubeの画面です。
4-2.png

Youtubeを扱えるようにする

この動作を行うためには、まずはYoutube動画を扱えるように変更する必要があります。

まずHTMLのヘッダ部分に、Youtubeを扱う為の宣言を追加して下さい。
追加部分のソースは以下の通りです。

<script type="text/javascript" src="https://www.youtube.com/iframe_api"></script>

また、Youtubeを表示する部分をHTMLに追加します。
サンプルプログラムでは、情報表示部分とvideoタグの間に挿入しました。
修正後のソースは以下の通りです。

<p class="msg-over-top" id="dispMsg"></p>
<p class="youtube-over-top" id="dispYTPlayer"></p>
<div class="video-wrap">
  <video id="denaripamControlSensor_video" width="800px" height="600px" controls autoplay>
  </video>
</div>

勿論、CSS側にもYoutube重ね合わせ表示の追加が必要です。サンプルプログラムのソースは以下の通り。

/* YoutubePlayer表示部 */
.youtube-over-top {
    opacity: 0.5;   /* 対象の透過度(0:完全透明 1:不透明) */
    position: absolute;
    left: 580px;
    top: 2%;
    z-index: 1;
    padding-left: 5px; padding-right: 5px;
}

続いて、JavaScriptでYoutube起動処理を組み込みます。
サンプルプログラムでは YouTubePlayerAPI を利用する事にしました。
最初に YouTubePlayerAPI のオブジェクトを作成し、「YouTubeIframeAPI=true;」で有効にします。

それから「YouTubeplayer_start」という関数を作成し、実際のYoutube起動処理を記述します。
オブジェクトがあればいったん停止処理を行い、そして改めてnewで作成しています。
Youtubeの表示サイズ等は、ここで指定します。

追加部分のソースは以下の通り。

//youtube
var YouTubeplayer;
var YouTubeIframeAPI=false;
 function onYouTubeIframeAPIReady() {
    YouTubeIframeAPI=true;
}
//youtube表示ウィンドウ
var html_temp_modal = 
     '<!-- YoutubePlayer -->'
    +'<div class="embed-responsive embed-responsive-16by9">'
    +'  <div class="embed-responsive-item" id="player"></div>'
    +'</div>';
//youtube起動
var YouTubeplayer_start=function(keyword,volume) {
    if(YouTubeIframeAPI) {
        YouTubeplayer_stop();
        YouTubeplayer = new YT.Player('player', {
            height: '150',
            width: '200',
            controls: 2,        //コントロールの表示
            iv_load_policy: 3,  //アノテーション非表示
            showinfo: 0,        //インフォメーション非表示
            events: {
                onReady: function(event){
                    if(keyword) YouTubeplayer.loadPlaylist({listType:"search",list:keyword,});
                    if(volume)  YouTubeplayer.setVolume(100);
                },
            },
        });
    }
};

起動処理と対になる停止処理も、ここで入れてしまいましょう。
「YouTubeplayer_stop」という関数を作成し、Youtube停止処理を記述します。ここではdestroy、つまり破棄をしています。

追加部分のソースは以下の通り。

//youtube停止
var YouTubeplayer_stop=function() {
    if(YouTubeplayer)YouTubeplayer.destroy();
};

音楽をかける音声キーの追加

これでYoutubeを扱えるようになりましたが、勿論これだけでは足りませんね。音声キーの追加が必要です。
以前に追加した「人物判断」の後ろに処理を加えましょう。

音声キーの追加そのものは以前の記事で行っていますので、今回のサンプルプログラムにおける新しい要素だけを説明します。
まず、サンプルプログラムの対象部分のソースを見て下さい。

//音楽をかける音声キーを追加する
{
    label: "PlayMusics",
    labelname: "音楽をかける",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/音楽|mugic|曲/,/かける|かけて|流す|流して|きく|きかせて|ききたい/],
    message:"こちらの曲をどうぞ",
    messageafter:function(sender,event,param) {
        document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
        YouTubeplayer_start("やる気の出る クラシック音楽 ピアノBGM");
    },
},

先程追加したJavaScript関数「YouTubeplayer_start」を呼び出す際に、キーワードを指定していますね。
これは実際にYoutubeで検索処理を行う為のキーワードで、この言葉をYouTubeIframeAPIに引き渡して検索処理を行うようになっています。
下記ソースの「if(keyword) YouTubeplayer.loadPlaylist({listType:"search",list:keyword,});」の部分です。
なお、次行の「if(volume) YouTubeplayer.setVolume(100);」の部分で、音量を設定しています。

if(keyword) YouTubeplayer.loadPlaylist({listType:"search",list:keyword,});
if(volume)  YouTubeplayer.setVolume(100);

以上の処理で、鏡に向かって「音楽かけて」等と告げると、鏡の下にYoutubeの音楽動画が表示されるようになりました。

音楽を止める音声キーの追加

始まりがあれば終わりがあるので、音楽を止める音声キーも必要ですね。さくっと追加してしまいましょう。
先程作成した「YouTubeplayer_stop」を呼び出すようにして下さい。
対象部分のソースは以下の通りです。

//音楽を止める音声キーを追加する
{
    label: "StopMusics",
    labelname: "音楽を止める",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/音楽|mugic|曲/,/止める|止めて|やめる|やめて|終わり|終了/],
    messageafter:function(sender,event,param) {
        YouTubeplayer_stop();
    },
},

「天気教えて」や「ニュースを見たい」と呼びかけると、鏡の上部に天気予報やニュースを表示する(Youtube起動)

Youtubeの起動/停止という、大きな処理が追加できました。
ここをクリアしたら、天気予報やニュースの表示も軽いものです。

やり方は音楽呼び出しとそれ程変わらず、それぞれの起動処理と停止処理の音声キーを追加します。
それでは、サンプルプログラムの追加部分のソースを見て下さい。

//朝のニュースを呼び出す音声キーを追加する
{
    label: "ShowNews",
    labelname: "ニュース表示",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/ニュース/,/見る|見せて|見たい|流す|流して/],
    message:"どうぞ",
    messageafter:function(sender,event,param) {
        document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
        var date = new Date();
        YouTubeplayer_start("nhk 朝のニュース");
        //前ゼロなし日付だと予想と異なるものが表示される。前ゼロ付きスラッシュ日付だと、うまく再生できなくなる。
        //YouTubeplayer_start("nhk ニュース " + formatYMD(date));
    },
},
//朝のニュースを止める音声キーを追加する
{
    label: "StopNews",
    labelname: "ニュース停止",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/ニュース/,/止める|止めて|やめる|やめて|終わり|終了/],
    messageafter:function(sender,event,param) {
        YouTubeplayer_stop();
    },
},
//天気予報を呼び出す音声キーを追加する
{
    label: "ShowWeatherForecast",
    labelname: "天気予報表示",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/天気/,/教えて|見る|見せて|見たい/],
    message:"どうぞ",
    messageafter:function(sender,event,param) {
        document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
        var date = new Date();
        YouTubeplayer_start("全国の天気予報 朝");
    },
},
//天気予報を止める音声キーを追加する
{
    label: "StopWeatherForecast",
    labelname: "天気予報停止",                //ラベル名称、現在のモード読み上げ等に使用
    word:[/天気/,/止める|止めて|やめる|やめて|終わり|終了/],
    messageafter:function(sender,event,param) {
        YouTubeplayer_stop();
    },
},

余談:YoutubePlayerAPIにスラッシュ編集の日付をキーワードとして引き渡すと、うまく引き当ててくれない

ニュースにしても天気予報にしても当日の日付が必要だろうと、スラッシュ編集した(つまり'2018/05/16’のような書式ですね)日付をキーワードに引き渡したところ、なぜかうまく動画が表示されません。
YoutubePlayerの枠は表示されるのですが、どうやらキーワード検索が出来ていないようです。
もし、解決方法など詳しい方がいらっしゃいましたら、コメントいただければ幸いです。

サンプルコード

最後に、今回作成したサンプルプログラムの全文を記載しておきます。

サンプルコード
<!DOCTYPE html>
<html>
<head>
    <title>魔法の鏡</title>
    <script src="https://code.jquery.com/jquery-3.0.0.js"></script>
    <script src="simpleai-0.1.0.min.enc.js"></script>
    <script type="text/javascript" src="https://www.youtube.com/iframe_api"></script>
<script>
//------------------------------------------------------------------------------------------------------------------------
//起動時処理
window.onload = function () {
    var SimpleAI = new denaripamSimpleAI(
        this,
        {},
        {
            initCamera:true,
            initMicrophone:true,
            VoiceRecognition:{listen:true},

//-----uriBase、APIキーを設定してください START-----
            MicrosoftAzureFaceAPI:true,
            MicrosoftAzureFaceAPIuriBase:"",                                            //FaceAPIのエンドポイントを入力
            MicrosoftAzureFaceAPIsubscriptionKey:"",                                    //FaceAPIのキー②を入力
            MicrosoftAzureFaceAPIparams:{
                "returnFaceAttributes": "gender,age,glasses,facialHair,makeup",         //取得したい情報をここで指定する
            },

            MicrosoftBingSpeechAPIREST:true,
            MicrosoftBingSpeechAPIRESTuriBase:"https://speech.platform.bing.com/speech/recognition/<RECOGNITION_MODE>/cognitiveservices/v1?language=<LANGUAGE_TAG>&format=<OUTPUT_FORMAT>",     //※※※※変更不要※※※※
            MicrosoftBingSpeechAPIsubscriptionKey:"",                                   //BingSpeechAPIのキー②を入力

            MicrosoftAzureComputerVisionAPI:true,
            MicrosoftAzureComputerVisionAPIuriBase:"",                                  //ComputerVisionAPIのエンドポイントを入力

            MicrosoftAzureComputerVisionAPIsubscriptionKey:"",                          //ComputerVisionAPIのキー①を入力

//-----uriBase、APIキーを設定してください END-----
        },
    );
//-----------------------------------------------
    //情報表示用
    var msg="";
    //現在日時のタイマー起動
    setInterval('showClock()',1000);

    if(SimpleAI) {
        //スマートエージェント開始
        SimpleAI.SmartAgent();

        //AIの応答の言葉を変更する
        SimpleAI.param.SmartAgent.Prompt = "かしこまりました、";
        //AIの語尾の言葉を変更する
        SimpleAI.param.SmartAgent.PromptEnd = "、ご主人様";

        //人物判断(スマートエージェントコマンド追加サンプル)
        var cmd;
        cmd=SimpleAI.getSmartAgentCommand();
        cmd.MainCommand.push(
            {
                //人物判断の音声キーを追加する
                label: "PersonalJudgment",
                labelname: "人物判断",              //ラベル名称、現在のモード読み上げ等に使用
                word:[/メイク|make|化粧|けしょう|仕上げ/,/check|確認|判断|判定|見て/],
                message:"しばらくお待ちください",
//              word:[/人物/,/判断/],
//              message:"人物判断を行います",
                messageafter:function(sender,event,param) {
                    SimpleAI.Personinformation(     //人物判断処理
                        {
                            done:function(data) {
                                msg = "";
                                var output=document.getElementById("denaripamSimpleAI_responseTextArea");
                                if(output) {
                                    var responsedata = JSON.parse(output.value);
                                    //判断結果を画面表示用に編集する
                                    if(responsedata[0]) {
                                        if(responsedata[0].faceAttributes.gender){
                                            if(responsedata[0].faceAttributes.gender=='female'){
                                                msg = msg + "性別:女性" + '<br>';
                                            } else {
                                                msg = msg + "性別:男性" + '<br>';
                                            }
                                        }
                                        if(responsedata[0].faceAttributes.age){
                                            msg = msg + "年齢:" + responsedata[0].faceAttributes.age + '<br>';
                                        }
                                        if(responsedata[0].faceAttributes.glasses){
                                            if(responsedata[0].faceAttributes.glasses=='NoGlasses'){
                                                msg = msg + "眼鏡:なし" + '<br>';
                                            } else {
                                                msg = msg + "眼鏡:あり" + '<br>';
                                            }
                                        }
                                        if(responsedata[0].faceAttributes.makeup.eyeMakeup){
                                            msg = msg + "アイメイク:あり" + '<br>';
                                        } else {
                                            msg = msg + "アイメイク:なし" + '<br>';
                                        }
                                        if(responsedata[0].faceAttributes.makeup.lipMakeup){
                                            msg = msg + "リップメイク:あり" + '<br>';
                                        } else {
                                            msg = msg + "リップメイク:なし" + '<br>';
                                        }
                                        document.getElementById("dispMsg").innerHTML = msg;
                                    } else {
                                        msg = "認識できませんでした。明るい所で鏡に映るようにして下さい。";
                                    }
                                } else {
                                    msg = "認識できませんでした。明るい所で鏡に映るようにして下さい。";
                                }
                                document.getElementById("dispMsg").innerHTML = msg;
                            },
                            fail:function(errstring) {
                                msg = "APIサービスが無効です。";
                                document.getElementById("dispMsg").innerHTML = msg;
                                //alert("NG!!" + errstring);
                            },
                        },
                    );
                },
            },
            //音楽をかける音声キーを追加する
            {
                label: "PlayMusics",
                labelname: "音楽をかける",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/音楽|mugic|曲/,/かける|かけて|流す|流して|きく|きかせて|ききたい/],
                message:"こちらの曲をどうぞ",
                messageafter:function(sender,event,param) {
                    document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
                    YouTubeplayer_start("やる気の出る クラシック音楽 ピアノBGM");
                },
            },
            //音楽を止める音声キーを追加する
            {
                label: "StopMusics",
                labelname: "音楽を止める",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/音楽|mugic|曲/,/止める|止めて|やめる|やめて|終わり|終了/],
                messageafter:function(sender,event,param) {
                    YouTubeplayer_stop();
                },
            },
            //朝のニュースを呼び出す音声キーを追加する
            {
                label: "ShowNews",
                labelname: "ニュース表示",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/ニュース/,/見る|見せて|見たい|流す|流して/],
                message:"どうぞ",
                messageafter:function(sender,event,param) {
                    document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
                    var date = new Date();
                    YouTubeplayer_start("nhk 朝のニュース");
                    //前ゼロなし日付だと予想と異なるものが表示される。前ゼロ付きスラッシュ日付だと、うまく再生できなくなる。
                    //YouTubeplayer_start("nhk ニュース " + formatYMD(date));
                },
            },
            //朝のニュースを止める音声キーを追加する
            {
                label: "StopNews",
                labelname: "ニュース停止",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/ニュース/,/止める|止めて|やめる|やめて|終わり|終了/],
                messageafter:function(sender,event,param) {
                    YouTubeplayer_stop();
                },
            },
            //天気予報を呼び出す音声キーを追加する
            {
                label: "ShowWeatherForecast",
                labelname: "天気予報表示",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/天気/,/教えて|見る|見せて|見たい/],
                message:"どうぞ",
                messageafter:function(sender,event,param) {
                    document.getElementById("dispYTPlayer").innerHTML = html_temp_modal;
                    var date = new Date();
                    YouTubeplayer_start("全国の天気予報 朝");
                },
            },
            //天気予報を止める音声キーを追加する
            {
                label: "StopWeatherForecast",
                labelname: "天気予報停止",                //ラベル名称、現在のモード読み上げ等に使用
                word:[/天気/,/止める|止めて|やめる|やめて|終わり|終了/],
                messageafter:function(sender,event,param) {
                    YouTubeplayer_stop();
                },
            },
        );
    }
//--------------------------------------------
};
//--------------------------------------------
//現在日時表示
function showClock(){
    var now = new Date();
    document.getElementById("dispClock").innerHTML = now.toLocaleString();
}
//--------------------------------------------
//youtube
var YouTubeplayer;
var YouTubeIframeAPI=false;
 function onYouTubeIframeAPIReady() {
    YouTubeIframeAPI=true;
}
//youtube表示ウィンドウ
var html_temp_modal = 
     '<!-- YoutubePlayer -->'
    +'<div class="embed-responsive embed-responsive-16by9">'
    +'  <div class="embed-responsive-item" id="player"></div>'
    +'</div>';
//youtube起動
var YouTubeplayer_start=function(keyword,volume) {
    if(YouTubeIframeAPI) {
        YouTubeplayer_stop();
        YouTubeplayer = new YT.Player('player', {
            height: '150',
            width: '200',
            controls: 2,        //コントロールの表示
            iv_load_policy: 3,  //アノテーション非表示
            showinfo: 0,        //インフォメーション非表示
            events: {
                onReady: function(event){
                    if(keyword) YouTubeplayer.loadPlaylist({listType:"search",list:keyword,});
                    if(volume)  YouTubeplayer.setVolume(100);
                },
            },
        });
    }
};
//youtube停止
var YouTubeplayer_stop=function() {
    if(YouTubeplayer)YouTubeplayer.destroy();
};
//--------------------------------------------
//前ゼロ付き日付変換
function formatYMD(date){
    if (date){
        var yyyy = date.getFullYear();
        var mm = ("0"+ (date.getMonth()+1) ).slice(-2); // 前ゼロ付き2桁
        var dd = ("0"+date.getDate()).slice(-2);        // 前ゼロ付き2桁
        return yyyy + '年' + mm + '月' + dd + "日";
    }
};
//------------------------------------------------------------------------------------------------------------------------
</script>
<style>/** CSS:Area */
/* 鏡フレーム */
.img-over-top {
    position: absolute;
    z-index: 1;
}
/* 鏡本体 */
.video-wrap {
  position: relative;

}
/* 時計表示部 */
.clock-over-top {
    background: #cbb994;
    color: #eaf4fc;
    font-family: serif;
    font-size: 100%;
    position: absolute;
    left: 2%;
    top: 2%;
    z-index: 1;
    padding-left: 5px; padding-right: 5px;
}
/* 情報表示部 */
.msg-over-top {
    background: #cbb994;
    color: #eaf4fc;
    font-family: serif;
    font-size: 80%;
    position: absolute;
    left: 2%;
    top: 7%;
    z-index: 1;
    padding-left: 5px; padding-right: 5px;
}
/* YoutubePlayer表示部 */
.youtube-over-top {
    opacity: 0.5;   /* 対象の透過度(0:完全透明 1:不透明) */
    position: absolute;
    left: 580px;
    top: 2%;
    z-index: 1;
    padding-left: 5px; padding-right: 5px;
}
</style>
</head>
<body>
<img class="img-over-top" src="fl_001.png" width="800px" height="600px">
<p class="clock-over-top" id="dispClock"><script>showClock();</script></p>
<p class="msg-over-top" id="dispMsg"></p>
<p class="youtube-over-top" id="dispYTPlayer"></p>
<div class="video-wrap">
  <video id="denaripamControlSensor_video" width="800px" height="600px" controls autoplay>
  </video>
</div>
<div hidden id="denaripamSimpleAI_responseRect"></div><br>
<textarea hidden id="denaripamSimpleAI_responseTextArea" class="UIInput" style="width:580px; height:400px;"></textarea><br>
</body>
</html>

最後に

今回はここまでです。お疲れ様でした。

数回に分けて掲載してきた「AI連携FW『シンプルエーアイ』を使ってみた」、如何でしたか?
まだ前書きの冒頭で書いた機能が残っているのですが、『シンプルエーアイ』に関する大まかな機能や使い方はご紹介できましたので、これで一区切りとさせていただきます。

また日を改めて、新しい記事を投稿することもあるやもしれません。その際はお付き合いいただければ幸いです。
記事をご覧下さった皆さま、また記事に関してご指摘下さった方々、有難うございました。