Skip to content

Instantly share code, notes, and snippets.

@KarstenB
Last active August 29, 2015 14:09
Show Gist options
  • Save KarstenB/aecf2b4d0685a15ec370 to your computer and use it in GitHub Desktop.
Save KarstenB/aecf2b4d0685a15ec370 to your computer and use it in GitHub Desktop.
This script converts a directory full of videos, images or audio into smaller versions that can be synced into the cloud without occupying terabytes of space.
#!/bin/bash
#Change this to the full directory path that contains the source media
SOURCE_MEDIA_DIR="/Video_Library_nas"
#Change this directory to the full directory path that will contain the proxy media
#As those files are rather small, this could be a cloud directory
PROXY_MEDIA_DIR="/Video_Library_proxy"
#Images will be resized to be of at most this width
IMG_WIDTH=1024
#Videos will be resized to be at most this wide
VIDEO_WIDTH=450
#When a source directory contains a failed named like this, it will not be
#proxied. This could be useful for editing projects or alike
NO_PROXY_FILE=".noProxyDir"
#FFMPEG Options that will always be used
FFMPEG_COMMON_OPT="-loglevel error -y -nostdin -hide_banner"
#If a file could not be converted, the failed command line will be logged to this
LOG_FILE="$PROXY_MEDIA_DIR/proxyFailedFilesLog.txt"
#Camera raw files are temporarily converted to this file before resizing by ffmpeg
RAW_TMP_FILE="/tmp/dcraw.ppm"
cd "$SOURCE_MEDIA_DIR"
date > "$LOG_FILE"
#White space safe way of listing files from http://mywiki.wooledge.org/BashFAQ/020
while IFS= read -r -d $'\0' SOURCE_FILE; do
TARGET_FILE="$PROXY_MEDIA_DIR/$SOURCE_FILE"
#check whether the proxy already exists and skip if so
if [[ -e "$TARGET_FILE" ]]
then
echo "Skipping existing file $SOURCE_FILE"
continue
fi
#Create directory structure if non-existant
TARGET_FILE_DIR=`dirname "$TARGET_FILE"`
if [[ ! -e "$TARGET_FILE_DIR" ]]
then
echo "Creating directory $TARGET_FILE_DIR"
mkdir -p "$TARGET_FILE_DIR"
fi
#Check for nonProxyDir marker files in all parent directories of the source file
SOURCE_FILE_DIR=`dirname "$SOURCE_FILE"`
path="$SOURCE_MEDIA_DIR/$SOURCE_FILE_DIR"
while [[ -n "$path" && "$path" != "." && ! -e "$path/$NO_PROXY_FILE" ]]; do
path="${path%/*}"
done
if [[ -n "$path" && "$path" != "." ]]
then
echo "Skipping file $TARGET_FILE in no proxy directory $path"
continue
fi
#Check what kind of file we have here
FILE_TYPE=`file --mime-type -b "$SOURCE_FILE"`
#Apparently it is an image
if [[ $FILE_TYPE =~ ^image.* ]]
then
#Some cameras write THM files for showing information on the camera display
#Those files are usually not very interesting
if [[ "$SOURCE_FILE" == *.THM ]]
then
echo "Skipping video thumbnail $SOURCE_FILE"
continue
fi
#Check whether the image is decodable by dcraw
if dcraw -i "$SOURCE_FILE" > /dev/null
then
if [[ -e "$TARGET_FILE.jpg" ]]
then
echo "Skipping existing raw file $SOURCE_FILE because $TARGET_FILE.jpg exists"
continue
fi
#Create a ppm file that can be understood by ffmpeg
echo "Converting raw image file $SOURCE_FILE"
if ! dcraw -w -c "$SOURCE_FILE" > "$RAW_TMP_FILE"
then
echo "Raw image conversion failed of $SOURCE_FILE"
echo "dcraw -w -c $SOURCE_FILE > $RAW_TMP_FILE" >> "$LOG_FILE"
continue
fi
SOURCE_FILE="$RAW_TMP_FILE"
TARGET_FILE="$TARGET_FILE.jpg"
fi #is a raw image
#Create the proxy image
echo "Resizing image $SOURCE_FILE"
if ! ffmpeg $FFMPEG_COMMON_OPT -i "$SOURCE_FILE" -vf scale=$IMG_WIDTH:-2 "$TARGET_FILE"
then
echo "FFMPEG Failed for image $SOURCE_FILE"
echo "ffmpeg $FFMPEG_COMMON_OPT -i $SOURCE_FILE -vf scale=$IMG_WIDTH:-2 $TARGET_FILE" >> "$LOG_FILE"
rm -f "$TARGET_FILE"
fi
else #not an image
#If it is not an image, maybe it is a video?
if [[ $FILE_TYPE =~ ^video.* ]]
then
echo "Resizing video $SOURCE_FILE"
#Remove the option -an to have audio in the proxy media
if ! ffmpeg $FFMPEG_COMMON_OPT -i "$SOURCE_FILE" -an -vf scale=$VIDEO_WIDTH:-2 "$TARGET_FILE"
then
echo "FFMPEG Failed for video $SOURCE_FILE"
echo "ffmpeg $FFMPEG_COMMON_OPT -i $SOURCE_FILE -an -vf scale=$VIDEO_WIDTH:-2 $TARGET_FILE" >> "$LOG_FILE"
rm -f "$TARGET_FILE"
fi
else # not an image or video
#If it is not an image or video, maybe it is audio
if [[ $FILE_TYPE =~ ^audio.* ]]
then
NEW_BASE_FILE="$TARGET_FILE.m4a"
if [[ -e "$NEW_BASE_FILE" ]]
then
echo "Skipping audio conversion for wave file $SOURCE_FILE because $NEW_BASE_FILE exists"
continue
fi
echo "Converting audio $SOURCE_FILE"
if ! ffmpeg $FFMPEG_COMMON_OPT -i "$SOURCE_FILE" -c:a libfaac -q:a 3 "$NEW_BASE_FILE"
then
echo "FFMPEG failed for wave file $SOURCE_FILE"
echo "ffmpeg $FFMPEG_COMMON_OPT -i $SOURCE_FILE -c:a libfaac -q:a 3 $NEW_BASE_FILE" >> "$LOG_FILE"
rm -f "$NEW_BASE_FILE"
fi
else # not an image, video or audio
echo "Copying file $SOURCE_FILE"
cp "$SOURCE_FILE" "$TARGET_FILE"
fi
fi
fi
done < <(find . -type f -print0)
echo "Processing done"
date >> "$LOG_FILE"
rm -f "$RAW_TMP_FILE"
@KarstenB
Copy link
Author

This script only requires a moderately new version of FFMPEG and dcraw.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment