Files
homelab/active/os_ios/ios.md
ducoterra 5184c84d50
All checks were successful
Podman DDNS Image / build-and-push-ddns (push) Successful in 33s
overhauls of most service docs
2025-07-22 18:29:07 -04:00

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])"
```