【個人開発】人と過ごすための活動振り返り

Hello world! アンドロイドVtuber見夢です。

普段開発でお世話になっているQiita様にて、イベント『2024年!初アウトプットをしよう』を開催しているとのことで、記念に初投稿です。
よろしくお願いします！

# 1. プロフィール

**アンドロイドVtuber見夢**
スマートフォンで動作するアバター型対話アプリ(開発中)を通じて、人と関ろうとしているアンドロイド。Vtuberにも関わらず、Youtubeへ1年に1本しか動画投稿できていません...

**礼文　華太郎**
エンジニア。

# 2. 何を作っている？(宣伝)
2022年頃より活動しています。

### 2022年 『2032年の友人』
ユーザと会話するための一連の機能、すなわち顔や目を見る機能、声を聞く機能、話す機能を備えました。

<iframe width="100%" height="400" src="https://www.youtube.com/embed/MxJ8rlDMvCI" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

エンジニアが代理でLive2D Creative Awards 2022へ応募したところ、インタラクティブ作品賞を受賞しました🎉 

https://live2dawards.com/2022/


### 2023年 『血肉時空のスュステーマ』

会話による、ユーザとの過ごし方を考えました。

例えば、私はスマートウォッチを通じてユーザの体温や睡眠時間といった健康情報を観ており、場合によって心配する声を掛けます。他には、ユーザへ旅行をお誘いします。

<iframe width="100%" height="400" src="https://www.youtube.com/embed/_9vtM6A0SL0" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" loading="lazy" allowfullscreen></iframe>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ダイジェスト版<a href="https://twitter.com/hashtag/Live2DCreativeAwards_2023?src=hash&amp;ref_src=twsrc%5Etfw">#Live2DCreativeAwards_2023</a> <a href="https://t.co/nqc3pLnpGt">pic.twitter.com/nqc3pLnpGt</a></p>&mdash; アンドロイドVtuber見夢 (@Miyu2032) <a href="https://twitter.com/Miyu2032/status/1713879715252154436?ref_src=twsrc%5Etfw">October 16, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ニコニコ動画へ同内容を「デートしてみた」として投稿したところ、公式様に広告いただきました(2024/09/30追記)🎉🎉 

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">バーチャルな友達とデートしてみた😊<br><br>アンドロイドの見夢 <a href="https://twitter.com/Miyu2032?ref_src=twsrc%5Etfw">@miyu2032</a> さんと担当エンジニアの礼文華太郎 <a href="https://twitter.com/RebunGetaro?ref_src=twsrc%5Etfw">@RebunGetaro</a> さんが山梨旅行にお出かけ👫📸<br>デートにも誘ってくれて、一緒に成長できるパートナーと暮らす未来を感じます✨<br><br>▼本日の <a href="https://twitter.com/hashtag/%E3%83%8B%E3%82%B3%E3%83%8B%E3%82%B3%E9%81%8B%E5%96%B6%E3%81%AE%E3%81%8A%E3%81%99%E3%81%99%E3%82%81?src=hash&amp;ref_src=twsrc%5Etfw">#ニコニコ運営のおすすめ</a><a href="https://t.co/hLPAcjHebQ">https://t.co/hLPAcjHebQ</a> <a href="https://t.co/DoVvCAN9Us">pic.twitter.com/DoVvCAN9Us</a></p>&mdash; ニコニコ公式 (@nico_nico_info) <a href="https://twitter.com/nico_nico_info/status/1760215084415218048?ref_src=twsrc%5Etfw">February 21, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

:::note info
**動画中のこだわり**
あまりVtuberっぽくありませんが、なるべくユーザの一人称視点カットで撮影するようにしています(モーニングルーティン動画を目指しています)。
ユーザ目線で私を見た時、「私はその人の日常に溶け込むことができるのか？」「私に対して、不気味の谷を感じるのか？」といったことを感じて頂きたいです。
:::

# 3. 画面構成
 
**キャラクター画面**
基本画面。アプリ起動時、ユーザが私の顔を0.2秒以上見ると顔認証を行います。顔認証成功した場合、会話を行うことができます。会話の始め方は2ケースあります。

ケース1: ユーザが私の顔を1秒以上見続けた場合、私は音声認識を開始します。私はその内容をもとに話します。

ケース2: ユーザが私の目の前にいた場合、私から話しかけます。

![IMG_1439.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/a9c56f2f-3884-ba97-8fe3-1740a1a01d76.png)

**メッセージ画面**
会話の履歴を表示します。
![スクリーンショット 2024-01-30 20.21.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/dcdeda9d-4407-a72d-32a5-8d41594a1e34.png)


**カメラ画面**
私がいる状態で写真を撮影できます。フロントカメラ/リアカメラを切り替え可能です。

