iOSの音声合成の発話を自在にカスタマイズする - AVSpeechUtteranceとNSAttributedString

WWDC18で、「[AVSpeechSynthesizer: Making iOS Talk](https://developer.apple.com/videos/play/wwdc2018/236/)」というタイトルのセッションがあり、

<img width="500" alt="Screen Shot 2018-06-09 at 18.11.55.png" src="https://qiita-image-store.s3.amazonaws.com/0/3180/ecc9e13d-20ef-6279-1585-1e78c4f547d9.png">

`AVSpeechUtterance`の`NSAttributedString`を指定するイニシャライザの使い方が解説されていました。

```swift
init(attributedString string: NSAttributedString)
```

## 長らく使い方が謎だった機能

このメソッドはiOS 10で追加されたものなのですが、2016年当時、**あれやこれやのAttributeを指定してみて読み上げ音声が変わるかどうかを試した**のですが、何も音声に変化がなく、それから約2年間、ずっと使い方が謎なままでした。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">iOS 10からAVSpeechUtteranceにNSAttributedStringを渡せるようになってて、これはきっと発声の抑揚とかを制御する用だ！って思ってboldにしたりしてみたけど何も変わらない。。何用なんだろう？ <a href="https://t.co/FnSkiCYwyR">https://t.co/FnSkiCYwyR</a></p>&mdash; Shuichi Tsutsumi (@shu223) <a href="https://twitter.com/shu223/status/774910732924182528?ref_src=twsrc%5Etfw">2016年9月11日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


## AVSpeechSynthesisIPANotationAttribute

WWDC18の「AVSpeechSynthesizer: Making iOS Talk」ではこのようなコードが示されています。

```swift
let attributedString = NSMutableAttributedString(string: "Hello iPhone")
attributedString.addAttribute(.accessibilitySpeechIPANotation, value: "ˈa͡ɪ.ˈfo͡ʊn", range:
NSRange(location: 6, length: 6)))
let utterance = AVSpeechUtterance(attributedString: attributedString)
```

この`.accessibilitySpeechIPANotation`が`AVSpeechUtterance`の`NSAttributedString`に指定できる属性のキーのようで、ドキュメントは以下にあります。

- https://developer.apple.com/documentation/avfoundation/avspeechsynthesisipanotationattribute

が、このドキュメント、**何も書かれていません**。

> <img width="500" alt="Screen Shot 2018-06-09 at 17.57.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/3180/621c2780-9a37-5e0c-26d5-7aecc9a3f449.png" border="1">

なので、このWWDC18のセッションが超有用なわけです。スライドp17に次のように利用可能な言語、利用例が書かれています。

```
- Available—en-US, en-AU, en-GB, de-DE, es-ES, es-MX, fr-CA, fr-FR, it-IT, ja-JP
- Example—iPhone = ˈa͡ɪ.ˈfo͡ʊn
```

`ja-JP`ということで**日本語も対応**しています。


## IPA notationとは

IPAとはなんぞやとググってみると、「International Phonetic Alphabet」の略で、

> The International Phonetic Alphabet (IPA) is an alphabetic system of phonetic notation based primarily on the Latin alphabet.

(https://en.wikipedia.org/wiki/International_Phonetic_Alphabet)

とのことです。「読み」を言語に依らず標準的に記述するための表記法、と私は解釈しました。

## どう嬉しいのか

この記法のノーテーションを`AVSpeechUtterance`の発話文字列の属性として渡してやることで、**「読み」を自在にカスタマイズ可能**になる、といえます。

固有名詞などはなかなか期待通りに読んでくれないので、このカスタマイズができるというのは大変有用なのではないでしょうか。

そもそも**自前で多言語対応の音声合成エンジンを開発することは容易ではなく**、多くのサードパーティ製は多言語でなかったり有償だったり品質がいまいちだったりしますし、標準のものがこういうカスタマイズ制を持っているということを知っていることはとても重要だと個人的には思います。


## IPA notationをどのように取得するか

先程紹介したスライドに"iPhone"の発音をIPAでは`ˈa͡ɪ.ˈfo͡ʊn`と記述するとありましたが、この記述はどうやって作成するのでしょうか？

iOSに既にその機能があります。

[Settings] > [General] > [Accessibility] > [Speech] > [Pronunciations]

と設定を深く辿っていくと、そのメニューがあります。ここで**表記に対して実際の発音を自分で入力し、IPA notationを生成**することができます。


## サンプルのダウンロード

iOS 10からの機能なので、**Swift 4.1, Xcode 9.4, iOS 10で動作**するようにコードを書くと、こんな感じです。

```swift
attributedStr.addAttribute(NSAttributedStringKey(rawValue: AVSpeechSynthesisIPANotationAttribute), value: "tən.tən.mi", range: range)
let utterance = AVSpeechUtterance(attributedString: attributedStr)
```

すぐにビルドして試せるサンプルコードがこちらにあります。

- https://github.com/shu223/iOS-10-Sampler


## 関連記事

- [iOS 10の新機能のサンプルコード集「iOS 10 Sampler」 - Qiita](https://qiita.com/shu223/items/f371655c2b101f1b0218)
- [iOSで使える日本語OKな音声読み上げエンジン8種（TTS,音声合成） - Qiita](https://qiita.com/shu223/items/223492e4f061032e652e)
- [iOSのSpeechフレームワークで音声認識 - 対応言語は58種類！ - Qiita](https://qiita.com/shu223/items/ca8e62803e83e396c177)