Smart Communication Design Company
ホーム > ナレッジ > Blog > フロントエンドBlog

フロントエンドBlog

Webのフロントエンドを構成する技術、特にHTMLやCSS、JavaScript、またそれらに関連する話題を扱うBlogです。

Google Chrome 61の搭載予定機能

UI開発者 泉口

PWA関連の情報を追って行く中でブラウザの最新情報は欠かせません。
Microsoft EdgeにおけるService Workerの実装も着々と進む中、9月13日に行われるMicrosoft Edge Web Summit 2017の告知ではPWAに関連する内容が言及され、最新版のEdgeではabout:flagsから試験的にService Workerを試せるようになるなど、ますますPWAへの期待が高まっていると感じています。

さて、PWA提唱元のGoogleはどうでしょうか、今回はWhat's New In DevTools (Chrome 61)から、Google Chrome 61の搭載予定機能の一部を見てみようと思います。

全文を読む

Alexa Skillをローカルで開発しよう

UI開発者 加藤

2017年5月にAmazonは「Amazon Echo Show」というデバイスを発表しました。このデバイスは音声による操作が可能で、たとえば「Alexa, call Dad.」と頼めば父親にテレビ電話をかけることができ、「Alexa, what's the weather this week?」と尋ねれば今週の天気を表示してくれます。

このシステムは裏側で「Amazon Alexa」(以下、Alexa)という音声認識AIアシスタントが発話を分析し、その結果に対して「スキル」と呼ばれるアプリケーションを実行することで実現されています。2017年7月現在、15,000を超えるスキルが公開されています。どんなスキルがあるのかはAlexa Skillsのページに掲載されているので興味がある方はご覧ください。

今回はそのスキルをローカルで開発する方法についてご紹介いたします。まず前提知識として知っておきたいのが下記の3つです。

スキルを実際に公開する際はこの3つの要素をアマゾンアプリ開発者ポータル上で定義する必要があります。それぞれの要素について簡単に説明していきます。

インテント

インテントはユーザーの発話に含まれるユーザーの要求を満たすアクションを表します。たとえば天気を取得するインテント「GetWeather」や、音楽を再生するインテント「PlayMusic」というように定義します。各インテントには「スロット」が含まれる場合があります。スロットとは発話の中で変化する可能性がある部分をさします。今日の新宿の天気を尋ねるときの一文を例として見てみましょう。

Alexa, ask Daily Weather for the weather of Shinjuku today.

「Daily Weather」はスキルの名前です。この例において「Shinjuku」や「today」はスロットとして定義するのが適しています。当然ユーザーは新宿区だけでなく品川区の天気を知りたい場合もありますし、今日ではなく明日の天気を知りたい場合もあるからです。インテントとスロットは下記のようにJSON形式で定義します。

{
    "intents": [
        {
            "intent": "GetWeather",
            "slots": [
                {
                    "name": "Date",
                    "type": "AMAZON.DATE"
                },
                {
                    "name": "Location",
                    "type": "LIST_OF_WARD"
                }
            ]
        }
    ]
}

GetWeather」というインテントに対して先ほど説明した二つのスロットが定義されており、各スロットに対してはタイプが指定されています。Dateスロットに指定されている「AMAZON.DATE」はAmazonがあらかじめ用意してくれているビルトインタイプです。Locationスロットに指定されている「LIST_OF_WARD」はこの後説明するカスタムロットタイプにあたるもので開発者が新しく定義するタイプです。

カスタムスロットタイプ

ビルトインタイプでカバーされていないものについてはカスタムスロットタイプとして新しく定義する必要があります。先にあげた「LIST_OF_WARD」の場合は東京23区の各名称を定義します。

※現状アメリカやヨーロッパの都市名はビルトインタイプとして存在しているのですが、アジアの都市はまだ用意されていないようでしたので、カスタムスロットタイプとして取り上げました。いずれはアジアの都市もビルトインタイプとして定義されると思います。

サンプルの発話

最後にサンプルの発話です。一つのサンプルは一つのインテントと紐付ける必要があります。

