はじめに
やることをひとことで
常時BGMを再生し,ボタンを押された際に現在地点の観光案内を流すシステムを作ります.
移動中にポチして勝手にニヤニヤ楽しむことを想定しています.
動機&目的
散歩をしている最中に周囲の施設を見て「ここ何だろう?」と思うことが多いのですが,その度にスマホで地図を開くのが面倒に思いました.
そこで,「その土地のことを何でも教えてくれる,おせっかいで噂好きな地元の人」に相当する存在を作ることにしました.
まだ出来ていませんが,最終的には「常時BGMを流しておき,名所などの面白地点に近づいたときに,自動的に案内を放送してくれるシステム」を作りたいと思っています.
作成コードについて
こちらに公開しています.ご自由にお持ちください~
https://github.com/kazunosuke1108/tourist_guide
pathの管理などは結構適当なので,あまり期待しないでください...
ご不明点はいつでもご連絡ください.
方法
準備
今回の実装環境です.
- Laptop PC
- Windows 11 Home
- AMD Ryzen™ 7 7735Uプロセッサー(音声合成でCPUを使うので一応記載)
- Python
- Python 3.10.8
- Anaconda環境
- Gemini
- この辺りを参考に,API keyを取得しておきます
https://ai.google.dev/gemini-api/docs/quickstart?hl=ja&lang=python
- この辺りを参考に,API keyを取得しておきます
- VOICEVOX
- この辺りを参考に,GUIアプリを使えるようにしておきます
https://voicevox.hiroshiba.jp/
- この辺りを参考に,GUIアプリを使えるようにしておきます
- 再生する音楽のダウンロード等はご自身で実施し,適宜pathを書き換えるようにお願いします.
コーディング
1. 現在地の取得
get_geo_info.py
では、Windowsの位置情報APIを使って現在地を取得します。
asyncio
で非同期処理してます。
HeartRailsのAPIで地名(県・市・町)まで引っ張ってきます。
from get_geo_info import getGeoInfo
geo = getGeoInfo()
lat, lng, loc = geo.get_geo_info()
2. 観光案内文の生成(by Gemini)
地名が取れたら、Geminiでその場所の観光紹介文を1文だけ生成します。
モデルには gemini-2.0-flash
を使っていますが,ちょくちょく間違えます。
from get_introduction import get_introduction
text = get_introduction(loc)
print(text) # 例:「東京タワーは夜景がとても綺麗です。」
3. VOICEVOXで音声合成
生成された観光文を、VOICEVOXエンジン(ローカルで動作)で .wav
ファイルに変換します。
from talk import talk
talk.generate_wav(text, speaker=1, filepath='./audio.wav')
※ VOICEVOXエンジンが起動済み&ポート50021で待ち受けている必要があります。VOICEVOXのGUIアプリを立ち上げておけばOKです.
4. 地図の画像を用意
SeleniumとFoliumで、現在地にマーカーをつけた地図をレンダリング → 画面キャプチャして、画像ファイルとして保存します。
この辺りは完全に天の声にお任せしました.
import folium
from selenium import webdriver
# 中略
folium.Map(...).save("map.html")
driver.get("file://" + os.path.abspath("map.html"))
driver.save_screenshot("map_capture.png")
5. 音声+地図を再生&表示
pygame
を使って、BGMを流しつつ、観光ガイド音声を再生!地図画像も同時に表示されます。
再生が終わったらBGMの音量が元に戻ります。
6. ボタンで全部まとめて動かす(Tkinter)
「現在地案内を再生」ボタンを押すと、↑の流れが一通り自動で実行されます。
非同期スレッドで動かしてます。
おわりに
まとめ
- 現在地を取得して
- 観光ガイド文を生成して
- 音声化して
- 地図と一緒に再生する
という一連の流れを、自分のPCで完結する形で作りました。
今後のToDo
- ボタンを押したタイミングではなく,近くに観光案内すべき場所があるときに案内する
- ユーザの進路に応じて,「右に見えますのは~」的案内を入れる