Last active
January 25, 2025 17:26
-
-
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 …
This file contains hidden or 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/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)" |
This file contains hidden or 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/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" |
This file contains hidden or 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/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 |
This file contains hidden or 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
> ./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 |
This file contains hidden or 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/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