Skip to content

Instantly share code, notes, and snippets.

@avianey
Last active January 25, 2025 17:26
Show Gist options
  • Save avianey/c8b3756cde362543ecd521cadc29b186 to your computer and use it in GitHub Desktop.
Save avianey/c8b3756cde362543ecd521cadc29b186 to your computer and use it in GitHub Desktop.
Saving data from Google Photo by converting MP.jpg file to .jpg file, resizing images and converting old videos. Navigate Google Photo to download an extract of overweighted photos and then run the script below to remove the clip from the MP.jpg files. The script does takes care of keeping metadatas (GPS, date, camera info, ...) but saves a lot …
#!/bin/bash
# Set locale to ensure decimal point is handled correctly
export LC_NUMERIC="en_US.UTF-8"
# Check if the required tools are installed
if ! command -v ffmpeg &> /dev/null; then
echo "Error: ffmpeg is not installed. Please install ffmpeg and try again (sudo apt-get install ffmpeg)."
exit 1
fi
if ! command -v exiftool &> /dev/null; then
echo "Error: exiftool is not installed. Please install exiftool and try again (sudo apt-get install libimage-exiftool-perl)."
exit 1
fi
# Check if the user provided arguments
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <file.MP.jpg> or $0 <*.MP.jpg>"
exit 1
fi
# Expand input arguments to process files
files=("$@")
total_files="${#files[@]}"
processed_files=0
total_bytes_saved=0
# Function to display the progress bar
show_progress() {
local current=$1
local total=$2
local width=50 # Width of the progress bar
local percent=$((current * 100 / total))
local filled=$((percent * width / 100))
local empty=$((width - filled))
local bytes_saved_human=$(human_readable_size $total_bytes_saved)
printf "\r[%-${width}s] %3d%% (%d/%d) - %s | Total Saved: %s" \
"$(printf "#%.0s" $(seq 1 $filled))" $percent $current $total "$current_file" "$bytes_saved_human"
}
# Function to convert bytes to a human-readable format
human_readable_size() {
local bytes=$1
if ((bytes >= 1073741824)); then
# Convert to GB, rounded to two decimal places
printf "%.2f GB" "$(echo "scale=2; $bytes / 1073741824" | bc)"
elif ((bytes >= 1048576)); then
# Convert to MB, rounded to two decimal places
printf "%.2f MB" "$(echo "scale=2; $bytes / 1048576" | bc)"
elif ((bytes >= 1024)); then
# Convert to kB, rounded to two decimal places
printf "%.2f kB" "$(echo "scale=2; $bytes / 1024" | bc)"
else
# Display bytes directly if less than 1 kB
printf "%d bytes" "$bytes"
fi
}
# Process each file
for input_file in "${files[@]}"; do
processed_files=$((processed_files + 1))
current_file="$(basename "$input_file")"
# Check if the file exists
if [ ! -f "$input_file" ]; then
echo -e "\nWarning: File '$input_file' not found. Skipping."
continue
fi
# Generate temporary and output filenames
temp_image="temp_image.jpg"
output_file="${input_file%.MP.jpg}.jpg"
# Get the size of the input file
input_size=$(stat -c%s "$input_file")
# Extract the first frame as an image (removes MJPEG video stream)
ffmpeg -i "$input_file" -vf "select=eq(n\,0)" -q:v 2 -frames:v 1 "$temp_image" -y &> /dev/null
if [ $? -ne 0 ]; then
echo -e "\nError: Failed to extract the image for $input_file."
continue
fi
# Copy EXIF metadata from the original file to the extracted image
exiftool -overwrite_original -tagsfromfile "$input_file" "$temp_image" &> /dev/null
if [ $? -ne 0 ]; then
echo -e "\nError: Failed to copy EXIF metadata for $input_file."
rm -f "$temp_image"
continue
fi
# Get the size of the output file
output_size=$(stat -c%s "$temp_image")
bytes_saved=$((input_size - output_size))
total_bytes_saved=$((total_bytes_saved + bytes_saved))
# Rename the temporary image to the final output file
mv "$temp_image" "$output_file"
# Update progress bar
show_progress "$processed_files" "$total_files"
done
# Print a new line after completing the progress bar
echo -e "\nProcessing complete: $processed_files/$total_files files processed."
echo "Total bytes saved: $(human_readable_size $total_bytes_saved)"
#!/bin/bash
# Vérifier si une vidéo est fournie en entrée
if [ "$#" -lt 1 ]; then
echo "Usage: $0 <input_video>"
echo "Exemple: $0 input.mkv"
exit 1
fi
INPUT_VIDEO="$1"
BASENAME=$(basename "$INPUT_VIDEO" | sed 's/\.[^.]*$//') # Nom de base sans extension
OUTPUT_VIDEO="${BASENAME}.mp4"
# Vérifier si le fichier de sortie est identique au fichier d'entrée
if [ "$OUTPUT_VIDEO" == "$INPUT_VIDEO" ]; then
OUTPUT_VIDEO="${BASENAME}-2.mp4"
fi
# Si le fichier de sortie existe déjà, ajouter un suffixe pour éviter les conflits
if [ -f "$OUTPUT_VIDEO" ]; then
OUTPUT_VIDEO="${BASENAME}-2.mp4"
fi
# Convertir la vidéo
ffmpeg -i "$INPUT_VIDEO" \
-vf "scale='min(1280,iw)':'min(720,ih)':force_original_aspect_ratio=decrease" \
-c:v libvpx-vp9 -crf 30 -b:v 0 \
-c:a libmp3lame -q:a 4 \
-movflags +faststart \
"$OUTPUT_VIDEO"
echo "Conversion terminée : $OUTPUT_VIDEO"
#!/bin/bash
# Check if at least one argument (input GIF file) is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 <input.gif> [input2.gif] ..."
exit 1
fi
# Loop through all the input GIF files
for GIF_PATH in "$@"; do
# Check if the input file exists
if [ ! -f "$GIF_PATH" ]; then
echo "File not found: $GIF_PATH"
continue
fi
# Define output file name by replacing .gif with .mp4
MP4_PATH="${GIF_PATH%.gif}.mp4"
# Convert GIF to MP4 using ffmpeg with VP9 codec, high quality, no sound
ffmpeg -i "$GIF_PATH" -c:v libvpx-vp9 -quality good -b:v 0 -auto-alt-ref 4 -an "$MP4_PATH"
echo "Conversion completed: $MP4_PATH"
done
> ./convert-mp.sh *.MP.jpg
[##################################################] 100% (111/111) - PXL_20241230_174715482.MP.jpg | Total Saved: 478.25 MB
Processing complete: 111/111 files processed.
Total bytes saved: 478.25 MB
#!/bin/bash
# Vérifier si ImageMagick est installé
if ! command -v convert &> /dev/null; then
echo "ImageMagick n'est pas installé. Veuillez l'installer avant d'utiliser ce script."
exit 1
fi
# Vérifier si un pattern et une qualité ont été fournis en argument
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Usage: $0 'pattern_de_fichier' 'qualite' [max_dimension]"
echo "Exemple: ./script.sh 'DSC*.JPG' 85 4080"
exit 1
fi
# Récupération des paramètres
PATTERN=$1
QUALITY=$2
MAX_DIMENSION=${3:-4080} # Par défaut, max dimension = 4080 pixels
# Vérification que la qualité est un nombre entre 1 et 100
if ! [[ "$QUALITY" =~ ^[0-9]+$ ]] || [ "$QUALITY" -lt 1 ] || [ "$QUALITY" -gt 100 ]; then
echo "La qualité doit être un entier compris entre 1 et 100."
exit 1
fi
# Vérification que la dimension maximale est un entier positif
if ! [[ "$MAX_DIMENSION" =~ ^[0-9]+$ ]] || [ "$MAX_DIMENSION" -le 0 ]; then
echo "La dimension maximale doit être un entier positif."
exit 1
fi
total_saved_bytes=0
# Fonction pour formater les tailles en human-readable
format_size() {
local size=$1
if [ "$size" -lt 1024 ]; then
echo "${size} B"
elif [ "$size" -lt 1048576 ]; then
echo "$(echo "scale=2; $size / 1024" | bc)" kB
else
echo "$(echo "scale=2; $size / 1048576" | bc)" MB
fi
}
# Boucle sur chaque fichier correspondant au pattern
for file in $PATTERN; do
# Vérifier si le fichier existe
if [ ! -f "$file" ]; then
echo "Fichier introuvable : $file"
continue
fi
echo "Traitement de $file..."
# Taille initiale du fichier
initial_size=$(stat -c%s "$file")
# Obtenir les dimensions actuelles de l'image
dimensions=$(identify -format "%wx%h" "$file")
width=$(echo "$dimensions" | cut -d'x' -f1)
height=$(echo "$dimensions" | cut -d'x' -f2)
# Vérifier si l'image doit être redimensionnée
if [ "$width" -gt "$MAX_DIMENSION" ] || [ "$height" -gt "$MAX_DIMENSION" ]; then
# Calculer le facteur d'échelle
if [ "$width" -gt "$height" ]; then
scale_factor=$(echo "scale=10; $MAX_DIMENSION / $width" | bc -l)
else
scale_factor=$(echo "scale=10; $MAX_DIMENSION / $height" | bc -l)
fi
# Forcer LC_NUMERIC pour garantir un point comme séparateur décimal
LC_NUMERIC="C"
new_width=$(printf "%.0f" "$(echo "$width * $scale_factor" | bc -l)")
new_height=$(printf "%.0f" "$(echo "$height * $scale_factor" | bc -l)")
# Redimensionner l'image avec la qualité spécifiée en conservant les métadonnées
convert "$file" -resize "${new_width}x${new_height}" -quality "$QUALITY" "$file"
echo "Image redimensionnée à ${new_width}x${new_height} avec une qualité de ${QUALITY}%."
else
# Ajuster uniquement la qualité si l'image est déjà sous la limite
convert "$file" -quality "$QUALITY" "$file"
echo "L'image $file est déjà sous la limite de ${MAX_DIMENSION}px. Seule la qualité a été ajustée à ${QUALITY}%."
fi
# Taille finale du fichier
final_size=$(stat -c%s "$file")
# Calculer l'économie en octets
saved_bytes=$((initial_size - final_size))
total_saved_bytes=$((total_saved_bytes + saved_bytes))
# Afficher l'économie pour cette image
if [ "$saved_bytes" -gt 0 ]; then
echo "Économie pour $file : $(format_size $saved_bytes)"
else
echo "Aucune économie pour $file."
fi
done
# Afficher le total des économies
echo "Économie totale pour toutes les images : $(format_size $total_saved_bytes)"
echo "Traitement terminé."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment