#!/bin/bash set -euo pipefail shopt -s nullglob nocaseglob LOGFILE="/home/lucas/logs/convertheic.log" mkdir -p "$(dirname "$LOGFILE")" exec >>"$LOGFILE" 2>&1 echo "Script started at $(date)" convert_one() { local src="$1" if [[ ! -f "$src" ]]; then echo "ERROR: file not found: $src" return 1 fi local base="${src%.*}" local dst="${base}.jpg" local tmp="${base}.tmp.jpg" echo "Converting: $src" # Convert HEIC -> JPEG if command -v magick >/dev/null 2>&1; then if ! magick "$src" \ -auto-orient \ -quality 100 \ -sampling-factor 4:4:4 \ "jpg:$tmp"; then echo "ERROR: local conversion failed: $src" rm -f "$tmp" return 1 fi else if ! docker run --rm \ -u "$(id -u):$(id -g)" \ -v "$PWD:/work" \ -w /work \ --entrypoint magick \ dpokidov/imagemagick \ "$src" \ -auto-orient \ -quality 100 \ -sampling-factor 4:4:4 \ "jpg:$tmp"; then echo "ERROR: docker conversion failed: $src" rm -f "$tmp" return 1 fi fi if [[ ! -s "$tmp" ]]; then echo "ERROR: output JPEG is empty: $tmp" rm -f "$tmp" return 1 fi echo "Copying metadata..." if ! exiftool \ -overwrite_original \ -TagsFromFile "$src" \ -all:all \ -unsafe \ "$tmp" >/dev/null; then echo "ERROR: metadata copy failed: $src" rm -f "$tmp" return 1 fi touch -r "$src" "$tmp" mv -f "$tmp" "$dst" if [[ ! -s "$dst" ]]; then echo "ERROR: final JPEG missing: $dst" return 1 fi rm -f "$src" echo "Done: $dst" echo "Removed: $src" } convert_mov() { local src="$1" if [[ ! -f "$src" ]]; then echo "ERROR: file not found: $src" return 1 fi local base="${src%.*}" local dst="${base}.mp4" local tmp="${base}.tmp.mp4" echo "Converting: $src" # MOV -> MP4, keep video/audio, drop unsupported data streams if ! ffmpeg \ -hide_banner \ -loglevel error \ -i "$src" \ -map 0:0 \ -map 0:1 \ -map_metadata 0 \ -c copy \ -movflags use_metadata_tags+faststart \ "$tmp"; then echo "ERROR: conversion failed: $src" rm -f "$tmp" return 1 fi if [[ ! -s "$tmp" ]]; then echo "ERROR: output MP4 is empty: $tmp" rm -f "$tmp" return 1 fi echo "Copying metadata..." if ! exiftool \ -overwrite_original \ -TagsFromFile "$src" \ -all:all \ -unsafe \ "$tmp" >/dev/null; then echo "ERROR: metadata copy failed: $src" rm -f "$tmp" return 1 fi touch -r "$src" "$tmp" mv -f "$tmp" "$dst" if [[ ! -s "$dst" ]]; then echo "ERROR: final MP4 missing: $dst" return 1 fi rm -f "$src" echo "Done: $dst" echo "Removed: $src" } process_file() { case "${1,,}" in *.heic) convert_one "$1" ;; *.mov) convert_mov "$1" ;; *) echo "Skipping unsupported file: $1" ;; esac } HOSTNAME_EXPECTED="mediahost" SOURCE_DIR="/data/nextcloud/syncuser/alina/Dropfolder" TARGET_DIR="/data/nextcloud/syncuser/camera" # If running on serverhost, perform initial sync if [[ "$(hostname)" == "$HOSTNAME_EXPECTED" ]]; then syncNC -d -c cd "$SOURCE_DIR" || exit 1 fi if [[ $# -gt 0 ]]; then process_file "$1" else shopt -s nullglob files=( *.heic *.mov ) if [[ ${#files[@]} -eq 0 ]]; then echo "No HEIC or MOV files found." else for f in "${files[@]}"; do process_file "$f" done fi fi # Run sync again if on serverhost if [[ "$(hostname)" == "$HOSTNAME_EXPECTED" ]]; then shopt -s nullglob for ext in jpg mp4; do files=("$SOURCE_DIR"/*."$ext") if ((${#files[@]})); then mv -n "${files[@]}" "$TARGET_DIR"/ fi done shopt -u nullglob syncNC -d -c fi