Có lẽ sở thích ít tốn tiền nhất mà thực sự hạnh phúc, chữa lành cả gia đình là… ngồi xem lại ảnh cũ trên bản đồ.

Nhà mình có hơn chục năm ảnh nằm trên Google Photos, hàng chục nghìn tấm đi khắp nơi. Mỗi lần muốn tìm lại tấm chụp ở Đà Lạt năm nào đó là lướt mỏi tay mà vẫn không ra. Nên mình nhờ Claude làm một tiện ích nhỏ cho Chrome: mở Google Maps lên, kéo tới đâu thì ảnh nhà mình chụp ở đó hiện ra ngay trên bản đồ. Tối ngồi cả nhà dò lại từng chỗ đã đi, vui phết.

Điều mình thích nhất: bạn không cần xin file của ai cả. Bạn dán một đoạn prompt vào Claude, Claude viết bộ file cho riêng bạn. Ảnh nằm trên máy bạn, không gửi đi đâu, không phải cấp quyền tài khoản Google cho ai.

Cần chuẩn bị gì

  • Máy tính Windows (Mac cũng được, chỉ cần nói rõ trong prompt) và trình duyệt Chrome
  • Tài khoản Claude
  • Python 3 (miễn phí)
  • Ổ đĩa trống bằng dung lượng thư viện Google Photos của bạn (xem tại one.google.com/storage). Ít chỗ thì làm từng đợt được.

Bước 1 – Xuất ảnh khỏi Google Photos

Bước 1: xuất ảnh bằng Google Takeout
  1. Vào takeout.google.com bằng tài khoản có ảnh.
  2. Bấm Bỏ chọn tất cả, rồi chỉ tick Google Photos.
  3. Bấm Bước tiếp theo: chọn gửi link qua email, xuất một lần, loại tệp .zip, kích thước 50 GB.
  4. Bấm Tạo bản xuất đúng một lần (bấm nhiều lần sẽ ra nhiều bộ trùng nhau).
  5. Chờ email của Google: vài giờ tới 1–2 ngày. Trong lúc chờ, làm luôn Bước 3.

Bước 2 – Tải các file zip về một thư mục

Bước 2: tải file zip về một thư mục

Tạo một thư mục, ví dụ D:\Takeout, tải hết các file takeout-…-001.zip, -002.zip… vào đó. Không cần giải nén. Link tải chỉ có hạn khoảng 1 tuần nên tải sớm nhé.

Bước 3 – Nhờ Claude viết bộ file

Bước 3: nhờ Claude viết bộ file và chạy CHAY.bat

Mở claude.ai, tạo cuộc trò chuyện mới và dán nguyên đoạn dưới. Claude sẽ trả về file anh-tren-maps.zip, bạn tải về và giải nén (ví dụ vào D:\anh-tren-maps). Dùng Mac thì đổi chữ “Windows” thành “macOS”.

Mình muốn tự làm một Chrome extension tên "Ảnh của mình trên Maps": mở Google Maps trên máy tính, kéo bản đồ tới đâu thì hiện ảnh Google Photos mình đã chụp ở đó. Máy mình dùng Windows. Ảnh lấy từ Google Takeout (các file takeout-*.zip, KHÔNG giải nén). Mọi thứ chạy trên máy mình, không gửi ảnh đi đâu, không dùng API của Google.

Hãy viết đầy đủ code, tự chạy thử với dữ liệu giả rồi đóng gói thành 1 file anh-tren-maps.zip cho mình tải về, gồm:

1) build_index.py (Python 3, dùng Pillow + pillow-heif):
- Nhận 2 tham số: thư mục chứa Takeout và thư mục extension. Quét cả file trong các .zip lẫn thư mục đã giải nén; zip hỏng hoặc đang tải dở thì bỏ qua và báo. Không quét thư mục extension.
- Đọc toàn bộ file JSON trước (JSON của 1 ảnh có thể nằm ở zip khác với ảnh). Ghép đúng các kiểu tên: IMG_1.jpg.supplemental-metadata.json, tên bị cắt ngắn (.supplemental-metad.json, tên dài bị cắt ~46 ký tự), ảnh trùng tên IMG_1(1).jpg ↔ IMG_1.jpg.supplemental-metadata(1).json, ảnh -edited dùng chung JSON gốc. Coi "Takeout/Google Photos/X" và "Takeout-2/Google Photos/X" là cùng album.
- Toạ độ lấy từ geoData rồi geoDataExif (bỏ giá trị 0,0); nếu thiếu thì đọc GPS trong EXIF (cả HEIC). Ngày chụp từ photoTakenTime, thiếu thì lấy từ EXIF. Giữ link "url" của Google Photos. JSON có toạ độ mà chưa thấy ảnh vẫn ghi lại.
- Gộp ảnh trùng (cùng ảnh nằm ở nhiều album/zip) theo tên file + toạ độ làm tròn.
- Tạo ảnh nhỏ 360px vào extension/t/xx/<hash>.jpg và ảnh xem lớn 1280px vào extension/p/xx/<hash>.jpg (biến PREVIEW_SIZE, đặt 0 để bỏ), xoay đúng chiều theo EXIF, chạy song song nhiều nhân CPU, ảnh đã có thì bỏ qua.
- Ghi extension/data/photos.json dạng gọn: mỗi ảnh [lat, lng, timestamp, ảnh nhỏ, url, tên, ảnh lớn]. Mỗi lần chạy CỘNG DỒN với kết quả cũ (để làm từng đợt zip rồi xoá zip).
- Có bộ nhớ đệm exif_cache.json (theo tên + kích thước + CRC) để lần sau không đọc lại ảnh cũ; lưu đệm mỗi 30 giây để lỡ tắt máy thì chạy tiếp được.
- In tiến độ bằng tiếng Việt: từng zip đang mở, mỗi 30 giây báo số ảnh đã xử lý. Tắt cảnh báo "Corrupt EXIF" vô hại.

