Last active
December 21, 2019 22:19
-
-
Save tnymlr/44a01f21c3f9af8657592e1f74954732 to your computer and use it in GitHub Desktop.
Download photos from an iPhone and convert HEIC to JPGs and MOVs to VP9 MKVs. Details: https://til.tmlr.xyz/notes/linux-ios-photo-sync/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
do_log() { | |
local scope=$1 | |
local msg=$2 | |
echo "[${scope}]: ${msg}" | |
} | |
do_error() { | |
do_log "$1" "$2" >&2 | |
} | |
log() { | |
do_log "${FUNCNAME[1]}" "$1" | |
} | |
error() { | |
do_error "${FUNCNAME[1]}" "$1" | |
exit 3 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -e | |
source "${HOME}/src/dotfiles/lib/log.sh" | |
CACHE_DIR="${HOME}/.cache/phsync" | |
ORIGINALS_DIR="${CACHE_DIR}/originals" | |
MOUNT_DIR="${CACHE_DIR}/phone" | |
SOURCE_DIR="${MOUNT_DIR}/DCIM" | |
PICTURES_DIR="${HOME}/Pictures" | |
PHOTOS_DIR="${PICTURES_DIR}/Photos" | |
TARGET_DIR="${PHOTOS_DIR}/Camera" | |
RSYNC_DONE="${PHOTOS_DIR}/rsync.done" | |
umount_phone() { | |
log "Unmounting phone from: $MOUNT_DIR" | |
if [ "$(mount | grep ifuse | wc -l)" -lt 1 ]; then | |
error "Nothing to unmount" | |
fi | |
while true; do | |
if fusermount -u "$MOUNT_DIR"; then | |
log "Phone is unmounted" | |
break | |
else | |
log "Failed to unmount phone, retrying in 1 sec" | |
sleep 1s | |
fi | |
done | |
} | |
trap "umount_phone; exit" ERR EXIT | |
validate_setup() { | |
log "Validating the environment..." | |
if which heif-convert; then | |
log "Found 'heif-convert' installed" | |
else | |
error "'heif-convert' is required to convert photos, install libheif" | |
fi | |
if which HandBrakeCLI; then | |
log "Found 'HandBrakeCLI' installed" | |
else | |
error "'HandBrakeCLI is require to convert videos" | |
fi | |
} | |
ensure_dirs() { | |
log "Preparing directories..." | |
mkdir -p "${MOUNT_DIR}" | |
mkdir -p "${TARGET_DIR}" | |
mkdir -p "${ORIGINALS_DIR}" | |
touch "${RSYNC_DONE}" | |
} | |
mount_phone() { | |
log "Mounting phone to: $MOUNT_DIR" | |
if ifuse "$MOUNT_DIR"; then | |
log "Phone is mounted at: $MOUNT_DIR" | |
else | |
error "Failed to mount phone at: $MOUNT_DIR" | |
fi | |
} | |
sync_photos() { | |
local target="$TARGET_DIR" | |
if [ $target == "" ]; then | |
error "Target can't be empty" | |
fi | |
log "Synchronizing photos [target=$target]" | |
if find "$SOURCE_DIR" -mindepth 1 -type d -name "*APPLE" -exec rsync \ | |
-azvhP \ | |
--size-only \ | |
--ignore-times \ | |
--no-perms \ | |
--no-owner \ | |
--no-group \ | |
--no-times \ | |
--exclude-from="$RSYNC_DONE" \ | |
{}/ \ | |
"$target" \;; then | |
log "Photo sync completed" | |
else | |
umount_phone | |
error "Failed to sync photos" | |
fi | |
} | |
record_changes() { | |
log "Marking received photos as 'synchronized'" | |
find "${TARGET_DIR}" -type f -exec basename {} \; | xargs -I {} /bin/sh -c \ | |
'grep -qxF "{}" '"$RSYNC_DONE"' || echo "{}" >> '"$RSYNC_DONE" | |
} | |
process_photos_from_to() { | |
local from="$1" | |
local to="$2" | |
log "Converting photos from: $from to: $to" | |
if [ "$from" == "" ]; then | |
error "'from' argument is not specified" | |
fi | |
if [ "$to" == "" ]; then | |
error "'to' argument is not specified" | |
fi | |
find "${TARGET_DIR}" -type f -name "*.$from" -exec basename -s .$from {} \; | \ | |
xargs -I {} /bin/sh -c \ | |
'heif-convert '"${TARGET_DIR}"'/{}.'"$from"' '"${TARGET_DIR}"'/{}.'"$to"' && mv '"${TARGET_DIR}"'/{}.'"$from"' '"${ORIGINALS_DIR}/" | |
} | |
process_photos() { | |
log "Converting photos..." | |
process_photos_from_to HEIC JPG | |
process_photos_from_to HEIF JPG | |
log "Done converting photos" | |
} | |
process_videos() { | |
log "Converting videos..." | |
find "${TARGET_DIR}" -type f -name "*.MOV" -exec basename -s .MOV {} \; | \ | |
xargs -I {} /bin/sh -c \ | |
'HandBrakeCLI -i '"${TARGET_DIR}"'/{}.MOV -o '"${TARGET_DIR}"'/{}.MKV --preset="VP9 MKV 2160p60" && mv '"${TARGET_DIR}"'/{}.MOV '"${ORIGINALS_DIR}/" | |
log "Done converting videos" | |
} | |
sync() { | |
validate_setup | |
ensure_dirs | |
mount_phone | |
sync_photos | |
record_changes | |
process_photos | |
process_videos | |
umount_phone | |
} | |
sync |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment