Last active
August 29, 2015 14:09
-
-
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.
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 | |
#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" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This script only requires a moderately new version of FFMPEG and dcraw.