Gửi cảnh báo Telegram kèm ảnh camera và mô tả AI khi có người trước cổng bằng Home Assistant
Cách mình dùng Home Assistant, Frigate, AI Task và Telegram để gửi cảnh báo có người trước cổng kèm ảnh/video và mô tả ngắn bằng tiếng Việt.
Mình muốn cảnh báo camera ở nhà không chỉ dừng ở kiểu "có chuyển động". Cảnh báo kiểu đó dễ gây mệt vì lúc nào cũng phải mở app, tua clip, tự xem có gì đáng chú ý hay không.
Flow mình đang dùng hiện tại là:
- Frigate phát hiện người hoặc sự kiện ở khu vực cổng.
- Home Assistant nhận event qua MQTT.
- Home Assistant chụp snapshot hoặc lấy clip từ Frigate.
- AI Task phân tích hình từ camera.
- Telegram nhận ảnh/video/GIF kèm mô tả ngắn bằng tiếng Việt.

Kiến trúc tổng thể
Frigate camera event
|
v
MQTT topic: frigate/events
|
v
Home Assistant automation
|
+--> camera.snapshot / Frigate clip
| |
| v
| AI Task Gemini
| |
| v
+----> Telegram alert
Trong cấu hình thật của mình, phần này dùng:
- Frigate camera:
camera.gate_camera,camera.garage_camera - Occupancy sensors:
binary_sensor.doorbell_person_occupancy,binary_sensor.gate_camera_person_occupancy,binary_sensor.garage_camera_person_occupancy - AI Task:
ai_task.gemini_flashhoặcai_task.gemini_image_3 - Telegram actions:
telegram_bot.send_video,telegram_bot.send_animation,telegram_bot.send_photo - Shell command tạo GIF:
shell_command.create_gate_gif,shell_command.create_gif
Cấu hình Telegram trong Home Assistant
Phần notifier Telegram nằm trong configuration.yaml. Khi viết lại cho người khác dùng, chỉ nên để dạng mẫu như sau:
notify:
- platform: telegram
name: telegram_home_notifications
chat_id: YOUR_TELEGRAM_CHAT_ID
- platform: telegram
name: telegram_home_alerts
chat_id: YOUR_TELEGRAM_ALERT_CHAT_ID
Không nên đưa bot token, chat id thật, webhook thật hoặc private URL vào bài viết. Những giá trị đó nên để trong secrets.yaml, biến môi trường, hoặc cấu hình riêng của hệ thống.
Tạo shell command để ghép GIF từ nhiều snapshot
Mình vẫn giữ cách chụp nhiều ảnh liên tiếp rồi ghép thành GIF. Nó giúp xem nhanh chuyện gì vừa xảy ra mà không cần mở cả clip dài.
Trong configuration.yaml:
shell_command:
create_gate_gif: >-
python3 /config/python_scripts/create_gif.py
/media/snapshots/gate_snapshot1.jpg
/media/snapshots/gate_snapshot2.jpg
/media/snapshots/gate_snapshot3.jpg
/media/snapshots/gate_motion.gif
create_gif: >-
python3 /config/python_scripts/create_gif.py
/media/snapshots/garage_snapshot1.jpg
/media/snapshots/garage_snapshot2.jpg
/media/snapshots/garage_snapshot3.jpg
/media/snapshots/garage_motion.gif
Script Python tối giản:
from PIL import Image
import sys
image_paths = sys.argv[1:-1]
output_path = sys.argv[-1]
images = [Image.open(path) for path in image_paths]
images[0].save(
output_path,
save_all=True,
append_images=images[1:],
duration=500,
loop=0,
)
Automation chính: có người ở khu vực chuông cửa
Automation thật trong hệ của mình có alias Human at doorbell area. Nó nhận event từ MQTT topic frigate/events, nhưng chỉ chạy khi sensor người ở khu vực doorbell đang bật.

