D.O.A.
Well-known member
I have over 98,000 videos uploaded into threads/posts so I wanted to see if I can make any savings with ffmpeg, long story short, yes. I compressed 70,000 odd videos (mp4) and saved 154GB, for a 18% reduction of the total of 853GB. No loss in quality. So I'll leave it here. Probaly wouldn't hurt to chmod 600 the log file if you do it in /video.
Set your video path and run the bash script. Run it every now and then.
Set your video path and run the bash script. Run it every now and then.
- will create a temp video file.
- if temp video file is smaller, replace original video.
- if bigger, delete temp video file.
- log result/check log on next run and skip processed files.
Code:
#!/bin/bash
# Set the parent directory
PARENT_DIR="/path/to/data/video" # Change this to your actual parent directory
# Log file to track conversions
LOG_FILE="conversion.log"
# ffmpeg settings
FFMPEG_CMD="ffmpeg -i"
# Conversion options
VIDEO_CODEC="-c:v libx264 -preset slow -crf 23"
AUDIO_CODEC="-c:a aac -b:a 128k"
MOV_FLAGS="-movflags +faststart"
# Check if the log file exists, if not, create it
if [[ ! -f "$LOG_FILE" ]]; then
touch "$LOG_FILE"
fi
# Function to log conversion results
log_conversion() {
echo "$1" >> "$LOG_FILE"
}
# Flag to track if any conversions are done
conversion_done=false
# Find all MP4 files in the parent directory and subdirectories
find "$PARENT_DIR" -type f -name "*.mp4" | while read -r input_file; do
# Check if the file was successfully converted or failed previously
if grep -q "^$input_file: SUCCESS" "$LOG_FILE" || grep -q "^$input_file: FAILED" "$LOG_FILE"; then
continue
fi
# Create a temporary output file
temp_file="${input_file}.temp.mp4"
# Run the ffmpeg compression command
$FFMPEG_CMD "$input_file" $VIDEO_CODEC $AUDIO_CODEC $MOV_FLAGS "$temp_file" < /dev/null
# Check if ffmpeg succeeded
if [[ $? -eq 0 ]]; then
# Compare the sizes of the original and the compressed file
original_size=$(stat -c %s "$input_file")
new_size=$(stat -c %s "$temp_file")
# If the new file is smaller, replace the original
if (( new_size < original_size )); then
mv "$temp_file" "$input_file"
log_conversion "$input_file: SUCCESS"
conversion_done=true
else
# Delete the temporary file if it's not smaller
rm "$temp_file"
log_conversion "$input_file: FAILED (Larger or same size)"
fi
else
# Log failure if ffmpeg failed
rm -f "$temp_file"
log_conversion "$input_file: FAILED (ffmpeg error)"
fi
done
# If no conversions were done, print a message and exit
if [[ "$conversion_done" == false ]]; then
echo "No files to convert. Exiting."
exit 0
else
echo "Conversion completed. Check the log file for details."
fi