6
2

More than 5 years have passed since last update.

ごきげんよう

この記事は
「するめごはんのVUI・スマートスピーカー Advent Calendar 2018」
の13日目の記事です。

ついにきましたね!
Echo Show!

というわけで、さっそく試してみるわけです。

でかい

比較のために500mlの空き缶を添えてますがでかいです。

DSC_1541.JPG

動画とかすごい

映画を観ると特に感じますが、ブラウン管かよってレベルの大きさであるだけ音がすごい良いです。
これはもう今後Echo ShowでPrime VideoやYoutubeを観ます。

スキルたちがより見やすくなる

■キャプテン九九
DSC_1547.JPG

■乙葉の時間
DSC_1568.JPG

■ヒロインの告白
DSC_1574.JPG

ヒロインの告白をAPL対応にしてみる

結果、テストバージョンでこうなってます。

DSC_1575.JPG

環境構築から実装まで、偉大なる @zono_0 さんが既にわかりやすい記事を掲載しています。
いつもありがとうございます。

Alexa Presentation Language(APL)スキル 開発チュートリアル

上記、記事ではask cliが前提ですが、そうでなくてもAPLはもちろん使えます。
同じところは省いて、そうでないところを今回は補完していきます。

1.Amazon Developer Portal

僕は今回開いた際にに右下にデバイス検出エラーがでました。

デバイス検出エラー.png

が、今回は気にしないで大丈夫です。
JSONのフォーマットが欲しいので。

ちなみに、ここで対象のデバイスの大きさを以下のように選べます。

小型ハブと中型ハブ.png

大型ハブと超大型TV.png

2.Lambdaでインラインエディタでも組める

ask cliは僕も使います。
というより、慣れるとそちらの方が開発は大変良いです。
コード管理とかもできますし。

かといって、ask cliの導入に躓く方もいらっしゃるとも思いますので、インラインでがんばってみました。

@zono_0 さんのように、APLのJSONは分割した方が良いと思います。

lambda.png

3.ソースコード

とりあえず起動して動いた段階のソースコードです。

APLでのヒロインの告白のLaunchRequest

'use strict';

const Alexa = require('ask-sdk');


//起動時
const kotoha_smartmacchiato = '<audio src=\"https://s3XXXXXXXXXXXXXX.mp3\" />';

const kotoha_voice = '<audio src=\"https://s3-XXXXXXXXXXXXXX.mp3\" />';


const LaunchRequestHandler = {
  canHandle(handlerInput) {
    return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
  },
  async handle(handlerInput) {

    // ディスプレイ有り(APL対応)の場合
    if (supportsApl(handlerInput)) {
      // APL対応(documentに設定したテンプレートレイアウトを利用し、datasourcesの内容をディスプレイに表示します。)
      handlerInput.responseBuilder
        .addDirective({
          type : 'Alexa.Presentation.APL.RenderDocument',
          version: '1.0',
          document: require('./homepage.json'),
          datasources: require('./data.json')
        });
    }

    const speechText = kotoha_smartmacchiato + kotoha_voice;

    return handlerInput.responseBuilder
      .speak('<speak>' + speechText + '</speak>')
      .reprompt('<speak>' + speechText + '</speak>')
      .withShouldEndSession(false)
      .getResponse();

  }
};


/**
 * ディスプレイサポート(APL対応)判定値
 * @author zono_0    いつもありがとうございます!
 */ 
const supportsApl = (handlerInput) => {
  const hasDisplay =
    handlerInput.requestEnvelope.context &&
    handlerInput.requestEnvelope.context.System &&
    handlerInput.requestEnvelope.context.System.device &&
    handlerInput.requestEnvelope.context.System.device.supportedInterfaces &&
    handlerInput.requestEnvelope.context.System.device.supportedInterfaces['Alexa.Presentation.APL'];

  return hasDisplay;
};

/**
 * Echo Spotで使っていたディスプレイかどうかを判定するfunction
   Echo Showでも引き続き使えますが、今回はAPLを使います
*/
function supportsDisplay(handlerInput) {
  var hasDisplay =
    handlerInput.requestEnvelope.context &&
    handlerInput.requestEnvelope.context.System &&
    handlerInput.requestEnvelope.context.System.device &&
    handlerInput.requestEnvelope.context.System.device.supportedInterfaces &&
    handlerInput.requestEnvelope.context.System.device.supportedInterfaces.Display;

  console.log("Supported Interfaces are" + JSON.stringify(handlerInput.requestEnvelope.context.System.device.supportedInterfaces));
  return hasDisplay;
}

//動かす
exports.handler = Alexa.SkillBuilders.standard()
  .addRequestHandlers(LaunchRequestHandler)
  .lambda();

homepage.json

