Alexa APL for Audio (APL-A) をスキルに実装する

# APL for Audio (APLA) 

APL for Audioは、Alexaデバイスの新しいオーディオミキシング機能で、APLAドキュメント形式を使用してデバイスに音声レスポンスを送信するもの。
APLAは、APLコンポーネントを使用してオーディオを定義することができ、すべてのAlexaデバイスでAPLAを再生できる。

※2021.7.21のAlexa Liveで一般公開され、**<font color="OrangeRed">.addDirectiveToRepromptが追加され、リプロンプト</font>**でもAPLAが使えるようになった。さらにサンプルレートが、44.1kHzから48kHzに変更された。

> <b>APL for Audio (APLA) is Now Generally Available</b>
Launched as a Public Beta at last year’s Alexa Live, APLA is now generally available (GA)! We want to thank everyone who participated in the beta and for the feedback you provided to make the service better. GA is an important milestone but, as Amazonians like to say, it’s still day one. We’re still working on a lot of new features and even have a couple to announce today!


### オーディオファイルのフォーマット

以下のフォーマットをサポートしている。

|No.|フォーマット|
|:--|:--|
|1|aac|
|2|mp3|
|3|ogg|
|4|opus|
|5|wav|

### オーディオファイルの要件

以下の要件を満たしていないと再生されない。
満たしていない場合は、FFmpegやフリーのオーディオ変換サイトで簡単に変換することができる。

|No.|項目|要件|
|:--|:--|:--|
|1|ビットレート|1411.20 kbps 以下|
|2|サンプルレート|48kHz 以下|
|3|ファイルサイズ|10MB 以内|
|4|長さ|240秒 以内|

### オーディオファイル数

１回のリクエストで使用できるオーディオファイルは15ファイルまで。
１つのAPLA内に使用できるオーディオファイルの最大が15ファイルということ。


### APLAコンポーネント
APLAは、次のプリミティブコンポーネントをサポートしている。

|No.|コンポーネント|説明|
|:--|:--|:--|
|1|Audio|オーディオを再生|
|2|Mixer|オーディオの同時再生／テキストとオーディオの同時再生|
|3|Selector|設定した配列の中から１つを選択し再生|
|4|Sequencer|テキストまたはオーディオを順次再生|
|5|Silence|音なし（一時停止）|
|6|Speech|テキストまたはSSMLを再生|

### オーディオフィルター機能

オーディオに変化を加えることができる。

|No.|フィルター|説明|
|:--|:--|:--|
|1|Trim filter|指定した位置でオーディオをトリムする|
|2|FadeIn filter|オーディオのフェードイン|
|3|FadeOut filter|オーディオのフェードアウト|
|4|Volume filter|オーディオのボリュームを調整|

# APL for Audio をスキルに実装する
JSONファイルを３つ（ `directive.json` 、`document.json` 、 `datasources.json` ）用意する。ファイル名は任意のファイル名をつけて問題ない。そしてファイルを３つに分けなくても特に問題ない。昔からのクセで必ずわけるようにしている。

`responseBuilder` の `.addDirective` に設定するJSONファイル。 

```directive.json
{
    "type": "Alexa.Presentation.APLA.RenderDocument",
    "token": "token",
    "document": apla_document,         ←　ドキュメント
    "datasources": apla_datasources,   ←　データソース
}
```

`document.json` は、document.jsonディレクティブのドキュメントを担う部分。
以下は、`Mixer` コンポーネントを使用した例。
`mainTemplate` → `item` → `type` に `Mixer` を設定。

```document.json（ドキュメント）
{
    "type": "APLA",
    "version": "0.8",
    "mainTemplate": {
        "parameters": [
            "payload"
        ],
        "item": {
            "type": "Mixer",
            "items": [
                {
                    "type": "Speech",
                    "contentType": "SSML",
                    "content": "<speak>${payload.myData.ssml}</speak>"
                },
                {
                    "type": "Audio",
                    "when": "${payload.myData.audio != ''}",
                    "source":"${payload.myData.audio}",
                    "filters": [
                        {
                            "type": "Volume",
                            "amount": "40%"
                        },
                        {
                            "type": "FadeIn",
                            "duration": 300
                        },
                        {
                            "type": "FadeOut",
                            "duration": 300
                        }
                    ]
                }
            ]
        }
    }
}
```
`datasources.json` は、ディレクティブのデータソースを担う部分。ドキュメント側でこの値が拾える。
データソースは、`Mixer` 用に、テキスト文字列と、オーディオのURLが設定できるようにしたもの。

```JOSN:datasources.json（データソース）
"myData": {
    "ssml": "",
    "audio": ""
}
```


### speakの代わりにAPLAのdirective(addDirective)を追加する

```javascript:sample
const apla_document = require('document.json');
const apla_datasources = require('datasources.json');
const apla_directive = require('directive.json');

const LaunchRequestHandler = {
    canHandle(handlerInput) {
        return Alexa.getRequestType(handlerInput.requestEnvelope) === 'LaunchRequest';
    },
    handle(handlerInput) {
        const ssml  = 'しゃべらせる文字列';
        const audio = 'https://..../..../audio.mp3';

        apla_datasources.myData.ssml = ssml;
        apla_datasources.myData.audio = audio;

        apla_directive.document = apla_document;
        apla_directive.datasources = apla_datasources;

        return handlerInput.responseBuilder
            .addDirective(apla_directive)
            .getResponse();
    }
}
```

### repromptの代わりにAPLAのdirective(addDirectiveToReprompt)を追加する

2021年7月21日 Alexa Live にて、APL for Audioがリプロンプトにも対応したことが発表された。
リプロンプトにディレクティブを追加する時は、`addDirectiveToReprompt` を使用する。

```javascript:reprompt
        return handlerInput.responseBuilder
            .addDirective(apla_directive)
            .addDirectiveToReprompt(apla_directive)
            .getResponse();
    }
}
```

### 実行順序

ディレクティブが上から順番に実行される。
APLよりAPL for Audioを先に実行したければ、APL for Audioを最初に記述する。
APLの `AnimateItem` を使ってる場合は、これを変更するだけでスキルの雰囲気が変わることがある。

```javascript:sample
        return handlerInput.responseBuilder
            .addDirective( APLのdirective )            ← 最初に事項される
            .addDirective( APL for Audioのdirective )  ← 次に実行される
            .getResponse();
    }
}
```

# ※Alexa Developer Console でJSONを作成する

Alexa Developer ConsoleでもAPLAのJSONが作成できる。
左側のナビゲーションから`マルチモーダル` をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426739/04f1f5ae-9305-08d6-4ed8-9f2f22820e61.png)


`Create Audio Response` をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426739/d69d7542-3bca-bba4-da46-34329245dd75.png)

そうするとJSONが表示されるので、これをコピーしてベースにするのも良い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426739/98e9da1f-bc6a-93d2-91fa-19a6115f6534.png)



# 参考
- [APL for Audio Reference](https://developer.amazon.com/en-US/docs/alexa/alexa-presentation-language/apl-for-audio-reference.html)
- [apl-for-audio-no-look-weather (GitHub)](https://github.com/alexa-labs/apl-for-audio-no-look-weather)
- [Every New APL Feature Announced at Alexa Live](https://developer.amazon.com/en-US/blogs/alexa/alexa-skills-kit/2021/07/every-new-apl-feature-announced-at-alexa-live)