GetWeather how is the weather of {Sign}
GetWeather how will the weather of {Sign} be on {Date}
GetWeather get the weather

最初に対応するインテント名を明記し、スペースもしくはタブで区切った後に文章を明記していきます。このときスロットになる部分は波括弧{}で囲います。天気を取得するだけでもたくさんのパターンが考えられますので、ユーザーが天気を知りたいときに使いそうなフレーズを洗い出します。このサンプルの数が多ければ多いほどAlexaの認識の精度が向上すると言ってよいでしょう。

スキルを開発する際はこの3つの要素がどれだけ正確に、そして豊富に定義されているかが重要になってきます。

ローカルで開発する方法

さて、基本となる要素が分かったところで、ローカルで開発する方法を説明していきます。まずはAlexaJSというコミュニティが公開しているリポジトリをダウンロードし展開します。

git clone https://github.com/matt-kruse/alexa-app-server.git

/examples/apps配下に実際のスキルのコードを配置していきます。今回はSpotifyのWeb APIを用いてプレイリストを再生するスキル「SpotifyPlayer」をつくってみました。ディレクトリ構造は下記のようになります。

/examples/apps/SpotifyPlayer/
                    ├ index.js //各インテントに対する処理を記述するファイル
                    ├ SpotifyPlayer.js //Spotify APIと連携するモジュール
                    ├ package.json

package.jsonには依存モジュールとして「alexa-app」をインストールしておきます。Spotify APIとの連携の方法はSpotify Web APIのページにリファレンスがありますので今回は省略させていただきます。

index.jsの中身は下記のようになっています。

'use strict';
module.change_code = 1;
var _ = require('lodash');
var Alexa = require('alexa-app');
var app = new Alexa.app('SpotifyPlayer');
var Player = require('./SpotifyPlayer');
var _player = new Player();

// スキルを立ち上げたときの処理
app.launch(function(req, res) {
    var prompt = 'I\'m ready to control audio player on spotify.';
    res.say(prompt);
});

// インテントの処理
app.intent('playPlaylist', {
        'slots': {
            'PLAYLISTNAME': 'AMAZON.MusicPlaylist'
        },
        'utterances': ['{|play|resume} {|playlist} {-|PLAYLISTNAME}']
    }, function(req, res) {
        var playlistName = req.slot('PLAYLISTNAME');
        var response = res;
        var reprompt = 'Tell me a playlist name to get play your playlist.';

        // プレイリスト名が空の場合に実行される。
        if (_.isEmpty(playlistName)) {
            var prompt = 'I didn\'t hear a playlist name. Tell me an playlist name.';
            response.say(prompt).reprompt(reprompt).shouldEndSession(false);
            return true;
        } else {
            return _player.getPlaylist(playlistName).then(function(response) {
                // プレイリストの再生が成功したときに実行される。
                res.say('I\'ll play').send();
            }).catch(function(err) {
                // 指定のプレイリストが存在しない場合などに実行される
                var prompt = 'I didn\'t have playlist data of ' + playlistName;
                res.say(prompt).reprompt(reprompt).shouldEndSession(false).send();
            });
        }
    }
);

module.exports = app;

examples配下にあるserver.jsをコマンドから実行し、ブラウザでlocalhostにアクセスすると下記のようにリクエストやスキーマが表示されます。(一部省略しています。)

まずRequestのType項目で「IntentRequest」を選択します。その下のIntent項目で実装したインテント「playPlaylist」を選択し、Send Requestをクリックすると、app.intent('playPlaylist')の部分が実行され、その結果がResponseの項目に表示されます。

このコードではプレイリストが聞き取れなかった(ユーザーが何も発しなかった)場合、誤ったプレイリスト名を再生しようとした場合、再生に成功した場合の3パターンの処理を記述しています。res.say()reprompt()は実際にAlexaが発話する部分です。