{
        "type": "APL",
        "version": "1.0",
        "theme": "dark",
        "import": [
            {
                "name": "alexa-layouts",
                "version": "1.0.0"
            }
        ],
        "resources": [
            {
                "description": "Stock color for the light theme",
                "colors": {
                    "colorTextPrimary": "#151920"
                }
            },
            {
                "description": "Stock color for the dark theme",
                "when": "${viewport.theme == 'dark'}",
                "colors": {
                    "colorTextPrimary": "#f0f1ef"
                }
            },
            {
                "description": "Standard font sizes",
                "dimensions": {
                    "textSizeBody": 48,
                    "textSizePrimary": 27,
                    "textSizeSecondary": 23,
                    "textSizeSecondaryHint": 25
                }
            },
            {
                "description": "Common spacing values",
                "dimensions": {
                    "spacingThin": 6,
                    "spacingSmall": 12,
                    "spacingMedium": 24,
                    "spacingLarge": 48,
                    "spacingExtraLarge": 72
                }
            },
            {
                "description": "Common margins and padding",
                "dimensions": {
                    "marginTop": 40,
                    "marginLeft": 60,
                    "marginRight": 60,
                    "marginBottom": 40
                }
            }
        ],
        "styles": {
            "textStyleBase": {
                "description": "Base font description; set color and core font family",
                "values": [
                    {
                        "color": "@colorTextPrimary",
                        "fontFamily": "Amazon Ember"
                    }
                ]
            },
            "textStyleBase0": {
                "description": "Thin version of basic font",
                "extend": "textStyleBase",
                "values": {
                    "fontWeight": "100"
                }
            },
            "textStyleBase1": {
                "description": "Light version of basic font",
                "extend": "textStyleBase",
                "values": {
                    "fontWeight": "300"
                }
            },
            "mixinBody": {
                "values": {
                    "fontSize": "@textSizeBody"
                }
            },
            "mixinPrimary": {
                "values": {
                    "fontSize": "@textSizePrimary"
                }
            },
            "mixinSecondary": {
                "values": {
                    "fontSize": "@textSizeSecondary"
                }
            },
            "textStylePrimary": {
                "extend": [
                    "textStyleBase1",
                    "mixinPrimary"
                ]
            },
            "textStyleSecondary": {
                "extend": [
                    "textStyleBase0",
                    "mixinSecondary"
                ]
            },
            "textStyleBody": {
                "extend": [
                    "textStyleBase1",
                    "mixinBody"
                ]
            },
            "textStyleSecondaryHint": {
                "values": {
                    "fontFamily": "Bookerly",
                    "fontStyle": "italic",
                    "fontSize": "@textSizeSecondaryHint",
                    "color": "@colorTextPrimary"
                }
            }
        },
        "layouts": {},
        "mainTemplate": {
            "parameters": [
                "payload"
            ],
            "items": [
                {
                    "when": "${viewport.shape == 'round'}",
                    "type": "Container",
                    "direction": "column",
                    "width": "100vw",
                    "height": "100vh",
                    "items": [
                        {
                            "type": "Image",
                            "source": "${payload.bodyTemplate3Data.image.sources[0].url}",
                            "scale": "best-fill",
                            "width": "100vw",
                            "height": "100vh",
                            "position": "absolute",
                            "overlayColor": "rgba(0, 0, 0, 0.6)"
                        },
                        {
                            "type": "ScrollView",
                            "width": "100vw",
                            "height": "100vh",
                            "item": [
                                {
                                    "type": "Container",
                                    "direction": "column",
                                    "alignItems": "center",
                                    "paddingLeft": 30,
                                    "paddingRight": 30,
                                    "paddingBottom": 200,
                                    "items": [
                                        {
                                            "type": "AlexaHeader",
                                            "headerAttributionImage": "${payload.bodyTemplate3Data.logoUrl}",
                                            "headerTitle": "${payload.bodyTemplate3Data.title}"
                                        },
                                        {
                                            "type": "Text",
                                            "text": "<b>告白と言えば</b> | <b>やはり学校ですよね</b>",
                                            "style": "textStylePrimary",
                                            "color": "#4dd2ff",
                                            "width": "90vw",
                                            "textAlign": "center"
                                        },
                                        {
                                            "type": "Text",
                                            "text": "<b>${payload.bodyTemplate3Data.textContent.title.text}</b>",
                                            "style": "textStyleBody",
                                            "width": "90vw",
                                            "textAlign": "center"
                                        },
                                        {
                                            "type": "Text",
                                            "text": "${payload.bodyTemplate3Data.textContent.subtitle.text}",
                                            "style": "textStylePrimary",
                                            "width": "90vw",
                                            "textAlign": "center"
                                        },
                                        {
                                            "type": "Text",
                                            "text": "${payload.bodyTemplate3Data.textContent.primaryText.text}",
                                            "paddingTop": 40,
                                            "style": "textStylePrimary",
                                            "width": "90vw",
                                            "textAlign": "center"
                                        },
                                        {
                                            "type": "Text",
                                            "text": "${payload.bodyTemplate3Data.textContent.bulletPoint.text}",
                                            "paddingTop": 50,
                                            "style": "textStylePrimary",
                                            "width": "90vw",
                                            "textAlign": "center"
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                },
                {
                    "type": "Container",
                    "width": "100vw",
                    "height": "100vh",
                    "items": [
                        {
                            "type": "Image",
                            "source": "${payload.bodyTemplate3Data.backgroundImage.sources[0].url}",
                            "scale": "best-fill",
                            "width": "100vw",
                            "height": "100vh",
                            "position": "absolute"
                        },
                        {
                            "type": "AlexaHeader",
                            "headerTitle": "${payload.bodyTemplate3Data.title}",
                            "headerAttributionImage": "${payload.bodyTemplate3Data.logoUrl}"
                        },
                        {
                            "type": "Container",
                            "direction": "row",
                            "paddingLeft": 40,
                            "paddingRight": 72,
                            "grow": 1,
                            "items": [
                                {
                                    "type": "Image",
                                    "source": "${payload.bodyTemplate3Data.image.sources[0].url}",
                                    "width": 340,
                                    "height": 360,
                                    "scale": "best-fit",
                                    "align": "center"
                                },
                                {
                                    "type": "ScrollView",
                                    "height": "60vh",
                                    "shrink": 1,
                                    "item": [
                                        {
                                            "type": "Container",
                                            "items": [
                                                {
                                                    "type": "Text",
                                                    "text": "<b>やはり告白と言えば学校ですよね</b>",
                                                    "style": "textStylePrimary",
                                                    "color": "#4dd2ff"
                                                },
                                                {
                                                    "type": "Text",
                                                    "text": "<b>${payload.bodyTemplate3Data.textContent.title.text}</b>",
                                                    "style": "textStyleBody"
                                                },
                                                {
                                                    "type": "Text",
                                                    "text": "${payload.bodyTemplate3Data.textContent.subtitle.text}",
                                                    "style": "textStylePrimary"
                                                },
                                                {
                                                    "type": "Text",
                                                    "text": "${payload.bodyTemplate3Data.textContent.primaryText.text}",
                                                    "paddingTop": 40,
                                                    "style": "textStylePrimary"
                                                },
                                                {
                                                    "type": "Text",
                                                    "text": "${payload.bodyTemplate3Data.textContent.bulletPoint.text}",
                                                    "paddingTop": 50,
                                                    "style": "textStylePrimary"
                                                }
                                            ]
                                        }
                                    ]
                                }
                            ]
                        }
                    ]
                }
            ]
        }
}

data.json

{
        "bodyTemplate3Data": {
            "type": "object",
            "objectId": "bt3Sample",
            "backgroundImage": {
                "contentDescription": null,
                "smallSourceUrl": null,
                "largeSourceUrl": null,
                "sources": [
                    {
                        "url": "https://s3-学校画像.png",
                        "size": "small",
                        "widthPixels": 0,
                        "heightPixels": 0
                    },
                    {
                        "url": "https://s3-学校画像.png",
                        "size": "large",
                        "widthPixels": 0,
                        "heightPixels": 0
                    }
                ]
            },
            "title": "APLを使って Echo Show で学校で(?)告白されよう!",
            "image": {
                "contentDescription": null,
                "smallSourceUrl": null,
                "largeSourceUrl": null,
                "sources": [
                    {
                        "url": "https://s3-結城琴葉画像.png",
                        "size": "small",
                        "widthPixels": 0,
                        "heightPixels": 0
                    },
                    {
                        "url": "https://s3-結城琴葉画像.png",
                        "size": "large",
                        "widthPixels": 0,
                        "heightPixels": 0
                    }
                ]
            },
            "textContent": {
                "title": {
                    "type": "PlainText",
                    "text": " ヒロイン(結城琴葉)の告白"
                },
                "subtitle": {
                    "type": "PlainText",
                    "text": " 告白メッセージ"
                },
                "primaryText": {
                    "type": "PlainText",
                    "text": " 私、あなたが好きです。世界中の誰よりも・・あなたのことが、本当に好きなんです!私と・・付き合ってください. "
                },
                "bulletPoint": {
                    "type": "PlainText",
                    "text": " 結城琴葉ちゃんから告白されてみよう! "
                }
            },
            "logoUrl": "https://s3-スキルのロゴ.png",
            "hintText": "アレクサ、「ヒロインの告白」を開いて"
        }
    }

まとめ

ask cliで躓いても、なんとかなります。
現時点では僕はこれが実機で動いたレベルですが、APLを使いこなせるようになるとそれだけで職業になる気がします。

以上

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2