Contenu connexe Similaire à iOSにおけるWakeword検知機能の実装 (10) iOSにおけるWakeword検知機能の実装2. | 2
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
自己紹介
Name:
伊賀 裕展 / @iganin_dev
Company:
株式会社エクサウィザーズ
Product:
CareWiz ハナスト
3. | 3
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
Wakeword検知とは
• Wakeword
• 音声認識などの処理のトリガーとなる単語
• Wakeword検知
• Wakewordを検知する仕組み
• 例
• iPhone - 「Hey Siri」でSiriを起動させることができる
4. | 4
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
iOSアプリでのWakeword検知の活用
手での操作が必要なく「音声のみ」でアプリを起動できる
介護の現場での記録に活用
5. | 5
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
「CareWiz ハナスト」のデモ
6. | 6
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
記録の全体像
Wakeword検知
「Hey Wiz」
Command
Word検知
「記録」
自由発話認識
「連絡」
自由発話認識
自由文を構造化
データに変換
Backend
Mobile
7. | 7
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
導入
記録の全体像
Wakeword検知
「Hey Wiz」
Command
Word検知
「記録」
自由発話認識
「連絡」
自由発話認識
自由文を構造化
データに変換
Backend
Mobile
10. | 10
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
ハナストでのWakeword検知
Edge AI で「Hey Wiz」というWakewordを検知
• パフォーマンス
• 通信環境に関わらず、発話から検知、反応を可能な限り高速に
• セキュリティ
• 音声データをサーバーに送りたくない
11. | 11
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
Wakeword検知モデルの2つのアプローチ
分類モデル
N秒ごとにM秒の音声にWakewordがある
か判定
Hey Wiz
その他
ラベリングモデル
時系列(0.N秒単位)の各音に対して、
ウェイクワードか否かをラベリング
0 0 1 1 1 1 1 0 0 0 0 0 0 00 1 1 1 1 1 0 0 0 0 0
12. | 12
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
Wakeword検知モデルの2つのアプローチ
分類モデル
○ 検知したかどうかの判別を行いやすい
× 秒数の値の決め方で性能が変化
Hey Wiz
その他
ラベリングモデル
○ 恣意的なパラメータが少なく安定
× 検知したかどうかの判別が難しい
0 0 1 1 1 1 1 0 0 0 0 0 0 00 1 1 1 1 1 0 0 0 0 0
13. | 13
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
Wakeword検知モデルの2つのアプローチ
分類モデル
○ 検知したかどうかの判別を行いやすい
× 秒数の値の決め方で性能が変化
Hey Wiz
その他
ラベリングモデル
○ 恣意的なパラメータが少なく安定
× 検知したかどうかの判別が難しい
0 0 1 1 1 1 1 0 0 0 0 0 0 00 1 1 1 1 1 0 0 0 0 0
14. | 14
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
学習ロジック
音声の認識
• LSTM(Long Short Term Memory)
• RNN(Recurrent Neural Network)
前(後)のコンテキストを考慮した学習
X0 X1 X2
Xt
-2
Xt
-1
Xt
h0 h1 h2
ht
-2
ht
-1 ht
A A A A A A
15. | 15
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
Wakeword検知機能をアプリに組み込むまでの流れ
ベースデータ収集
モデル作成・学習
モデル変換
アプリ組み込み
データ作成
ベースデータ収集
モデルを作成するためのベースとなるデータの収集
データ作成
ベースデータから学習用の実データ作成
モデル作成・学習
モデルの作成、学習
モデル変換
アプリに組み込める形にモデルを変換する
アプリ組み込み、ビルド・リリース
実際にアプリに組み込みリリースをする
ビルド・リリース
16. | 16
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
ベースデータ収集
Hey Wiz というWakewordモデルのためのデータ収集
正例: さまざまなバリエーション(年齢、性別、etc)
負例: 関係のない発話内容
ノイズ: 環境音(介護事業所、etc)
17. | 17
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
データ作成
正例・負例・ノイズからデータを作成
• 環境音ノイズを様々な混合比で追加
• フーリエ変換で周波数に変換し、特定の周波数帯・時間を除去
18. | 18
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
データ作成
環境音ノイズの追加 データの編集
正例 環境音ノイズ
混合
19. | 19
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
モデル作成・学習
モデルをLSTMやRNNで作成
環境音ノイズを加えて編集したデータで学習を実施
20. | 20
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
モデル作成・学習 求められる精度
Wakeword検知モデルは誤検知に強くなければいけない
例:
誤検知回避率 99%の場合
2分に1回くらい誤検知する
=> 現場で使うのはかなり厳しい
21. | 21
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
モデル変換
作成したモデルをアプリに組み込める形に変換する
• Core ML Tools
• TensorFlow Lite
• etc
22. | 22
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
モデル変換 – Core ML Tools
• Apple提供のツール
• 様々なライブラリのモデルを Core ML モデルに変換可能
• Core ML
Neural Engineが使用できパフォーマンスが一般的に高い
23. | 23
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
モデル変換 – TensorFlow Lite
• Google提供
• 様々なライブラリのモデルをTensorFlow Lite モデルに変換可能
• TensorFlow LiteモデルはAndroidでも使用可能
• Core ML DelegateによってNeural Engineを使用可能
• iOS 12以上、A12 SoCチップ以上搭載端末
24. | 24
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
アプリ組み込み - Core ML モデル
• CoreMLモデルの初期化
• CoreMLで追加した場合は関連Classが自動生成される
25. | 25
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
アプリ組み込み
• CoreMLモデルの初期化
• CoreMLで追加した場合は関連Classが自動生成される
• AVAudioEngineのStreamをモデルに流す
• StreamをモデルのInput形式にAVAudioConverter等で変更
• 解析に必要な分の音声をインスタンスで保持
26. | 26
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
アプリ組み込み
• CoreMLモデルの初期化
• CoreMLで追加した場合は関連Classが自動生成される
• AVAudioEngineのStreamをモデルに流す
• StreamをモデルのInput形式にAVAudioConverterで変更
• 解析に必要な分の音声をインスタンスで保持
• モデルで推論実行
• 返却値のConfidenceの値に従って処理実施
• 高 -> 後続処理実行 / 低 -> 何も行わない
27. | 27
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知
まとめ
• Wakeword検知とは
• Wakeword検知モデルをアプリに組み込むまでの流れ
29. | 29
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
さまざまな音があり、人の声以外の音を誤検知しうる
Wakeword
検知モデル
人の音声以外を
Wakewordとして検知
30. | 30
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
前段階でフィルターを使用することにより改善できるのでは?
Wakeword
検知モデル
人の音声のみ
通すフィルター
人の音声のみモデルに流す
31. | 31
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
Sound Analysis
32. | 32
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SoundAnalysisとは
• iOS13から導入されたフレームワーク
• 音の分類が可能
33. | 33
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SoundAnalysis Custom ML Modelが使用可能
Source: Training Sound Classification Models in Create ML (WWDC 2019)
https://developer.apple.com/videos/play/wwdc2019/425/
34. | 34
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SoundAnalysis iOS15からBuilt Inのモデルが使用可能に
• iOS15以降からBuilt-Inの分類モデルが使用可能に
• WWDC 2021 Discover built-in sound classification in SoundAnalysis
• iOS15では 約300種類 の音を分類可能
35. | 35
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
Built-Inモデルで判別できる音
let request = try SNClassifySoundRequest(classifierIdentifier: .version1)
print(request.knownClassifications)
["speech", "shout", "yell", "battle_cry", "children_shouting", "screaming", "whispering",
"laughter", "baby_laughter", "giggling", "snicker", "belly_laugh", "chuckle_chortle",
"crying_sobbing", "baby_crying", "sigh", "singing", "choir_singing", "yodeling", "rapping",
"humming", "whistling", "breathing", "snoring", "gasp", "cough", "sneeze", "nose_blowing",
"person_running", "person_shuffling", "person_walking", "chewing", "biting", "gargling", "burp",
"hiccup", "slurp", "finger_snapping “, … ]
36. | 36
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
Built-Inモデルで判別できる音
let request = try SNClassifySoundRequest(classifierIdentifier: .version1)
print(request.knownClassifications)
["speech", "shout", "yell", "battle_cry", "children_shouting", "screaming", "whispering",
"laughter", "baby_laughter", "giggling", "snicker", "belly_laugh", "chuckle_chortle",
"crying_sobbing", "baby_crying", "sigh", "singing", "choir_singing", "yodeling", "rapping",
"humming", "whistling", "breathing", "snoring", "gasp", "cough", "sneeze", "nose_blowing",
"person_running", "person_shuffling", "person_walking", "chewing", "biting", "gargling", "burp",
"hiccup", "slurp", "finger_snapping “, … ]
Speech
37. | 37
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SoundAnalysisを使用して人の声のみを検知モデルに流す
Wakeword
検知モデル
SoundAnalysis
SoundAnalysisで
人の音声のみモデルに流す
38. | 38
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNAudioStreamAnalyzerの使用
// Streamでの処理の場合はSNAudioStreamAnalyzerを使用
let analyzer = SNAudioStreamAnalyzer(format: format)
39. | 39
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNAudioStreamAnalyzerの使用
let analyzer = SNAudioStreamAnalyzer(format: format)
// SNClassifySoundRequestを使うことでBuilt-Inのモデルを使用
let request = try SNClassifySoundRequest(classifierIdentifier: .version1)
40. | 40
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNAudioStreamAnalyzerの使用
let analyzer = SNAudioStreamAnalyzer(format: format)
let request = try SNClassifySoundRequest(classifierIdentifier: .version1)
// Observerを設定してRequestをAnalyzerに追加
try analyzer.add(request, withObserver: self)
41. | 41
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNAudioStreamAnalyzerの使用
try analyzer.add(request, withObserver: self)
// AudioEngineから取得した音をAnalyzerに流す
audioEngine.inputNode.installTap(
onBus: 0, bufferSize: bufferSize, format: format
) { [weak self] buffer, when in
analyzer.analyze(buffer, atAudioFramePosition: when.sampleTime)
}
42. | 42
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNResultsObservingへの準拠
// 解析結果はSNResultObservingのrequest(request:,didProduce:)で受け取る
extension SoundAnalyzer: SNResultsObserving {
public func request(_: SNRequest, didProduce result: SNResult) { … }
}
43. | 43
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNResultsObservingへの準拠
public func request(_: SNRequest, didProduce result: SNResult) {
// 検知結果をSNClassificationResultにキャスト
guard let result = result as? SNClassificationResult else { return }
}
44. | 44
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNResultsObservingへの準拠
public func request(_: SNRequest, didProduce result: SNResult) {
guard let result = result as? SNClassificationResult else { return }
// 検知結果から “speech”のみを取得
guard let speechConfidence = result.classifications
.first(where: {
$0.identifier == "speech"
})?.confidence else { return }
}
45. | 45
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
SNResultsObservingへの準拠
public func request(_: SNRequest, didProduce result: SNResult) {
guard let result = result as? SNClassificationResult else { return }
guard let speechConfidence = result.classifications
// confidenceが一定値を超えた段階で検知をカウント
if speechConfidence > confidenceThreshold {
// 検知時の処理
}
}
46. | 46
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
処理の流れ
Wakeword
検知モデル
SoundAnalysis
SoundAnalysisで
人の音声のみモデルに流す
47. | 47
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
SoundAnalysisによる機能改良
まとめ
• SoundAnalysisのBuilt-Inモデルを使用して人の会話を判別可能
• Wakeword Modelの前にフィルターとして配置し、誤検知を低減
49. | 49
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
Wakewordを検知した後
• Wakewordを検知したことをユーザーにフィードバックする
• Wakeword検知後の機能につなげる
50. | 50
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
画面上のUIでのフィードバック
ユーザーへの伝わりやすさ
• PrimaryColorの画面を全面に
51. | 51
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
ユーザーフィードバック UI実装
// 状態を定義
// Wakeword検知時に trueに変更
@Published private(set) var isSTTRecognizing: Bool = false
52. | 52
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
ユーザーフィードバック UI実装
@Published private(set) var isSTTRecognizing: Bool = false
// isSTTRecognizing = true でWakeword検知後のViewを表示する
struct ContentScreen: View {
var body: some View {
ZStack {
…
if deviceAudioStore.isSTTRecognizing {
ReactionScreen()
}
}
}
}
53. | 53
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
ユーザーフィードバック
音声によるフィードバック
• 必ずしも画面を見ていない
• 手が使えない状態でもわかるようにしたい
54. | 54
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
ユーザーフィードバック
音声によるフィードバック
• 必ずしも画面を見ていない
• 手が使えない状態でもわかるようにしたい
Wakeword検知時に「はい?」と
AVSpeechSynthesizerで発話させる
はい?
55. | 55
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
ユーザーフィードバック 音声実装
// Wakeword検知時に下記を実行
private let talker = AVSpeechSynthesizer()
let utterance = AVSpeechUtterance(string: ”はい?")
utterance.voice = AVSpeechSynthesisVoice(language: "ja-JP")
talker.speak(utterance)
56. | 56
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
他の機能との連携
Wakewordによる機能起動
• 音声によって動作させる機能につなげることが多い
• AudioEngine側の処理も必要
• UI側の操作も受け付けるようにしたい
57. | 57
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
「CareWiz ハナスト」での連携例
Wakeword検知 コマンドワード検知 記録音声認識 連絡音声認識
記録
連絡
Hey Wiz
58. | 58
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
「CareWiz ハナスト」での連携例
Wakeword検知 コマンドワード検知 記録音声認識 連絡音声認識
記録
連絡
Hey Wiz
音声
Stream
振り分け
音声
Stream
振り分け
59. | 59
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
「CareWiz ハナスト」での連携例
Wakeword検知 コマンドワード検知 記録音声認識 連絡音声認識
記録
連絡
Hey Wiz
音声
Stream
振り分け
音声
Stream
振り分け
User
操作を
サポート
v v v
60. | 60
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
音声Stream振り分け 実装
// Wakeword検知時にisSTTRecognizing = trueに変更
audioState.$isSTTRecognizing
.sink(receiveValue: { [weak self] isSTTRecognizing in
guard let self = self else { return }
if isSTTRecognizing {
// コマンドワードの検知開始
self.startSTTCommandWord()
}
})
.store(in: &cancellables)
61. | 61
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
音声Stream振り分け 実装
private func startSTTCommandWord() {
// コマンドワードの音声認識開始
commandWordSpeechRecognizer.startSTTRecognition { [weak self] result in
// 音声認識に対する処理
}
}
62. | 62
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
音声Stream振り分け 実装
private func startSTTKeyWord() {
commandWordSpeechRecognizer.startSTTRecognition { [weak self] result in }
// Wakeword検知に流していたtapを除去
audioEngine.inputNode.removeTap(onBus: 0)
}
63. | 63
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
音声Stream振り分け 実装
private func startSTTKeyWord() {
commandWordSpeechRecognizer.startSTTRecognition { [weak self] result in }
audioEngine.inputNode.removeTap(onBus: 0)
// AudioEngineのTapの振り分け先をコマンドワードのRecognizerに変更
audioEngine.inputNode.installTap(
onBus: 0, bufferSize: bufferSize, format: format
) { [weak self] buffer, _ in
guard let self = self else { return }
// 音のStreamをRecognizerに流す
self.commandWordsSpeechRecognizer.write(
buffer: buffer, inputFormat: recordingFormat
)
}
}
64. | 64
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知の後
まとめ
• Wakewordの検知
• UIの変化によるフィードバック
• 音によるフィードバック
• 検知後のアプリ操作
• 音声による操作
• Streamの振り分け先変更処理
• UI上での操作も可能に
66. | 66
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
まとめ
• Wakeword検知モデルの作成方法
• SoundAnalysisをもちいた機能強化
• 音声で操作するアプリのUI/UXとその実装
70. | 70
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
Wakeword検知に伴う問題と対応
Wakewordの検知のためには音声を取得し続ける必要あり
• 音声の入力デバイスが変化する
• Build In マイク <-> ヘッドホン
• 電話などによる介入がある
• 介護施設の場合はナースコールなど
71. | 71
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
音声の入力デバイスの変化
音声StreamのInputFormatが変化
適切に対応しないとApp Crashの可能性あり
72. | 72
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
音声の入力デバイスの変化
• NotificationCenterで検知可能
• AVAudioSession.routeChangeNotification
• NotificationのuserInfoから詳細がとれる
• 新しいDeviceを検知
• 以前のDeviceが使用できなくなった
• etc
73. | 73
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
音声の入力デバイスの変化
異なるInputFormatへの対応
• 音声入力が必要な箇所で対応も可能
• ConverterのInputFormatの変更
• InputFormatを使用しているインスタンスの再生成
74. | 74
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
電話などによる介入
• 電話などによる介入でAVAudioSessionがアクティブでなくなる
• NotificationCenterで検知可能
• AVAudioSession.interruptionNotification
• .beganと.endedが取得できる
75. | 75
©︎ Copyright ExaWizards Inc. All Rights Reserved.
Public
Wakeword検知に伴う問題と対応
AVAudioSession.interruptionNotification
• AVAudioSessionInterruptionTypeKeyでuserInfoから詳細がとれる
• .began
• 中断開始のため、音声取得を中断する
• .ended
• 中断が終わったため音声取得を再開する
• NotificationはMain ThreadでPostされる
• 重めの処理やMainThread以外で処理を行いたい場合は注意
Notes de l'éditeur iOSにおけるWakeword検知機能の実装というタイトルで発表します。よろしくお願いいたします。 簡単な自己紹介をさせてください。伊賀裕展ともうします。
株式会社エクサウィザーズのソフトウェアエンジニアとして現在は主にCareWiz ハナストというプロダクトのiOSアプリ開発を行なっています。 本日はWakeword検知のiOSアプリでの実装に関してお話いたします。さて、まずそもそもWakeword検知とはどのような機能でしょうか。
Wakeword検知とは音声認識などの処理を起動させるためのキーワードを検知する機能を意味します。
例えばiPhoneでのHey Siriの活用などが馴染み深いのではないでしょうか。 本日お話しするCareWizハナストでは音声のみでアプリを操作するためにウェイクワード検知を活用しています。 音声でのアプリ操作といっても今ひとつイメージがつきずらいかもしれません。
簡単な数十秒程度の動画を用意いたしましたので、まずはご覧いただければと思います。
動画 0:27から
先ほどは記録する場合のフローの動画でした。
もう一つ連絡機能を使用する場合の動画もご参考までに共有いたします。
動画 1:47から
先ほどご覧いただきましたデモの操作をシーケンスで図解してみると図のようになります。
ウェイクワードを検知し、記録、連絡といったコマンドワードを検知、自由発話を文字起こしし、バックエンドに送信しています。 本日はウェイクワード検知の部分に焦点をあて解説し、その後音声でアプリを操作する際のUI・UXに関してもお話しします。 さて、本日のアジェンダです。
まずDemoでもご覧いただいたWakeword検知に関して、モデルの作成からアプリへの組み込みまでをご説明します。
次にSoundAnalysisと組み合わせて誤検知を減らす取り組みに関してご説明します。
その後、音声によるアプリ操作に関して、UI・UX観点で気をつけていること、どのように実装しているかをお伝えします。 まずはウェイクワード検知からご説明します。 多くの場合にそうであると思いますが、ハナストでもウェイクワードの検知をEdge AIで行っています。
主な理由は2点で、パフォーマンスとセキュリティです。
ウェイクワードは通信環境にかかわらず、発話から検知・反応まで可能な限り高速にしたいです。
また、ウェイクワード検知のために全ての音声をバックエンドに流すのはセキュリティ上好ましくありません。
これらの理由より、Edgeでの処理が適していると考えています。 ウェイクワードの検知にあたり2つのアプローチを考えました。
1つは分類モデルです。
一定の秒数ごとに一定の秒数の発話がウェイクワードであるかどうかを判定します。
もう一つはラベリングモデルです。
こちらは時系列の各音に対して、その音がウェイクワードに関連する音なのかどうかをラベリングします。 分類モデルでは検知したかどうかの判別が行いやすいですが、発話とみなす音の秒数によって性能が変わってきます。
ラベリングモデルはその点安定しますが、検知したかどうかの判別が難しくなります。 今回はアプリでの検知結果の判定のしやすさを優先し、分類モデルを採用しました。 学習ロジックとしては、Long Short Term MemoryやRecurrent Neural Networkが使用されることが多いようです。
音声の認識のためには前後の文脈が重要になりますが、これらのモデルは学習に前後のデータを使用し反映させるためコンテキストも考慮した推論ができるようになります。 ウェイクワード検知機能をアプリに組み込むまでの流れをご説明します。
モデルを学習するためのベースデータを収集し、そのデータをもとに学習用のデータを作成します。
作成したデータをモデルに学習させ、アプリに組み込める形に変換します。
その後、アプリに組み込みリリースを行います。
それぞれにフォーカスを当てて内容を確認していきましょう。 ベースデータの収集においては正例と負例とノイズを収集します。
正例では年齢、性別などデータにバリエーションを持たせることが重要になります。
環境音ノイズは様々な種類を取得するべきですが、使用が想定される場所のノイズ音を取得できるとより効果的です。 取得したベースデータから学習用データを作成します。
具体的には正例、負例のデータと環境音ノイズを混合したり、データの一部を除去したりします。 それぞれの作業イメージは図のようになります。
このようにすることでベースデータからバリエーション豊かな学習用データを作成することができます。 先ほどご説明したLSTMやRNNを用いてモデルを作成し、環境音ノイズを加えて編集したデータで学習を実施します。 学習の際に1点留意すべきことがありますので、ご紹介します。
ウェイクワード検知のモデルにおいては誤検知率が低くなることが大変重要になります。
例えば、誤検知しない確率が99%だとしても2分程度の時間の間に1度誤検知してしまい、ユーザーの体験が大きく損なわれます。
そのため、誤検知率をいかに抑えられるように学習させるかに注意する必要があります。 作成したモデルをアプリに組み込むことを考えます。
代表的な方法としてはCoreML Tools、 TensorFlow Liteなどがあるかと思います。 CoreML ToolsはApple によって提供されているツールです。
PytorchやTensorFlowなど様々なライブラリによって作られたモデルをCore ML モデルに変換することができます。
Core ML モデルはNeural Engineが使用できることにより、パフォーマンスが高くなる可能性が高いため、まず検討したい方法です。 TensorFlow LiteはGoogleによって提供されています。
こちらも様々なライブラリで作成されたモデルをモバイル端末で実行可能なモデルに変換できます。
TensorFlow LiteのモデルはAndroidでも使用可能なため、両OSをサポートしている場合とくに候補に上がるかと思います。
最近では種々の制約はありますが、Core ML Delegateを使うことでCore ML モデル同様にNeural Engineを使用することができるようです。 アプリに組み込む際の流れを確認します。CoreMLモデルに変換した場合を例に取ります。
CoreMLモデルはプロジェクトに含めると自動的に対応したクラスが生成されるためそちらを初期化します。
AVAudioEngineを使用し、音のStreamを取得しモデルに流します。
この際にモデルの推論実行に必要なデータ形式に変換することが重要になります。
取得した音を用いてモデルで推論を実施し、実施結果のConfidenceをもとに処理を決定します。
この際に必要なConfidenceの値はユーザー側で調整できるようにすると、感度調整といった形でユーザービリティを高められるかもしれません。 まとめます。
ウェイクワード検知とは何かをお伝えしました。
ウェイクワード検知によって、音声によってアプリの機能を起動させることができます。
また、ウェイクワード検知モデルを作成し、アプリに組み込むまでの流れの概要をお伝えしました。 次にSoundAnalysisによる機能改良についてご説明します。 Wakewordを検知するために音声を流し続けていますが、必ずしも人の音声が含まれているデータだけが流れてくるわけではありません。
大部分の区間はそれ以外の環境音や人の声以外の音が流れてきます。
そのため、環境音をWakewordとして誤検知するということもありえます。 そこで、Wakeword検知モデルに流れる前に人の音声を含む音のみを通すフィルターを置くことで機能改良が図れるのではないかと考えました。
Appleが提供するFrameworkにそのようなものはあるのでしょうか。 調べたところSoundAnalysisが使用できそうだということがわかりました。 Sound AnalysisはiOS13から導入されたフレームワークで、音の分類を行うことが可能です。 導入された当初は分類のためのモデルを自作する必要がありました。
https://developer.apple.com/videos/play/wwdc2019/425/ iOS15でビルトインのモデルが使用できるようになりました。
WWDCでの説明によると約300種類の音を分類することができるようです。 ビルトインモデルで判別できる音を出力してみました。 目を凝らしてみますと分類可能な音の中にspeechがあることがわかります。
人の発話を分類できるようです。 以上からSoundAnalysisを使用して人の音声データを含む音のみを通すフィルターを作成することができそうです。 具体的な実装を概観してみましょう。
まずストリームの音の処理を行うためSNAudioStreamAnalyzerを使用します。 SNClassifySoundRequestを使用することでビルトインのモデルを使用することができます。 Observerを設定してrequestをanalyzerに追加します。 AudioEngineで取得した音声をanalyzerに流します。 解析結果は先ほどanalyzerにセットしたSNResultObservingを継承したクラス経由で行います。 検知結果をSNClassficationResultにキャストし。 検知結果のidentifierを使用し、検知結果からspeechのもののみを取得、confidenceを取得します。 confidenceが一定の値を超えていた場合に検知したと判断し、検知時の処理を実行します。 先ほどまでの実装によって、SoundAnalysisを使用した人の音声が含まれる音のストリームのみを通すフィルターを追加することができました。 まとめます。
SoundAnalysisのビルトインモデルを使用することで人の会話を判別することができます。
ウェイクワード検知モデルの前段階に配置することで誤検知が低減できるように活用した事例をご紹介しました。 さて、ウェイクワードの検知はそれを行なって終わりではありません。
検知後に繋げる必要があります。その辺りをお話しします。 ウェイクワードを検知した際にはまず、ユーザーにそのことをフィードバックする必要があります。
また、ウェイクワード検知後の機能につなげるひつようもあります。 まずユーザーへのフィードバックについてみていきます。
画面のUIでのフィードバックではユーザーへの伝わりやすさを重視し、PrimaryColorの画面を全面に出すことで検知を伝えています。 実装についてもご紹介します。
非常にシンプルになっていて、ウェイクワード検知時にtrueに変更されるプロパティを用意し、 アプリのベースとなるViewでプロパティの変更を検知し画面を表示するようになっています。 次に音声でのフィードバックについてもご紹介します。
ウェイクワードを検知する際に必ずしもユーザーは画面を見ているわけではありません。
そのため、手が使えず画面を確認できない場合でもウェイクワードを検知したことがわかるように音でのフィードバックも重要になります。 ハナストではウェイクワード検知時にAVSpeechSynthesizerで「はい?」という発話をさせることで音声でのフィードバックを実現しています。 実装に関しても簡単にご紹介します。
AVSpeechSynthesizerを初期化し、utteranceで発話させたい内容を定義します。
AVSpeechSynthesisVoiceで言語を設定し、speakメソッドを呼び出すと発話させることができます。
これをウェイクワード検知のタイミングで行うという実装になります。 さて、ウェイクワードの検知はそれ単体で完結する訳ではなく、次の機能につなげる必要があります。
この際にウェイクワードに続く処理を音声で行いたいことも多く、音のStreamの操作が必要になります。
また、音声のみの操作だけではなく、素早く確実なインタラクションのためにUI側の操作を受け付けるようにすることも重要です。 セッション冒頭でご紹介しましたように、ハナストではウェイクワードを検知した後に記録、連絡という機能に繋げています。
記録というコマンドを検知すると記録機能に連絡という発話コマンドを検知すると連絡機能へと遷移します。 この流れの中で、HeyWizというウェイクワードを検知したあとはコマンドワードを検知する機能に音声のStreamを振り分け直す必要があります。
また、記録、連絡という発話をコマンドワードとして検知したあとはそれぞれの機能を実行するために音声Streamの振り分けを再度行います。 先ほどのご説明の通り、音声での操作だけではなく、ユーザーによるUI操作もサポートしています。
例えば、コマンドワードの検知の際には記録、連絡機能にそれぞれのボタンを押下することでも遷移できます。
また、記録、連絡それぞれの機能においてバツボタンを押すことで機能をキャンセルすることが可能です。 音声Streamの振り分けの実装に関してご紹介します。
例としてウェイクワード検知後にコマンドワード検知機能に音声を振り分け直す場合をみてみます。
ウェイクワードを検知した場合に変更されるisSttRecognizingの変更を検知し、startSttCommandWordメソッドを実行します。
startSttCommandWordメソッド内でコマンドワード検知用のRecognizerを実行します。 音声ストリームの振り分けのためにaudioEngineに対してremoveTapを実行し、 installTapによって、audioEngineからの音声ストリームが流れる先を再設定します。
今回はコマンドワード検知用のrecognizerに音声を流し込むようになっています。
removeTapとinstallTapによって音声の振り分け先を変更する方法をご紹介しました。 まとめます。
ウェイクワード検知はUIと音の双方のフィードバックが重要であることをお伝えしました。
また、ウェイクワードは検知して終わりではなく、その後の機能につなげる必要があり、音声ストリームの振り分けなどが必要なことをお伝えしました。
それだけではなく、確実性の高いUIへの操作を並行して提供していることもお伝えいたしました。 最後に全体のまとめに入ります。 本日はまずウェイクワード検知モデルを作成し、アプリに組み込むまでの流れをお話ししました。
データ収集から実際にアプリに組み込むまでの流れを一通りみていきました。
次にSoundAnalysisフレームワークを用いて人の音声のみを通すフィルターを作り誤検知率を低下させる試みに関してお話ししました。
最後に音声で操作するアプリのUIやUXに関してお話ししました。画面でのフィードバックだけではなく音によるフィードバックも重要であること、
音声による操作とUIによる操作を両立していることなどをお伝えしました。
以上で発表を終わります。ご清聴いただきありがとうございました。