PLAYLISTNAMEスロットのタイプとして指定している「AMAZON.MusicPlaylist」はビルトインタイプで、「work out」や「dance」といった一般的な音楽プレイリスト名が定義されています。その他のビルトインタイプについてはSlot Type Referenceのページに掲載されています。

また、app.intentの引数に「utterances」を指定しておくと、先ほど説明したサンプルの発話を自動で生成してくれます。この機能はAlexa Utterance Generatorの機能を使用したものでブラウザ上でも使用することが可能です。

以上でローカルでの開発は終了です。いきなりクラウドに展開して開発していくよりも、今回のようにまずはローカルで開発することで短時間でより多くのテストが可能になり、より品質の高いスキルを提供できると思います。またインテントやスロットタイプ、サンプルの発話も既に定義されているので、実際にクラウドに展開するのも容易でしょう。

Alexaはまだ英語とドイツ語にしか対応していませんが、ブラウザで試せるAlexa Skill Testing Toolというツールがありますので、興味があれば試してみてください。日本国内ではデバイスを購入することもできませんが、スキルの開発や公開はもちろん可能ですので日本のおもてなし文化をAlexaにのせて海外にお届けするのもよいかもしれませんね。

第8回MLCマークアップ部 開催レポート

UI開発者 宇賀

当社では日頃から様々な社内勉強会が開催されていますが、今回は07月05日(水)に社内で開催された第8回MLCマークアップ部の様子をお伝えします。

MLCマークアップ部とは?

html5jマークアップ部が開催しているMarkupCafeにインスパイアされ発足した活動です。

「お題」のWFを見ながら、参加者一人一人が自由にマークアップしたものを持ち寄り全員で話し合います。
「正解がない」マークアップの中で「より品質の高いマークアップとは何か」を模索する場です。

この活動は、HTMLの仕様やアクセシビリティ、情報構造化等に対する理解を深めると共に、議論や発表の機会を通じファシリテーション能力を高めることを目的としています。

お題のワイヤーフレーム

さて、今回で8回目となったMLCマークアップ部。お題は「ニュース・お知らせセクション」です。

お題のワイヤーフレーム

枠内が今回の対象範囲です。トップページやニュースのインデックスページなどでよく目にしますね。

たった1つのモジュールやウィジェットだけに注目してもマークアップはそれを設計する人の数だけ異なるソースになると思いますが、果たして今回はどのようになったのでしょうか。

全文を読む

リアルタイムなAMPページを作成する

UI開発者 木村

AMPは表示速度の高速化がメリットで、ユーザーが検索してから表示されるまでの時間を短縮できるのが特徴ですが、AMPには表示後の情報をより速くユーザーに取得させるための方法があります。それは、AMPページのコンテンツをリアルタイムで更新させる方法です。

リアルタイム更新の使用例としては、更新頻度が高い記事やニュース記事のような鮮度が重要となるコンテンツの一覧、スポーツ中継やイベントの様子を発信する特設サイトなどがあげられます。

全文を読む

レシピを見ながら楽しく実装、フォームのアクセシビリティ!その3

UI開発者 宇賀

4月20日、2016年版のWCAG 2.0達成方法集の日本語訳が公開されました。

WCAG 2.0 達成方法集

前回はfieldset要素とlegend要素、2つの要素を適切に用いることでフォームのアクセシビリティを向上させる方法をお伝えしました。

今回は、WCAG 2.0 達成方法集に記載されている「よくある不適合事例」の中からフォームに関連する事例についてご紹介したいと思います。

※ この記事は、以前執筆したレシピを見ながら楽しく実装、フォームのアクセシビリティ!その1レシピを見ながら楽しく実装、フォームのアクセシビリティ!その2の続きです
※ この記事に設置されている入力欄に入力された情報が当社に送信されることはありません
※ 作成したページや、本記事の実装例をVoiceOver(macOS、iOS標準搭載)などのスクリーンリーダーで実際に聴いてみると、より直感的に理解が深まります
※ 一部記事内で最低限の見た目を調整することを目的にstyle属性を用いていますが、実際に実装する場合は外部CSSファイルへの記述を推奨します

全文を読む