Na przełomie października i listopada rozpocząłem proces migracji zdjęć i filmów z Google Photo do lokalnego NAS-a (qnap), popełniając sporo błędów po drodze. Finalnie, mam uruchomioną lokalnie kopię zapasową zdjęć i filmów, opartą na Photoprism.
Mając do dyspozycji sprzęt i odpowiednią przestrzeń dysków w domowym homelabie, uznałem, że jest to właściwy czas na uporządkowanie cyfrowych bibliotek zdjęć i filmów, które rejestruję od ponad dekady za pomocą smartfonów.
Najprostsze rozwiązanie?
Na końcu wpisu (tutaj) znajdziesz (chyba) najprostsze rozwiązanie dla migracji do PhotoPrismy z Zdjęć Google
Podejście nr 1 - synchronizacja z poziomu QNAP
Mam od dawna QNAP z 2 × 4 TB, który częściej służył za dysk sieciowy niż za dysk do gromadzenia kopii zapasowych. Ma spore możliwości synchronizacji z topowymi chmurami, w tym Google Photos oraz OneDrive, dlatego naturalnie moją przygodę rozpocząłem od tej platformy. Zainstalowałem aplikację MARS ↗ (multi-application recovery service
), która umożliwia synchronizację bezpośrednio ze Zdjęć Google.
Zostawiłem na noc i rano biblioteka była już gotowa. Niestety mocno rozczarowałem się po dokładniejszym przeglądzie zawartości biblioteki. Okazało się, ze wszelkie detale zdjęć i filmów (metadane EXIF), na czym mocno mi zależało, były wykastrowane. Co więcej, nie było wszystkich pozycji z racji ograniczeń Google API (co widać na załączonej ilustracji).
Szybko usunąłem ściągniętą zawartość, podejmując sie kolejnej próby.
Podejście nr 2 - Google Takeout
Google Takeout ↗ jest usługą Google, która umożliwia pobieranie kopii danych z konta Google, takich jak wiadomości e-mail, zdjęcia, dokumenty, kontakty i wiele innych. Z tej opcji będę korzystał wielokrotnie.
Narzędzie jest proste w obsłudze i trzeba wyprać te opcje, które nas interesują, wybrać częstotliwość eksportu oraz typ i rozmiar pliku. Po dłuższej chwili na maila przychodzi lista z linkami do pobrania. Z przyczyn bezpieczeństwa Google nas weryfikuje nas każdorazowo po kliknięciu link, więc nie dodamy do wszelkich aplikacji odp. za masowe pobieranie plików.
Pierwszy błąd — format .tgz
i rozmiar pliku 10 GB
Chcąc zaoszczędzić czas na dodatkowanie akcje, przy eksporcie wybrałem opcje możliwie największy plik pojedynczego archiwum w stricte linuksowym formacie. Finalnie łączny rozmiar archiwum przekraczał 230 GB danych, co dało 23 pliki do pobrania.
Warto pamiętać, że Google do niedawna dawało nielimitowaną przestrzeń na zdjęcia i filmy, jeśli wyraziło się zgodę na ich kompresję.
Następnie, w terminalu wpisałem następujące polecenie do rozpakowania:
for f in *.tgz; do tar -xzvpf "$f" -C ../googlePhotos; done
Trzeba było się uzbroić w cierpliwość — bo w zależności od mocy obliczeniowej urządzenia — trwało od 2 do 5 godzin.
Po tej operacji sprawdziłem rozmiar rozpakowanych archiwum:
gdzie:
takeout
to katalog zawierający archiwa.tgz
googlePhotos
rozpakowany bałagan z Google Photos
WTF? Brakuje tylko 50 GB
materiałów! Wszystkie pliki ściągnęły się prawidłowo i pobieżnie je sprawdzałem pod kątem uszkodzeń. Wszystko się zgadzało, ale wciąż brakowało tych ~ 50 GB danych, czego nie akceptowałem i znów przystąpiłem do kolejnej próby.
Przy usuwaniu katalogów natrafiłem na kolejny ciekawy bug:
Przypadek? Prawie 1 miliard plików? Jakakolwiek próba listowania katalogów z taką ilością plików kończyła się ubiciem procesu. Podjąłem się jeszcze jednej próby generowania archiwum w tym formacie, ale znów, problem ten sam.
Podejście nr 2.1 - zmiana formatu na .zip
i max. rozmiar 4 GB
Po kolejnej nieudanej próbie doszedłem do wniosku, ze znacznie bezpieczniej będzie korzystanie ze sprawdzonego formatu .zip
i rozmiaru plików max. 4 GB. Udało się w miarę szybko ściągnąć i wypakować do odpowiednich katalogów. Łączny rozmiar wypakowanych plików multimedialnych nareszcie był zgodny z oczekiwaniami — czyli większy niż rozmiar wszystkich plików .zip
.
Ogarnianie bałaganu — MediaOrganizer
Przeglądając zawartość kopii zapasowych z Google Photos, można dostrzec jeden wielki bałagan:
- wszystkie zdjęcia są wrzucane do katalogów, zgodnych z rocznikiem;
- te same zdjęcia znajdują się w albumach, które sam tworzyłem (np. wakacyjne, rowerowe)
- dodatkowo, masa zdjęć znajdowała w tzw. albumach bez nazw z numeracją od 0 do 100;
To było dalece od moich oczekiwań / tolerancji; w erze przed chmurowymi rozwiązaniami z pomocą IrfanView ↗ sortowałem zdjęcia wg. kluczy YYYY-MM
i tworzyłem odpowiednie albumy. Chcąc uzyskać podobną architekturę, z niewielką pomocą AI stworzyłem odpowiedni zestaw skryptów (repo z skryptami ↗).
Wyszło bardzo dobrze, zmapowałem większość przypadków ale niektórych przeszkód nie mogłem przeskoczyć i zostawiłem sobie na koniec zabawy.
Cele
- migracja z katalogów dostarczonych przez google,
- filtrowanie zdjęc wg.:
- daty z exif;
- data utworzenia plików z atrybutu plików;
- data na bazie nazwy plików;
- data na bazie timestamp, ukrytym w nazwie plików;
- wrzucenie do odpowienich katalagów wg wzorca “YYYY-MM”;
- w ostateczności dodaje do ‘unsorted”;
- w przypadku filmów z rozszerzeniem
mp4
MP
;- data utworzenia plików z atrybutu plików;
- sortowanie wg daty, ukrytej w nazwie plików;
Dodatkowo:
- usuwa śmieci
.json
; - w przypadku powtórzenia się zdjęcia i filmu o takiej samej nazwie
- sprawdzić czy te pliki są takie same (pod względem daty utworzenia i wagi pliku):
- jeśli tak to dodać do końcówki nazwy
_duplicate
; - jeśli nie to dodać kolejne cyferki typu 001;
- jeśli tak to dodać do końcówki nazwy
- sprawdzić czy te pliki są takie same (pod względem daty utworzenia i wagi pliku):
- przypadek rozszerzeń pisanych dużymi i małymi literami
Efekt
Początkowo, skrypt uruchomiłem w QNAP (tak, też ma sh/bash
), ale ostatecznie “odkurzyłem” RPi4B, instalując RaspberryOS i zostawiłem na kilka dni.
Finalnie struktura wyglądała tak:
├── 2013-01
├── ..
├── 2023-02
├── ..
├── 2023-10
└── 2023-11
PhotoPrism
Pozostało zatem przejść do ostatniego etapu, jakim jest uruchomienie usługi PhotoPrism i migracji sporej ilości multimediów.
PhotoPrism to nowoczesna i funkcjonalna aplikacja do zdjęć i filmów, będącą świetną alternatywą dla innych usług chmurowych. Jej najważniejszą zaletą jest możliwość uruchomienia na własnym serwerze w domu zarówno w oparciu o RPI4B (ARM), jak i klasyczny thinclient typy Dell Wyse.
Spodobała mi się jej lista funkcji. Obsługuje rozpoznawanie twarzy i obiektów, automatyczną kategoryzację, ulubione, chwile, albumy i wiele więcej. Posiada również bogaty zestaw ustawień i zaawansowane możliwości importu.
Konfiguracja
Mając do dyspozycji gotowe konfiguracje ↗ dla konkretnych platform, wystarczy ściągnąć i uruchomić poleceniem:
docker compose up --build -d
TO wystarczy na początek dla większości, w moim przypadku wprowadziłem następujące modyfikacje:
-
w RPi zamontowałem zdalny dysk z zawartością zdjęć i multimediów
sudo mount -t nfs 192.168.1.8:/photos/ready ~/share/zdjecia
-
w
docker-compose.yml
w sekcjivolumes
zmieniłem ścieżkęvolumes: - "~/share/zdjecia:/photoprism/originals" # Original
Następnie zalogowałem się w przeglądarce do usługi PhotoPrism i rozpocząłem proces migracji. To samo można zrobić poziomu terminala za pomocą komendy
docker compose exec photoprism photoprism index --cleanup
W zależności od wielkości cyfrowej biblioteki, proces ten może trwać od kilku godzin do kilkunastu dni.
Dzięki tej zmianie, Raspberry PI miało dostęp do zdalnego katalogu z posortowanymi zdjęciami, które należy traktować jako Read-Only
.
Szkolny problem
Wszystko szło pięknie, dopóki nie uruchomiłem procesu indeksowania twarzy i regeneracji miniaturek. Okazało się, ze dość szybko zapełniłem dysk (mały bo “tylko” 128 GB).
Dokonałem małej reorganizacji projektu, polegającej na:
- migracji katalogów
storage
z dysku RPi na dysk NAS i podpięcia go jako zasobu zdalnego - podobnie zrobiłem z katalogiem
import
(to tutaj warto wrzucać pliki, które chcemy wgrać do albumu)
Restart usługi i ponowna regeneracja wszelki treści multimedialnych.
A dlaczego nie Qnap?
Parę miesięcy “testowałem” PhotoPrism, w wirtualnym kontenerze w QNAP, ale z racji słabego procesora i dramatycznie małej ilości pamięci (tylko 1 GB RAM), to nie miało racji bytu i często padał.
Stąd też postawiłem na RasperryPi 4B i z powodzeniem robi to, co do niego należy.
Alternatywne rozwiązania
Ten wpis mógłbym ograniczyć do poniższej sekcji, bo jak sie potem okazało: istniały równie ciekawe i (chyba) lepsze rozwiązania.
Wbudowany migrator w Photoprism
Zacznijmy od najważniejszego: Photoprism ma odpowiedni mechanizm do migracji ze Zdjęć Google i wystarczyłoby zajrzeć do tego rozdziału ↗ w dokumentacji.
- Rzecz jasna, trzeba samemu zadbać o eksport danych z Google Takeout
- Następnie rozpakować zawartość do katalogu
originals
lub `imports. - W zależności wybranego katalogu albo uruchomić proces indeksowania lub migracji zdjęć.
Metadane umieszczone w plikach .json
są wykorzystywane przy importowaniu multimediów.
Dla tych, co nie chcą PhotoPrism?
Jasne! Obok mojego skryptu, istnieje także Photoup ↗, który działa na podobnych zasadach, ale może działać jako usługa w Dockerze.
Synchronizacja
Dalsza synchronizacja zdjęc z lokalną usługą PhotoPrism może być realizowana na różne sposoby.
- Sam projekt świetnie działa jako
progressive-web-app
, które można zainstalować jako aplikację w telefonie - Można wykorzystać aplikację PhotoSync ↗, by bezpiecznie tworzyć kopie zapasowe telefonów z systemem iOS i Android w tle.
- Można wykorzystać Syncthing ↗ do synchronizacji między telefonem a katalogiem w NAS, a następnie manualnie / automatycznie importować do PhotoPrism.
Podsumowanie
Popełniłem sporo błędów przy organizacji zdjęć, począwszy od niezbyt udanego researchu na ten temat, poprzez niejasne zasady eksportowania zdjęć i problemów przy wypakowaniu zawartości a kończąc na braku przestrzeni dyskowej na Raspberry Pi.
Finalnie, jestem zadowolony z osiągniętego celu.
Bezpieczne przechowywanie obrazów na dysku NAS, do którego mam bezpośredni dostęp, oznacza, że jeśli chcę, mogę z łatwością przejść na nową aplikację hostowaną samodzielnie, bez żmudnego eksportowania z systemu komercyjnego. Nie wiem, czy to już koniec płacenia za usługi typu Google One, ale wreszcie mam uporządkowany ten segment cyfrowego życia.
Co dalej?
Kontrolowany dostęp z zewnątrz
Jeszcze nie dojrzałem do decyzji, czy chciałbym wystawić projekt na zewnątrz - spoza homelab. Prędzej czy później dojdzie do tego.
Pamiętaj o backupie
O ile wszystkie pliki cache czy miniaturki “siedzą” już w NAS, o tyle baza danych jest lokalnie na Raspberry PI. Na szczęście jest to dość dość prosta sprawa, bo dzięki mojej konfiguracji docker-compose.yml
ograniczam się do prostego polecenia:
docker compose exec photoprism photoprism backup -i -f
w katalogu ./storage/backup/mysql/
pojawia się plik bazy .sql
.