「帰宅前に LINE でメッセージを送るだけで、Google Home が家族に知らせてくれる」——そんな仕組みを我が家に導入しました。
家族 LINE のグループや個人チャットにメッセージを送ると、LINE Bot が Webhook でラズパイに通知し、Google Home がリビングや子供部屋で「〇〇 by △△さん」と読み上げます。
本記事では、LINE Bot Webhook + Flask サーバーを使って LINE メッセージを Google Home に音声通知する実装方法を解説します。
なぜこの機能を作ったのか?
家族はそれぞれスマートフォンを持っていますが、テーブルに置きっぱなしにしていたり、音量を絞っていたりと、LINE の通知音に気づかないことがよくありました。
特に「もうすぐ帰るよ」「夕飯できたよ」「お風呂が沸いたよ」のような短いメッセージは、スマホを手に取らずに家族全員に届いてほしいものです。
そこで「LINE に送るだけで家中の Google Home に声が届く」仕組みを作り、スマホを見ない家族にも確実に情報が伝わるようにしました。

LINE に送るだけで Google Home が家族に声で知らせてくれる!スマホを見なくても伝わる!
実現したいこと
- 家族 LINE のグループや個人チャットへのメッセージをラズパイが受信し、Google Home(リビング)で自動読み上げ
- 子供部屋専用の LINE チャンネルを作り、子供部屋の Google Home で最大音量・ランダム音声で読み上げ
- メッセージ送信者の名前を自動的に末尾に付けて「誰からのメッセージか」を明示(例:「もうすぐ帰るよ by パパ」)
- URL が含まれるメッセージは「ウェブページへのリンクあり」と短縮して読み上げ
- LINE からスラッシュコマンドで Google Home の音量をリモート調整
この記事でわかること
- LINE Bot SDK(linebot)で Webhook を受信し Flask Blueprint で処理する方法
- 複数の LINE チャンネルを一つの Flask サーバーで同時に処理するパターン
- 受信メッセージから送信者名・音声名を settings.json から引き当てる方法
- URL を含むメッセージを自動的に短い説明文に置き換えて読み上げる方法
- LINE からスラッシュコマンドで Google Home の音量・ミュートをリモート制御する方法
- 子供部屋専用チャンネルで最大音量・ランダム音声を実現する方法
必要な準備と用意するもの
- Raspberry Pi(例:Raspberry Pi 5)
- Google Home / Google Nest(リビング用・子供部屋用など)
- Python 3
- flask
- line-bot-sdk(linebot)
- googlehome(自作ライブラリ)
- LINE Developers
- LINE Bot チャンネル(リビング用・子供部屋用など、用途別に作成)
- チャンネルアクセストークン・チャンネルシークレット
- 外部公開 URL(LINE Webhook 受信用。ngrok や自宅サーバーの HTTPS 公開など)
完成イメージ
完成後のシステムは下記のように動作します。
- LINE → Google Home 読み上げ(リビング用):家族 LINE のグループや個人チャットにメッセージを送ると、LINE Bot が Webhook でラズパイに通知 → Google Home が「〇〇 by △△さん」と読み上げる
- LINE → Google Home 読み上げ(子供部屋用):子供部屋専用 LINE Bot にメッセージを送ると、子供部屋の Google Home が最大音量・ランダム音声で読み上げる
- スラッシュコマンド:LINE に「/volume 0.5」や「/mute」と送ると、Google Home の音量をリモートで変更できる
システムの仕組み
LINE Bot にメッセージが送信されると、LINE プラットフォームから Webhook(HTTP POST)がラズパイの Flask サーバーに届きます。
Flask Blueprint で各チャンネルのルートを定義し、LINE Bot SDK の WebhookHandler で署名検証と処理振り分けを行います。
チャンネルは用途ごとに複数作成しており、それぞれ異なるルートに Webhook を設定します。
/googlehome/:リビングの Google Home で読み上げ(家族グループ LINE や個人チャット用)/googlehome_<子供の名前>/:子供部屋の Google Home で読み上げ(最大音量・ランダム音声)
Google Home への発話は自作ライブラリ「googlehome」を使用しています。実装の詳細は別記事を参照してください。
実装のポイント
複数チャンネルを一つの Flask サーバーで処理
LINE Bot のチャンネルを用途別に分けると、それぞれの Webhook URL が必要です。しかし複数の Flask サーバーを立ち上げるのは非効率なため、一つの Flask アプリに Blueprint でルートをまとめ、チャンネルごとの WebhookHandler を使い分けます。
チャンネル分離で柔軟な制御が可能
リビング用チャンネルと子供部屋用チャンネルを分けることで、音量・音声・動作をチャンネルごとに独立して設定できます。家族のグループ LINE とは別に子供部屋専用の LINE Bot を作ることで、子供への呼びかけ専用スピーカーとして活用できます。
送信者名の自動付与
settings.json に LINE ユーザー ID と名前・音声名のマッピングを定義しておくことで、誰からのメッセージかを自動的に識別します。メッセージ末尾に「by △△」を付加することで、Google Home が読み上げた際に誰からの連絡かすぐわかります。
例:パパが「もうすぐ帰るよ」と送ると → Google Home が「もうすぐ帰るよ by パパ」と読み上げる
URL の自動置換
LINE メッセージに URL が含まれると、Google Home が URL をそのまま読み上げてしまい非常に聞きづらくなります。そこでメッセージ受信時に URL を検出し、自動的に短い説明文に置き換えます。
- メッセージ全体が URL → 「ウェブページへのリンクが送信されました。」
- URL を含むテキスト → URL 部分を「[ウェブページへのリンクあり]」に置換して読み上げ
スラッシュコマンドで音量をリモート制御
メッセージが「/」から始まる場合はコマンドとして解釈し、Google Home のパラメータを変更します。音量調整やミュートを LINE から遠隔で操作できるため、外出先から「帰宅前に音量を上げておく」などの使い方ができます。
/volume 0.7:音量を 0.7 に設定(0.0〜1.0)/up_volume:音量を上げる/down_volume:音量を下げる/mute:ミュート/unmute:ミュート解除/status:現在の状態(音量・IP・再生状態など)を LINE に返信/help:コマンド一覧を LINE に返信
子供部屋チャンネルの最大音量・ランダム音声
子供部屋用チャンネルのメッセージハンドラでは、毎回音量を 1.0(最大)・volume_gain_db を 16.0 に設定してから読み上げます。音量が最大でない状態でも次のメッセージ受信時に自動的に最大音量に戻るため、誰かがコマンドで音量を下げていても確実に子供に届きます。
また googlehome.get_random_voice() で毎回異なる音声を選ぶことで、単調さを避けて聞き取りやすくしています。
子供が勉強や遊びに集中していても気づけるよう、爆音設定にしています。夜間は親が音量コマンドで下げることもできます。
事前準備
LINE Bot チャンネルの作成
LINE Developers コンソール(https://developers.line.biz/)でプロバイダーと Messaging API チャンネルを作成します。
用途ごとにチャンネルを分けて作成し、それぞれのチャンネルシークレットとチャンネルアクセストークンを取得してください。
- LINE Developers にログイン
- プロバイダーを作成(または既存のものを選択)
- 「Messaging API」チャンネルを作成
- 「チャンネル基本設定」からチャンネルシークレットを取得
- 「Messaging API 設定」からチャンネルアクセストークン(長期)を発行
- 「Messaging API 設定」の Webhook URL にラズパイのエンドポイントを登録(例:
https://example.com/webhooks/googlehome/) - 「Webhook の利用」を ON にする
- LINE Bot をグループチャットに招待する(グループ通知の場合)
LINE Webhook は HTTPS が必須です。ラズパイを自宅サーバーとして公開する場合は、Let’s Encrypt 等で SSL 証明書を取得するか、ngrok などのトンネリングサービスを利用してください。
LINE ユーザー ID の取得
送信者名を自動付与するために、家族それぞれの LINE ユーザー ID を事前に取得しておく必要があります。
ユーザー ID は LINE Bot に話しかけた際の Webhook イベントの event.source.user_id から確認できます。Flask サーバーを起動してメッセージを送り、ログに出力して確認するのが手軽です。
ライブラリのインストール
pip install flask line-bot-sdk実装方法
設定ファイル(settings.json)
LINE チャンネルのシークレット・アクセストークンと、家族それぞれのユーザー情報を JSON で管理します。
{
"line": {
"user": {
"user1": {
"id": "<LINEユーザーID>",
"name": "<名前>",
"voice_name": "ja-JP-Wavenet-A"
},
"user2": {
"id": "<LINEユーザーID>",
"name": "<名前>",
"voice_name": "ja-JP-Wavenet-B"
}
},
"channel": {
"googlehome": {
"channel_secret": "<チャンネルシークレット>",
"access_token": "<アクセストークン>"
},
"googlehome_<子供の名前>": {
"channel_secret": "<チャンネルシークレット>",
"access_token": "<アクセストークン>"
}
}
}
}voice_name は Google Cloud Text-to-Speech の音声名です。家族ごとに異なる音声を設定することで、Google Home の声で誰からのメッセージかを聞き分けることもできます。
LINE Webhook サーバー(dispacher.py)
Flask Blueprint を使って LINE Webhook を受け取る処理を実装します。チャンネルごとに WebhookHandler を作成し、受信したメッセージを Google Home に発話させます。
# -*- coding: utf-8 -*-
import googlehome
from flask import request, abort
from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import MessageEvent, TextMessage, TextSendMessage
from . import webhooks_bp
notify = googlehome.Notify(googlehome.GoogleHome.LIVING)
notify_childroom = googlehome.Notify(googlehome.GoogleHome.CHILD_ROOM)
handler_googlehome = WebhookHandler(settings['line']['channel']['googlehome']['channel_secret'])
handler_googlehome_child = WebhookHandler(settings['line']['channel']['googlehome_<子供の名前>']['channel_secret'])
# ---- リビング用チャンネルの Webhook エンドポイント ----
@webhooks_bp.route("/googlehome/", methods=['POST'])
def callback_googlehome():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
try:
handler_googlehome.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
# ---- 子供部屋用チャンネルの Webhook エンドポイント ----
@webhooks_bp.route("/googlehome_<子供の名前>/", methods=['POST'])
def callback_googlehome_child():
signature = request.headers['X-Line-Signature']
body = request.get_data(as_text=True)
try:
handler_googlehome_child.handle(body, signature)
except InvalidSignatureError:
abort(400)
return 'OK'
# ---- 共通:送信者情報の取得とメッセージ前処理 ----
def get_line_sending_info(event, line_bot_api: LineBotApi) -> tuple:
userid = event.source.user_id
try:
user_name = line_bot_api.get_profile(userid).display_name
except Exception:
user_name = 'アノニマス'
# settings.json から送信者名と音声名を取得
sender_name = None
voice_name = None
for user in settings['line']['user']:
if userid == settings['line']['user'][user]['id']:
sender_name = settings['line']['user'][user]['name']
voice_name = settings['line']['user'][user]['voice_name']
break
message = event.message.text
# URL を含む場合は短い説明文に置き換え
if message.startswith("http"):
message = "ウェブページへのリンクが送信されました。"
elif "http" in message:
message = message.split("http")[0] + "[ウェブページへのリンクあり]"
line_bot_name = line_bot_api.get_bot_info().display_name
return line_bot_name, sender_name, voice_name, message
# ---- スラッシュコマンドの処理 ----
def set_googlehome_parameters(notify: googlehome.Notify, message: str) -> str | None:
if not message.startswith("/") or len(message) < 2:
return
parts = message.strip().split()
command = parts[0][1:] # "/" を除去
args = parts[1:]
if command == "volume":
notify.volume = float(args[0])
elif command == "up_volume":
notify.up_volume()
elif command == "down_volume":
notify.down_volume()
elif command == "mute":
notify.mute()
elif command == "unmute":
notify.unmute()
elif command == "status":
status = notify.status
return (
f'name: {status.get("name")}\n'
f'ip: {status.get("ip")}\n'
f'Volume: {status.get("volume")}\n'
f'tts_voice_name: {notify.tts_voice_name}'
)
elif command == "help":
return (
'/volume: 音量を変更します (0.0 - 1.0)\n'
'/up_volume: 音量を上げます\n'
'/down_volume: 音量を下げます\n'
'/mute: ミュートします\n'
'/unmute: ミュートを解除します\n'
'/status: ステータスを表示します\n'
'/help: ヘルプを表示します'
)
# ---- リビング用メッセージハンドラ ----
@handler_googlehome.add(MessageEvent, message=TextMessage)
def handle_message_googlehome(event):
line_bot_api = LineBotApi(settings['line']['channel']['googlehome']['access_token'])
line_bot_name, sender_name, voice_name, message = get_line_sending_info(event, line_bot_api)
if message.startswith("/"):
reply_message = set_googlehome_parameters(notify, message)
if reply_message:
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_message))
else:
message = message.strip()
if sender_name is not None:
message = message + ' by ' + sender_name
notify.speak(message, voice_name=voice_name)
# ---- 子供部屋用メッセージハンドラ(最大音量・ランダム音声)----
@handler_googlehome_child.add(MessageEvent, message=TextMessage)
def handle_message_googlehome_child(event):
line_bot_api = LineBotApi(settings['line']['channel']['googlehome_<子供の名前>']['access_token'])
line_bot_name, sender_name, voice_name, message = get_line_sending_info(event, line_bot_api)
if message.startswith("/"):
reply_message = set_googlehome_parameters(notify_childroom, message)
if reply_message:
line_bot_api.reply_message(event.reply_token, TextSendMessage(text=reply_message))
else:
# 毎回音量を最大にする
if notify_childroom.volume < 1.0:
notify_childroom.volume = 1.0
notify_childroom.volume_gain_db = 16.0
# 声を毎回ランダムに変える
voice_name = googlehome.get_random_voice()
notify_childroom.speak(message, None, voice_name)systemd への登録
Flask サーバー(dispacher.py を含む Web サーバー)はラズパイ起動時に自動起動するよう systemd サービスとして登録します。
[Unit]
Description=Smarthome Flask Server
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/<username>/smarthome/server.py
Restart=always
User=<username>
[Install]
WantedBy=multi-user.targetsudo systemctl enable smarthome_server.service
sudo systemctl start smarthome_server.serviceコードの解説
Webhook 署名の検証(セキュリティ)
LINE SDK の WebhookHandler は X-Line-Signature ヘッダーを自動的に検証します。チャンネルシークレットで HMAC-SHA256 署名を検証するため、第三者からの不正なリクエストを弾くことができます。
署名検証に失敗した場合は InvalidSignatureError がスローされ、abort(400) でリクエストを拒否します。
チャンネルシークレットとアクセストークンは絶対にソースコードにハードコードせず、settings.json や環境変数で管理してください。
送信者名の解決ロジック
get_line_sending_info() では、イベントの user_id を settings.json のユーザーリストと照合します。
一致するエントリが見つかれば登録済みの名前と音声名を使用し、見つからなければ sender_name = None となるため、「by △△」の付加をスキップします。家族以外の人が Bot にメッセージを送った場合でも正常に動作します。
グループトークと個人トークの両対応
LINE Bot はグループチャットに招待することも、個人チャットで利用することもできます。
グループトーク内では Bot 宛のメッセージだけでなくグループ内の全メッセージが Webhook として届くため、不要なメッセージが読み上げられる場合があります。家族のみのグループであれば全メッセージ読み上げで問題ありませんが、大人数のグループに Bot を入れる場合は送信者 ID によるフィルタリングを検討してください。
グループトークで Bot を追加すると「応答メッセージ」が自動で送信される場合があります。LINE Developers の「応答設定」で「応答メッセージ」をオフ、「Webhook」をオンに設定してください。
スラッシュコマンドの拡張
set_googlehome_parameters() に条件分岐を追加するだけでコマンドを自由に増やせます。例えば「/speak おはよう」で任意のメッセージを読み上げさせたり、「/play」で特定の音声ファイルを再生させたりといった拡張が可能です。
動作確認
- Flask サーバーを起動する
- LINE Developers の Webhook URL にラズパイのエンドポイントを登録し「検証」ボタンを押す → 200 OK が返ることを確認
- LINE Bot をグループに招待し(または個人チャットで)、メッセージを送信する → リビングの Google Home がメッセージを読み上げることを確認
- メッセージ末尾に「by △△」が付いていることを確認(settings.json にユーザー登録済みの場合)
- 「/help」と送信し、LINE にコマンド一覧が返信されることを確認
- 「/volume 0.3」と送信し、音量が変わることを確認
- URL を含むメッセージを送り、「ウェブページへのリンクあり」に置換されて読み上げられることを確認
LINE Developers の「検証」ボタンで 200 OK が返らない場合は、ラズパイ側のサーバーが起動しているか、外部公開 URL が正しく設定されているか、HTTPS 証明書が有効かを確認してください。
まとめ
LINE Bot Webhook と Flask を組み合わせることで、家族 LINE のメッセージを Google Home が自動で読み上げるシステムが実現できました。
- Flask Blueprint で複数の LINE チャンネルを一つのサーバーで処理できる
- settings.json でユーザーごとの名前・音声を管理し、送信者名を自動付与できる
- URL 自動置換で聞き取りづらい読み上げを防げる
- スラッシュコマンドで LINE から Google Home の音量をリモート制御できる
- チャンネルを分けることで、リビング用・子供部屋用と用途別に動作を変えられる
「帰る前に LINE で一言送るだけで、家族全員が Google Home の声で気づいてくれる」——そんな小さな仕組みが日常のコミュニケーションをスムーズにします。ぜひ試してみてください。