2) CHAY.bat: bấm đúp là chạy. Tự cài pillow pillow-heif, HỎI mình thư mục chứa file zip (nhớ lại cho lần sau), rồi chạy build_index.py với thư mục extension nằm cạnh nó. Dùng chcp 65001 để hiện tiếng Việt, cuối có pause.

3) Thư mục extension (Manifest V3, content script trên https://www.google.com/maps/*, google.com.vn/maps/* và maps.google.com/*; data/, t/, p/ là web_accessible_resources):
- Đọc vị trí đang xem từ URL Maps: "@lat,lng,15z" (zoom) hoặc "@lat,lng,1234m" (vệ tinh, đổi ra zoom bằng: zoom = log2(156543.03392 × cos(lat) × chiều cao cửa sổ / số mét)). Tâm bản đồ = tâm cửa sổ. Kiểm tra URL mỗi 0,4 giây.
- Nút tròn 📷 góc phải dưới hiện số ảnh trong khung nhìn; bấm mở panel lưới ảnh 3 cột, sắp xếp "gần tâm nhất / mới nhất / cũ nhất".
- Ghim ảnh trên bản đồ: chiếu toạ độ bằng Web Mercator, ảnh gần nhau gom thành 1 ghim có số đỏ, không ghim đè nhau, không đè lên khung tìm kiếm/bảng thông tin của Maps (chỉ vẽ nơi elementFromPoint là canvas bản đồ). Tạm ẩn ghim khi đang kéo/zoom, ẩn khi bản đồ nghiêng hoặc xoay 3D. Có ô bật/tắt ghim.
- Bấm ghim: 1 ảnh thì mở ảnh lớn; nhiều ảnh thì panel chỉ hiện ảnh của ghim đó, có nút quay lại tất cả. Rê chuột lên ảnh trong panel thì ghim tương ứng phóng to, viền vàng.
- Xem ảnh lớn ngay trong panel: nút ‹ › và phím ← →, Esc quay lại; nút "Xem vị trí trên bản đồ" và nút "Mở ảnh gốc trên Google Photos". Video và ảnh chưa có ảnh nhỏ thì hiện ô tên file.
- Giao diện giống Google Maps, tiếng Việt, có chế độ tối.

4) HUONG-DAN.md: các bước cài đặt ngắn gọn bằng tiếng Việt.

Trước khi gửi, hãy tự tạo một bộ Takeout giả (đủ các kiểu tên JSON kể trên, ảnh chia ở 2 zip khác nhau, 1 zip hỏng) để chạy thử, và thử extension trên một trang giả lập Google Maps.

Sau đó cài Python (nhớ tick Add Python to PATH), mở thư mục vừa giải nén và bấm đúp CHAY.bat. Khi nó hỏi thì dán đường dẫn thư mục chứa zip. Ảnh nhiều thì để máy chạy vài tiếng, nhớ tắt chế độ ngủ. Lỡ tắt giữa chừng cứ chạy lại, nó làm tiếp từ chỗ cũ.

Bước 4 – Cài tiện ích vào Chrome

Bước 4: cài tiện ích vào Chrome
  1. Gõ chrome://extensions vào thanh địa chỉ.
  2. Bật Chế độ dành cho nhà phát triển ở góc phải.
  3. Bấm Tải tiện ích đã giải nén, chọn thư mục anh-tren-maps\extension.

Bước 5 – Mở Google Maps và dạo chơi

Bước 5: mở Google Maps xem lại ảnh

Mở Google Maps (đang mở sẵn thì bấm F5). Kéo tới nơi từng đi: ảnh hiện thành ghim, số đỏ là số ảnh ở điểm đó. Bấm vào ghim để xem ảnh lớn, hoặc mở bản gốc trên Google Photos.

Lỗi hay gặp

  • Gõ lệnh bị báo SyntaxError: bạn đang gõ vào cửa sổ Python. Đóng lại, chỉ cần bấm đúp CHAY.bat.
  • Không thấy nút 📷 trên Maps: bấm F5. Vẫn không có thì vào chrome://extensions xem tiện ích có bật không.
  • Hiện “Corrupt EXIF data”: cảnh báo vô hại, cứ để chạy tiếp.
  • Ghim chỉ có tên file, không có ảnh: ảnh nằm ở zip chưa tải. Tải nốt rồi chạy lại CHAY.bat.
  • Ảnh không hiện trên bản đồ: ảnh đó không có định vị (ảnh chụp màn hình, máy ảnh không GPS).

Gặp lỗi khác thì chụp màn hình gửi lại cho Claude trong cùng cuộc trò chuyện, nhờ nó sửa. Làm xong nhớ khoe mình xem nhà bạn đã đi những đâu nhé!