All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 33s
165 lines
4.2 KiB
Markdown
165 lines
4.2 KiB
Markdown
# iOS
|
|
|
|
## iPhoto Export
|
|
|
|
1. Download all your photos in batches of 1000
|
|
2. Extract all zip files
|
|
3. Use `find` to copy all files to photo-archive
|
|
|
|
find ./icloud -type f -not -name '*.zip' -print0 | xargs -0 -I % /bin/bash -c 'cp -v --backup=numbered "%" photo-archive/'
|
|
|
|
4. Verify all photos were copied successfully
|
|
|
|
find ./icloud -type f -not -name '*.zip' | wc -l
|
|
find ./photo-archive -type f | wc -l
|
|
|
|
5. Rename duplicates so they have the correct extension
|
|
|
|
```bash
|
|
# Collect duplicates
|
|
find photo-archive -name '*.~*' > duplicates.txt
|
|
cat duplicates.txt | wc -l
|
|
|
|
# dry run convert duplicates named *.~n~ to something else
|
|
for item in $(cat duplicates.txt); do echo mv $item photo-archive/$(python -c "from pathlib import Path; number=Path(\"$item\").suffix ;name = Path(Path(\"$item\").stem); print(name.stem + '_' + number.replace('~','').replace('.','') + name.suffix)"); done
|
|
# actual rename
|
|
for item in $(cat duplicates.txt); do mv $item photo-archive/$(python -c "from pathlib import Path; number=Path(\"$item\").suffix ;name = Path(Path(\"$item\").stem); print(name.stem + '_' + number.replace('~','').replace('.','') + name.suffix)"); done
|
|
|
|
# verify
|
|
find photo-archive -name '*.~*'
|
|
find ./photo-archive -type f | wc -l
|
|
```
|
|
|
|
6. Remove live photos
|
|
|
|
Live photos show up as a .MOV files. They should be the only .MOV files in the folder. Remove
|
|
them with:
|
|
|
|
```bash
|
|
find photo-archive -name '*.MOV' -delete
|
|
|
|
# verify
|
|
find ./photo-archive -type f | wc -l
|
|
```
|
|
|
|
7. Organize by year
|
|
|
|
To keep your photos folder from getting too bloated you should organize your photos into
|
|
subfolders by (at least) year.
|
|
|
|
[Phockup](https://github.com/ivandokov/phockup) seems to be able to do this:
|
|
|
|
```bash
|
|
podman run -v ~/Pictures:/mnt ivandokov/phockup:latest /mnt/iphone /mnt/iOS -d YYYY
|
|
```
|
|
|
|
## Photos Export
|
|
|
|
<https://github.com/icloud-photos-downloader/icloud_photos_downloader>
|
|
|
|
```bash
|
|
podman run -it --rm --name icloudpd \
|
|
-v $(pwd)/iPhotos:/data \
|
|
-e TZ=America/New_York \
|
|
icloudpd/icloudpd:latest \
|
|
icloudpd \
|
|
--directory /data \
|
|
--username apple@ducoterra.net \
|
|
--watch-with-interval 3600
|
|
```
|
|
|
|
You can browse all downloaded photos with `feh`:
|
|
|
|
```bash
|
|
pacman -S feh
|
|
|
|
feh --recursive --scale-down -d -S filename $(pwd)/iPhotos
|
|
```
|
|
|
|
## Extensions
|
|
|
|
- PNG
|
|
- HEIC: iOS HDR photo
|
|
- MOV
|
|
- DNG: iOS raw photo
|
|
- JPG
|
|
- 3gp: quicktime video file
|
|
- MP4
|
|
- GIF
|
|
- WEBP: Google photo container
|
|
- CR2: Canon raw photo
|
|
|
|
## Conversion
|
|
|
|
You will need `imagemagick` and `libraw`:
|
|
|
|
```bash
|
|
pacman -S imagemagick libraw
|
|
```
|
|
|
|
Then you can convert any image with magick:
|
|
|
|
```bash
|
|
magick input.HEIC output.png
|
|
magick input.HEIC output.jpeg
|
|
```
|
|
|
|
You get a list of all unique file extensions with:
|
|
|
|
```bash
|
|
find . -type f | awk -F. '!a[$NF]++{print $NF}'
|
|
```
|
|
|
|
Then use those file extensions to create a find command:
|
|
|
|
```bash
|
|
# -o means "or" in this case
|
|
# Parentheses are required
|
|
find . -type f -printf '%p\n' \( \
|
|
-iname '*.jpg' \
|
|
-o -iname '*.heic' \
|
|
-o -iname '*.dng' \
|
|
-o -iname '*.png' \
|
|
-o -iname '*.WEBP' \
|
|
-o -iname '*.cr2' \
|
|
\)
|
|
```
|
|
|
|
And then use xargs with magick to convert the images:
|
|
|
|
```bash
|
|
find . -type f \( \
|
|
-iname '*.jpg' \
|
|
-o -iname '*.heic' \
|
|
-o -iname '*.dng' \
|
|
-o -iname '*.png' \
|
|
-o -iname '*.WEBP' \
|
|
-o -iname '*.cr2' \
|
|
\) -print0 | xargs -0 -P $(nproc) -I % python -c "\
|
|
import subprocess; \
|
|
from pathlib import Path; \
|
|
to_folder = '/run/media/ducoterra/photos/'; \
|
|
p = Path(\"%\"); \
|
|
realpath = (str(p.parent) + '/' if str(p.parent) != '.' else '') + p.stem + '.jpg'; \
|
|
subprocess.run(['mkdir', '-p', to_folder + str(Path(realpath).parent)]); \
|
|
subprocess.run(['magick', \"%\", to_folder + realpath])"
|
|
```
|
|
|
|
And then videos:
|
|
|
|
```bash
|
|
find . -type f \( \
|
|
-iname '*.MOV' \
|
|
-o -iname '*.3gp' \
|
|
-o -iname '*.MP4' \
|
|
-o -iname '*.GIF' \
|
|
\) -print0 | xargs -0 -I % python -c "\
|
|
import subprocess; \
|
|
from pathlib import Path; \
|
|
to_folder = '/run/media/ducoterra/photos/'; \
|
|
p = Path(\"%\"); \
|
|
realpath = (str(p.parent) + '/' if str(p.parent) != '.' else '') + p.stem + '.mp4'; \
|
|
subprocess.run(['mkdir', '-p', to_folder + str(Path(realpath).parent)]); \
|
|
subprocess.run(['ffmpeg', '-i', '%', '-c', 'copy', to_folder + realpath])"
|
|
```
|