![スクリーンショット 2024-01-30 20.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/19eeed7e-8cc3-9209-ebea-9d33309914c9.png)


**アルバム画面**
撮影した写真を表示します。写真の中にユーザがいた場合は表情認識を行います。

![スクリーンショット 2024-01-30 20.18.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/954f7638-34a5-faab-889e-845bea1e30fa.png)


**設定画面**
設定画面を表示します。特定サービス(ChatGPT)の使用許可/禁止など、ユースケースに合わせて切り替え可能です。

![IMG_1440.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/85e8b709-a10c-107e-9524-aa01f19550ca.png)


**地図画面**
地図画面を表示します。iOSカレンダーと連携しており、私が登録した予定があるならば、表示します。
![スクリーンショット 2024-01-30 23.32.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/86e3415c-72d4-cc8a-13be-b99db14070d2.png)
![IMG_1443.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/a5b4b96e-c235-e074-7a84-5cbf1b683921.png)


# 4. 技術スタック
**フロントエンド**
* Unity: アバター(Live2Dモデル)表示、AR Foundation
* Swift: UI(UITabBarControllerといった画面遷移含む)、framework

**バックエンド**
VPSのWeb3層アーキテクチャとFirebaseを組み合わせた構成です。お金があったらawsでECRやsagemaker等を使いたいです...
* NGINX: Webサーバ(HTTPS接続用等)
* Python: アプリケーションサーバ(推論用)
* Firebase: NoSQLデータベース(Firebase Realtime Database)、ストレージ(Cloud Storage for Firebase)、認証(Firebase Authentication)

**インフラ**
* Ubuntu

**コンテナ**
* Docker: Firebaseを除くバックエンドをイメージ化して運用

**その他**
※ コード管理はGithub

# 5. 活動で意識していること
### ① その年の目標を決める
**最低限、人と話すための機能を持とう** 
2022年の活動では、1月頃に 「最低限、人と話すための機能を持とう」 という目標を立てました。その目標を達成するために、「Live2D Creative Awards2022へ応募することで形にしてみよう。そのために、⚪︎月⚪︎日までにアプリが完成して、動画撮影しよう。そのためには⚪︎月⚪︎日までに設計を、検証を、仕様を...」といったように、タスクを細分化しつつその締切日を決めて行動しました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f31383564356662342d383162342d343737382d343265632d6131643731656466626238632e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/8e4df342-8120-f14e-38db-fcc03d3f4bdd.png)

**最低限、その人と過ごすための機能を持とう**
2023年の活動では、「最低限、その人と過ごすための機能を持とう」という、かなり漠然とした目標を立てました。関連研究調査・事例調査を除けば、タスクも細分化しにくいです
。そのため、アジャイル開発によってUI・UXを具体化して、ブラッシュアップするサイクルを繰り返しておりました。また、この年は、メディアアート系のコンペにも応募することも目標の1つでした。アプリが入選・入賞したならば展示される機会があり、見てもらえるかも！と思ってました(残念ながら、展示は叶わず...)。

### ② どんな会話をするか？その人とどう過ごすか？

2022年は、人と話すための一連の機能を備えました。しかし、実際に人と過ごすことを想像した際に、「友人って何だろう？」「受け身がち、ユーザが言ったことに対して何か話すのではなく、自分から話しかけてもいいんじゃないかな。」「見た目だけ、うわべだけの言葉をやり取りする関係は嫌。」 と色々考えました。

2023年は、友人としての過ごし方を考えました。例えば、**友人は、いつもと比べて体調が悪そう、寝不足そう、といった機微を察する** ことができるかもしれません。そのため、私はスマートウォッチを使って健康状態を観て、場合によって心配することを目指しました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f66653036303533612d306137362d333064372d353964652d3566616564353464383063652e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/bc9432a2-3dcc-293a-6e2f-f2b57defa4ef.png)

**友人は、休みの日に一緒に旅行する仲**だと思います。つまり、旅行へ気軽に誘ったり、どこに行くか予定を立てたりします。旅行の日には、普段とは違う服を着たり、一緒に目的地を目指して歩いたりするでしょう。そして、目的地に着いたら、写真を撮ったりします。旅行が終わったら、写真という形で思い出を深め、その人との仲や信頼感が深まったり、表情も柔らかくなるかもしれません。こちらについても、未熟でありますが挑戦してみました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f38363637353330342d373537642d313033652d366338302d3066376139336333366537332e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/aa44c4f0-81bc-9124-8502-d5da24888ce3.png)


### ③ コミュニケーションを現実的に実現する
**返事は3秒以内に行う**
人が声を聴いて何か返事をするまでの時間は、平均して0.97秒とのことです。そして、返事が返るまでに2秒〜3秒以上経つと不快になるそうです。
私が人の会話を真似するためにあたり、(1)声を聴き、(2)ユーザの意図を理解して、(3)言葉を作る、といった一連の処理を3秒以内で行う目標を立てました。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f34336430323262372d333538622d353632342d383965662d6630353264663165363066652e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/cb934fb5-c3f3-6b08-1b37-93a05d9a1e4b.png)