Phiên bản đã rút gọn và ẩn thông tin riêng:
alias: Human at doorbell area
description: Người bấm chuông trước cổng
trigger:
- platform: mqtt
topic: frigate/events
condition:
- condition: state
entity_id: binary_sensor.doorbell_person_occupancy
state: "on"
action:
- service: camera.snapshot
target:
entity_id: camera.gate_camera
data:
filename: /media/snapshots/gate_snapshot.jpg
- alias: Nhận diện người trong khung hình
service: ai_task.generate_data
data:
entity_id: ai_task.gemini_flash
task_name: Nhận diện người
instructions: >
Phát hiện chuyển động và mô tả ngắn gọn bằng tiếng Việt.
Nếu có người hoặc xe, mô tả người đang làm gì, đi bộ hay đi xe,
màu áo nổi bật nếu thấy rõ.
Không mô tả vật thể đứng yên hoặc tòa nhà.
Nếu không thấy nguyên nhân rõ ràng, trả lời:
Camera phát hiện chuyển động ở cổng.
attachments:
media_content_id: media-source://camera/camera.gate_camera
media_content_type: application/vnd.apple.mpegurl
response_variable: generated_content
- service: telegram_bot.send_video
data:
url: YOUR_HASS_URL/api/frigate/notifications/{{ trigger.payload_json["after"]["id"] }}/clip.mp4
caption: "{{ generated_content['data'] }}"
target: YOUR_TELEGRAM_CHAT_ID
inline_keyboard: >
Tắt thông báo:/automation.human_in_doorbell,
Gửi hình ảnh hiện tại:/snapshot
- delay: "00:10:00"
mode: single
Điểm quan trọng ở đây là không gửi cảnh báo ngay khi MQTT có event. Automation còn kiểm tra binary_sensor.doorbell_person_occupancy. Nhờ vậy cảnh báo tập trung vào người trước cổng, giảm bớt nhiễu từ các event không liên quan.
Script phụ: chụp nhiều ảnh, AI mô tả, gửi GIF lên Telegram
Mình cũng có script Gate - Snapshot, AI & Notification. Script này phù hợp khi muốn gửi một GIF ngắn thay vì chỉ gửi clip Frigate.

