日曜プログラマーのための「Clovaスキルつくり隊!」 第4回
音楽を利用するプログラミングを学ぼう
子供も一緒に楽しめるゲーム「椅子取りゲーム」スキルをスマートスピーカー用につくってみよう
2019年07月26日 11時00分更新
というわけで、さっそく見て行きましょう。できあがったのがこちらのスキルです。
ソースコードはこちら(リスト1)。Node.js(サーバー側でJavaScriptを使う言語)で書かれています。
const clova = require('@line/clova-cek-sdk-nodejs');
const express = require('express');
const music = [
'music1.mp3',
'music2.mp3',
'music3.mp3',
'music4.mp3',
'music5.mp3',
];
const clovaSkillHandler = clova.Client
.configureSkill()
//起動時
.onLaunchRequest(responseHelper => {
responseHelper.setSpeechList([
{
lang: 'ja',
type: 'PlainText',
value: '秒数指定もできちゃう、いす取りゲームを起動しました。いすの周りをみんなで回り、音楽が止まったら、いすに座って取り合うゲームです。音楽が止まってから、次のゲームまでは30秒のインターバルがあります。'
},
{
lang: 'ja',
type: 'PlainText',
value: '最初に、音楽の最大再生時間を設定します。10秒から3分までの時間を言ってください。'
}
]);
})
//ユーザーからの発話が来たら反応する箇所
.onIntentRequest(async responseHelper => {
const intent = responseHelper.getIntentName();
switch (intent) {
case 'ChairsIntent':
//①セッション情報から最大再生時間を取得
const session = responseHelper.getSessionAttributes();
const max_time = session['time'] ? session['time'] : 30000;
//②5000~〇ミリ秒
const duration_time = Math.floor(Math.random() * (max_time + 1 - 5000)) + 5000;
//ランダムで音楽を選定
const music_number = Math.floor(Math.random() * music.length);
//③音楽再生
responseHelper.responseObject.response.directives = [
{
header: {
namespace: 'AudioPlayer',
name: 'Play'
},
payload: {
audioItem: {
stream: {
beginAtInMilliseconds: 0,
durationInMilliseconds: duration_time,
url: music[music_number],
urlPlayable: true
}
},
playBehavior: 'REPLACE_ALL'
}
}
];
break;
case 'TimeConfIntent':
const numberslot_min = responseHelper.getSlot('NumberSlotMin');
const timeslot_min = responseHelper.getSlot('TimeSlotMin');
const numberslot_sec = responseHelper.getSlot('NumberSlotSec');
const timeslot_sec= responseHelper.getSlot('TimeSlotSec');
let time_min = 0;
let time_sec = 0;
let speech = '';
if (numberslot_min && timeslot_min) {
time_min = numberslot_min;
if (timeslot_min === '分') {
time_min *= 60000;
} else {
time_min *= 1000;
}
}
if (numberslot_sec && timeslot_sec) {
time_sec = numberslot_sec;
if (timeslot_sec === '分') {
time_sec *= 60000;
} else {
time_sec *= 1000;
}
}
const time = time_min + time_sec;
if (time === 0) {
speech = '最大再生時間は、10秒から3分までの時間を指定してください。';
} else if (time < 10000 || time > 60000 * 3) {
speech = '最大再生時間は、10秒以上、3分以内の時間を指定してください。';
} else {
//セッション情報の保存
responseHelper.setSessionAttributes({'time':time});
speech = '時間を設定しました。ゲームを開始するには、スタートと言ってください';
}
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: speech
});
break;
case 'Clova.GuideIntent':
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'いすの周りをみんなで回り、音楽が止まったらいすに座って取り合うゲームです。音楽が止まってから、次のゲームまでは30秒のインターバルがあります。ゲームを開始するには、スタート、といってみてください。最大再生時間を設定するには、10秒から3分までの時間を言ってください。'
});
break;
case 'Clova.FallbackIntent':
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'ゲームを開始するには、スタート、といってみてください。'
});
break;
}
console.log('Intent:' + intent);
})
.onEventRequest(async responseHelper => {
const event_namespace = responseHelper.requestObject.request.event.namespace;
const event_name = responseHelper.requestObject.request.event.name;
switch (event_namespace) {
case 'AudioPlayer':
switch (event_name) {
//④再生終了時に無音を流す
case 'PlayFinished':
responseHelper.setSpeechList(
[
{
lang: '',
type: 'URL',
value: 'muon.mp3'
},
{
lang: 'ja',
type: 'PlainText',
value: 'ゲームを開始するには、スタート、といってください。'
}
]);
//リプロンプト
responseHelper.setSimpleSpeech({
lang: 'ja',
type: 'PlainText',
value: 'ゲームを開始するには、スタート、といってください。'
}, true);
break;
default:
break;
}
break;
default:
break;
}
})
//終了時
.onSessionEndedRequest(responseHelper => {
})
.handle();
//ポート3000番で起動しリクエスト待受
const app = new express();
const port = process.env.PORT || 3000;
//applicationIdの検証、基本情報のExtension IDを入力
const clovaMiddleware = clova.Middleware({applicationId: 'YOUR_APPLICATION_ID'});
//ルートディレクトリ配下の本ディレクトリを指定
app.post('/PATH/TO/DEV', clovaMiddleware, clovaSkillHandler);
app.listen(port, () => console.log(`Server running on `));
どんな命令が実行されているかは、「//」で始まる行に書いてあるコメントを参照してください。
それでは、今回のプログラムのキモになる部分を少し詳しくみていきましょう。
スキルづくりのワンポイントテク
スキルの中で音楽を再生する
今回のスキルのワンポイントは、スキルの中で音楽を再生する方法です。
ここでは、プログラムソースコード内のコメント番号①~④について説明していきます。
①セッション情報を取得する
最大再生時間をTimeConfIntentで設定を行い、設定された秒数の取得を行います。秒数設定を行わなかった場合は30秒が最大再生時間となっています。
const session = responseHelper.getSessionAttributes();
const max_time = session['time'] ? session['time'] : 30000;
②時間をランダムに設定する
①で取得した最大再生時間をもとにランダムで音楽終了時間を求めます。
const duration_time = Math.floor(Math.random() * (max_time + 1 - 5000)) + 5000;
③音楽を再生する
AudioPlayerを使い音楽を再生します。
音楽を再生するには下記のコードでもできますが、秒数指定などはできません。
responseHelper.setSimpleSpeech({
lang: '',
type: 'URL',
value: 'music.mp3'
});
AudioPlayerを使えば、秒数指定や一時停止といったことができます。秒数の指定を行うには、ストリーミング情報を送信する必要があります。beginAtInMillisecondsで再生開始時間を設定し、durationInMillisecondsで再生終了時間を設定します。今回のコードでは0秒から②で求めた秒数まで音楽を再生します。
④再生終了時に無音の音楽を流す
AudioPlayerには様々なイベントが用意されており、一時停止や再生開始などを知らせてくれます。今回は再生終了時を知らせてくれるPlayFinishedイベントを使います。
音楽終了時に数秒間応答がないとスキルが終了してしまいます。そのためすぐにスキルが終了しないためにPlayFinishedイベントで、無音の音楽を流す処理となっています。
case 'PlayFinished':
responseHelper.setSpeechList(
[
{
lang: '',
type: 'URL',
value: 'muon.mp3'
},
{
lang: 'ja',
type: 'PlainText',
value: 'ゲームを開始するには、スタート、といってください。'
}
]);
スキルづくりのワンポイントテクその2
AudioPlayerの設定
AudioPlayerを使用するためには、サーバー設定の「AudioPlayer利用の有無」に「はい」をチェックすることで使用できます。
今回のプログラムでは、music1~music5という5つの音楽ファイルのうち、ランダムにどれか1曲が再生されるようになっています。この利用するmp3ファイルを入れ替えることで、自分の好きな曲で椅子取りゲームを楽しめるように改造することもできますね。
この連載では、これからも面白いスキルをジャンジャンつくっていくので、みんなもぜひ挑戦してみてくださいね!
この連載の記事
-
第6回
デジタル
鳴った音の音階を当てる「絶対音感ゲーム」スキルをつくってみよう -
第5回
デジタル
読み手をClovaにやってもらう「江戸いろはかるた」スキルをつくってみよう -
第3回
デジタル
パーティーゲームの定番「ビンゴ」スキルをスマートスピーカー用につくってみよう -
第2回
デジタル
1日が楽しくなる「おみくじ」スキルをスマートスピーカー用につくってみよう -
第1回
デジタル
むかしの時刻を返す、スマートスピーカー用スキルをつくってみよう - この連載の一覧へ