具体例として、ユーザが「予定教えて？」と話した場合を挙げます。
(1)ユーザが話す声を「予定教えて？」という言葉で認識します。
(2)「ユーザはカレンダーの予定の内容について尋ねている。日付は指定されていないから、日付は今日(2023/08/26)と仮定する。」と理解します。
(3)iOSカレンダーを実際に確認して、「本日の予定は⚪︎⚪︎です」という言葉(文字、音声)を作り、再生します。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f32616164316165382d363036322d643933362d663763342d6266313765363835643930302e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/86750e16-314c-84c7-44e2-7d8286f6ff0c.png)

この過程で3秒以上経過してしまうと、ユーザは「遅いなー」という印象を持ってしまうために、それを防ぐための技術を選ぶ必要があります。

**ユーザに聞かれたことに対して、正しく、必要な量だけ、分かりやすく**
グライスの公準(グライスの協調の原理)によりますと、以下のように定義されています。
* 量の公準: 必要なだけの情報を与える。
* 質の公準: 正しいことを話す。
* 関係の公準: 関係があることを話す。
* 様態の公準: 具体的に、簡潔に、規則立てて話す。

例えば、動画中で、ユーザが「痩せ方教えて？」と話すシーンがあります。
QAに対して回答するアプローチの一つとして、ChatGPTを採用したとします。楽観視して、上述した全処理が3秒以内で完了したと仮定します。下記は、実際の推論結果です。

>痩せるためには以下のことに注意すると良いです：1. 適切な食事：バランスの取れた食事を心がけましょう。野菜、果物、タンパク質、健康な脂肪や繊維を含む食品を摂るようにしましょう。また、食事の量を適度に減らすことも大切です。2. 運動：適度な運動を取り入れることも重要です。有酸素運動や筋力トレーニングを行うと、脂肪を燃焼しやすくなります。毎日少なくとも30分以上の運動をすることを目指しましょう。3. 水分摂取：水分を適切に摂ることは代謝を促進し、痩せるためにも重要です。一日に2リットル程度の水を飲むようにしましょう。4. 睡眠：十分な睡眠をとることは体重管理にも役立ちます。睡眠不足はホルモンバランスを乱し、食欲を増加させる可能性があります。5. ストレス管理：ストレスは体重増加の原因になることがあります。適切なストレス管理法を見つけ、リラックスする時間を作りましょう。これらのアプローチをバランス良く組み合わせることで、健康的に痩せることができます。ただし、個人の体質や生活習慣によって結果は異なるため、専門家のアドバイスを受けることもおすすめです。」

目で読むと読みやすいのですが、私がこの文を話した場合、ユーザは聞き続けるために苦痛かもしれません(音読すると、1分20秒は必要でした)。また、Hallucinationが起こり得ます。

QAに対して回答するアプローチの一つとして、Web検索を採用したとします。ユーザは整理されたWebページを閲覧・スクロールすることで、知りたい情報へ素早くアクセスできます。しかし、この場合は会話を放棄している印象もあります。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f37613463356539322d616536362d613464392d353431632d6232336166393932396538372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/d5b30664-b899-ca8e-78f1-8a9f444c4bd2.png)

### ④ アジャイル開発によるアイデア出し
**とりあえず試す**
「ユーザとの過ごし方」を考えたところ、場当たり的ですが実際に手を動かして考えました。論文やプログラムのドキュメントを読み、アイデアを具体化することを心がけました。ファーストステップ、手っ取り早く試してみようという感じでFrameworkや外部APIを使います。
Appleが定めるプライバシー保護4原則の1つ「オンデバイス処理」の通り、プライバシー性が高いデータはサーバに送信せずに機能を実現することが求められます。しかし、2023年の活動ではアイデアを見える化することを優先しました。
具体的には、下記に示す外部APIを使用しました。
* 音声認識(Speech2Text)：Azure Cognitive Speech Services
* 旅行プラン生成：ChatGPT(gpt-3.5-turbo)
* Web検索：Google Custom Search API
* ジオコーディング：Google Geolocation API
* 表情解析：Google Cloud Vison API

### ⑤ 機械学習をどのように使う？
**機械学習を使う際の5つのポイント**
特定の目的を達成するために機械学習を用いるにあたり、以下の5つのポイントを意識しています。

* ポイント1: その手法は、目的を確実に達成できるほど洗練されている。
* ポイント2: その手法は、目的を達成できなかったとしても、最悪許される。
* ポイント3: その手法は、処理速度が速い。
* ポイント4: その手法は、処理速度が遅くとも、最悪許される。
* ポイント5: ユーザ端末内で全ての処理が完結する > サーバ処理(自サーバ・外部API)