Flow của script:
- Chạy song song AI Task và chuỗi snapshot.
- Chụp 3 ảnh từ
camera.gate_camera. - Ghép 3 ảnh thành
gate_motion.gif. - Nếu AI không thấy bất thường thì dừng.
- Nếu có nội dung đáng chú ý thì gửi animation lên Telegram.
Phiên bản rút gọn:
alias: Gate - Snapshot, AI & Notification
sequence:
- parallel:
- service: ai_task.generate_data
data:
entity_id: ai_task.gemini_image_3
task_name: Nhận diện
instructions: >
Phân tích ảnh từ camera lối vào.
Nếu thấy người hoặc phương tiện, trả về mô tả cực ngắn gọn.
Không mô tả vật thể đứng yên, tòa nhà, hoặc chi tiết không liên quan.
Nếu không xác định được nguyên nhân, trả về:
Không phát hiện bất thường
attachments:
media_content_id: media-source://camera/camera.gate_camera
media_content_type: image/jpeg
response_variable: generated_content
- sequence:
- service: camera.snapshot
target:
entity_id: camera.gate_camera
data:
filename: /media/snapshots/gate_snapshot1.jpg
- delay: "00:00:01.5"
- service: camera.snapshot
target:
entity_id: camera.gate_camera
data:
filename: /media/snapshots/gate_snapshot2.jpg
- delay: "00:00:03.5"
- service: camera.snapshot
target:
entity_id: camera.gate_camera
data:
filename: /media/snapshots/gate_snapshot3.jpg
- service: shell_command.create_gate_gif
- if:
- condition: template
value_template: "{{ generated_content['data'] == 'Không phát hiện bất thường' }}"
then:
- stop: ""
else:
- service: telegram_bot.send_animation
data:
file: /media/snapshots/gate_motion.gif
target: YOUR_TELEGRAM_CHAT_ID
caption: "{{ generated_content['data'] }}"
mode: single
Trong thực tế, AI prompt nên càng ngắn càng tốt. Nếu prompt dài và mơ hồ, AI dễ mô tả cả cây, tường, bóng đổ, hoặc vật đứng yên. Với camera an ninh, mình chỉ cần câu ngắn kiểu:
Một người mặc áo sáng đang đứng trước cổng.
Biến thể cho garage
Garage dùng cùng ý tưởng nhưng đổi camera và file output:
camera.garage_camera/media/snapshots/garage_snapshot1.jpg/media/snapshots/garage_motion.gifshell_command.create_gifscript.garage_snapshot_ai_notification_duplicate
Automation Ghi lại chuyển động khu vực nhà xe đang làm nhiệm vụ route:
- Nếu
binary_sensor.gate_camera_person_occupancybật thì gọi script cổng. - Nếu
binary_sensor.garage_camera_person_occupancybật trong khung giờ đêm thì gọi script garage.
Đây là cách mình tách phần "khi nào chạy" khỏi phần "chụp, phân tích và gửi".
Biến thể nâng cấp: nhận diện shipper
Sau này mình thêm một flow riêng cho shipper. Ý tưởng là AI không chỉ hỏi "có người không", mà hỏi cụ thể:
Có bao nhiêu shipper đang đứng trước cổng?
Automation đầu tiên đọc Frigate event, dùng AI Task để đếm shipper, rồi set counter:
alias: Đếm shipper trước cổng
trigger:
- platform: mqtt
topic: frigate/events
condition:
- condition: template
value_template: "{{ trigger.payload_json['after']['label'] == 'person' }}"
action:
- service: ai_task.generate_data
response_variable: shipper_count
data:
entity_id: ai_task.gemini_flash
task_name: Camera AI
instructions: >
Đếm số shipper đang đứng trước cổng trong hình.
Chỉ dựa vào dấu hiệu như đồng phục giao hàng, mũ bảo hiểm,
túi giao hàng, thùng hàng, xe máy giao hàng.
Không nhận diện danh tính cá nhân.
Trả về đúng một dòng dạng số.
attachments:
media_content_id: media-source://camera/camera.gate_camera
media_content_type: application/vnd.apple.mpegurl
- if:
- condition: template
value_template: >
{{ (shipper_count['data'] | regex_findall_index('([0-9]+)', 0) | int(0)) > 0 }}
then:
- service: counter.set_value
target:
entity_id: counter.shipper_count
data:
value: >
{{ shipper_count['data'] | regex_findall_index('([0-9]+)', 0) | int(0) }}
- service: camera.snapshot
target:
entity_id: camera.gate_camera
data:
filename: /media/snapshots/gate_snapshot1.jpg
Automation thứ hai chỉ lo gửi Telegram khi counter lớn hơn 0:
alias: Thông báo shipper đứng trước cổng
trigger:
- platform: numeric_state
entity_id: counter.shipper_count
above: 0
action:
- service: telegram_bot.send_photo
data:
file: /media/snapshots/gate_snapshot1.jpg
caption: AI nhận diện được có shipper đứng trước cổng
inline_keyboard:
- Chụp lại camera cổng và garage:/snapshot
Cách này hay hơn khi mình muốn các automation khác cũng dùng lại trạng thái counter.shipper_count, ví dụ bật loa báo, hiện card trên dashboard, hoặc gửi thông báo khác cho người đang ở nhà.
Kiểm tra trong Developer Tools
Sau khi cấu hình xong, vào Developer Tools -> States kiểm tra các entity:
camera.gate_camera
camera.garage_camera
binary_sensor.doorbell_person_occupancy
binary_sensor.gate_camera_person_occupancy
binary_sensor.garage_camera_person_occupancy
automation.human_in_doorbell
script.garage_snapshot_ai_notification_duplicate
counter.shipper_count
Trong lần kiểm tra live state ngày 13/06/2026, automation Human at doorbell area, automation nhận diện shipper và automation gửi thông báo shipper đều đang bật. script.new_script và script.garage_snapshot_ai_notification_duplicate đang ở trạng thái off, đúng với kỳ vọng vì script chỉ chạy khi có trigger. counter.shipper_count đang là 0, còn các sensor hiện diện người ở doorbell, gate và garage đều đang off.
Điểm đáng chú ý là camera.gate_camera tại thời điểm kiểm tra đang unavailable, trong khi camera.garage_camera vẫn recording. Đây là lý do mình luôn kiểm tra Developer Tools trước khi debug YAML: nhiều lỗi cảnh báo không đến từ automation, mà đến từ camera, entity hoặc integration phía sau đang unavailable.
Một số lưu ý vận hành
- Không gửi ảnh nếu AI không thấy gì rõ ràng
Thêm một câu fallback cố định nhưKhông phát hiện bất thường, rồi dùngifđể dừng script. - Không đưa URL nội bộ hoặc token vào message
Nếu cần gửi clip Frigate, dùng URL đã được Home Assistant bảo vệ và tránh hardcode secret. - Đừng để AI nhận diện danh tính cá nhân
Prompt nên chỉ mô tả hành động, trang phục, xe, số lượng người, hoặc dấu hiệu shipper. Không nên yêu cầu AI đoán người đó là ai. - Chụp nhiều frame sẽ tốt hơn một frame
Một ảnh đơn có thể bị mờ hoặc đúng lúc người đi ra khỏi khung hình. Ba ảnh cách nhau 1-3 giây thường đủ để AI mô tả tốt hơn. - Tách automation và script
Automation quyết định khi nào chạy. Script quyết định chạy những bước nào. Cách này dễ debug và dễ tái sử dụng.
Kết luận
Điểm hay của Home Assistant là mình không bị khóa trong app camera hay app AI nào. Frigate lo phát hiện, Home Assistant lo điều phối, Gemini/AI Task lo mô tả, Telegram lo gửi cảnh báo.
Khi ghép lại, cảnh báo an ninh trở nên hữu ích hơn nhiều: mở Telegram lên là biết trước cổng đang có người, có clip hoặc ảnh kèm theo, và có một câu mô tả đủ ngắn để quyết định có cần mở camera xem kỹ hay không.