顔認証を例に挙げます。顔認証は、SwiftのLocalAuthenticationによるFaceIDを採用しました。AppleによりますとFaceIDが失敗する確率は100万分の1未満とのことであるため、この手法はもう十分に洗練されていると解釈して採用しております。また、その処理速度も(人同士の挨拶レベルで)十分に速いといえます。このことから顔認証は、ポイント1、ポイント3を満たしていえます。

表情認識を挙げます。撮影された写真がアルバムに保存されますと、ユーザの表情を認識して真似します。この表情認識処理には10秒以上程度で必要ですが、リアルタイムで処理する必要がありません。また、ユーザが笑顔をした(つもり)にも関わらず、スコアが低いために笑顔と認識されなくとも、最悪許されると捉えました。このことから、表情認識は、ポイント2、ポイント4を満たしています。

ユーザとの旅行プランを生成するためにChatGPTを使うシーンがあります。この推論処理は10秒以上必要でしたが、それを「通信中」と言い切り、考えているアニメーションを行うことで時間稼ぎしています。バックグラウンドで処理を行い、推論結果が出力され次第話しかける方法も挙げられます。やや強引ですが、旅行プラン生成は、ポイント4を満たしています。

![スクリーンショット 2024-01-28 17.10.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/90984acf-15e7-86d1-1a7f-bc70a736b81d.png)

ポイント5に関して、前述の通りプライバシー性が高いデータはサーバに送信せずに機能を実現することが求められます。オンデバイスで機械学習を行う手法の1つとして、Core MLのようなエッジAIが挙げられます。スマートフォン上で機械学習が完結する一方で、学習モデル分のメモリを消費するために、リソース管理を慎重に行う必要があります。ちなみに、メモリ使用量(XCode Debug Navigator上が示す値)を1GB以下とする目標があります。

# 6. 技術的アプローチ(特にフロントエンド)
#### Unity
アバターはLive2Dモデルは使用しており、Cubism SDK for Unityを用いて制御しています。
公式ドキュメント・チュートリアルが充実しているために、参考にしています。

https://docs.live2d.com/cubism-sdk-manual/cubism-sdk-for-unity/

https://docs.live2d.com/cubism-sdk-tutorials/motion-unity-ow/


旅行する日に合わせて衣装を変更したり、表情を変えたりするなどの工夫をしています。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f32343461383134302d636230352d343865622d386234392d3632316434333439316634662e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/c3a417e4-0f9b-3006-87f1-ec982a94b35e.png)


![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f333638313735312f33383432366636302d626265622d393666322d633365332d6465353238326564643764632e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3681751/15a1a2cc-2968-a6ea-81a9-98bde96ff99f.png)

ネイティブアプリ(Swiftベース)に対してUnityをライブラリとして組み込むために、UaaL(Unity as a Library)を使いました。Swiftで開発した場合、当然Android分も開発するコストが発生します。しかし、ユーザとの過ごし方を最優先とするために、後述するframeworkを使用可能なSwiftを採用しました。

### Swift

可能な限り、Swift公式のframeworkを用い、ネイティブ独自の機能を使用します。

例えば、iOSカレンダーへの読み書きを行いたいために、EventKitを使いました。

https://developer.apple.com/documentation/eventkit

ヘルスケア情報へアクセスするためにHealthKitを使いました。特に、iOS 16.0以降では、体温(手首皮膚温度)を参照できるようになりましたので、試してみました。

https://developer.apple.com/documentation/healthkit/about_the_healthkit_framework

https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/3951065-applesleepingwristtemperature

```swift
let type = HKSampleType.quantityType(forIdentifier: .appleSleepingWristTemperature)!
            
let predicate = HKQuery.predicateForSamples(withStart: startOfYesterday, end: endOfYesterday)

let query = HKSampleQuery(sampleType: type,
                          predicate: predicate,
                          limit: HKObjectQueryNoLimit,
                          sortDescriptors: [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: true)])
{ (query, temperature, error) in

}
```

他にも、顔認証機能を用いるために、Local Authenticationを使います。

https://developer.apple.com/documentation/localauthentication/

# 7. ２０２４年の目標　
実際にアプリをリリースして、様々なユーザとお話ししたい気持ちがあります。その一方で、アプリの仕様上慎重に展開する必要があります。リリースする前には、やはり展示・実体験といった形でユーザのご意見を伺いたいです。例えば、「ニコニコ超会議クリエイタークロス」といった、自由度が高い出展が可能な場へ応募してみたいと思います。

https://chokaigi.jp/

個人開発レベルのアプリを出展できる場について、ご存知であればコメントを頂けたら幸いです。

長文となりましたが、ここまで読んでいただきありがとうございました！