Last active
August 29, 2015 14:11
-
-
Save doersino/ade1edd8fe154ea30ba4 to your computer and use it in GitHub Desktop.
Downloads a webcam image, overlays the date/time, and compress past images into ZIP and MP4 format.
This file contains 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 | |
# http://www.reddit.com/r/spacex/comments/2pwjni/live_video_of_asds_in_port/cn19n2i?context=7 | |
# https://gist.github.com/doersino/ade1edd8fe154ea30ba4 | |
# | |
# This script downloads a webcam image to a date/hour-labeled directory, | |
# creating intermediate directories as required, making sure that the image is | |
# not corrupt, and optionally overlaying the current date and time on the image | |
# and maintaining a mirror of the webcam. Any images from the previous day will | |
# optionally be ZIP-compressed and compiled into a MP4 video after the first | |
# download of each day. | |
# | |
# The output is quite verbose for debugging purposes, so you may want to discard | |
# it by appending >/dev/null 2>&1 to the call. | |
# | |
# Run this script either | |
# * manually whenever you want to download the current webcam image, | |
# * in a bash loop (e.g. while sleep 30; do bash webcam_dl.sh; done), | |
# * or, especially for long-term monitoring, with cron (keep in mind that cron | |
# can only run a command once per minute or less frequently) or runwhen. | |
# | |
# Tested on Mac OS X and CentOS. | |
# | |
# Dependencies: | |
# * Required: curl, grep, zip | |
# * Optional: jpeginfo, imagemagick (identify, mogrify), ghostscript, ffmpeg | |
# * if found, jpeginfo will be used to detect corrupt images if FILE_EXT is | |
# either "jpg" or "jpeg", otherwise identify will be used | |
# * if neither jpeginfo nor identify can be found, corrupt images won't be | |
# detected and removed | |
# * if mogrify can't be found or isn't configured to work with ghostscript, | |
# images won't be annotated with the current date and time | |
# * if ffmpeg can't be found, no video will be created | |
# | |
# In case you're considering using this to spy on somebody: please don't. | |
# BEGIN CONFIG ----------------------------------------------------------------- | |
WEBCAM_URL="http://www.centennialbulb.org/ctbulb.jpg" | |
APPEND_TIMESTAMP=1 # try to fool potential server-side caching? (1: determine | |
# whether to use ? or & as delimiter automatically, 0: don't | |
# append timestamp, string: use the value assigned to this | |
# variable as delimiter) | |
CURL_FLAGS="" # useful if the webcam requires a particular --referer | |
BASE_DIR="$HOME" # no trailing slash! | |
#FILENAME=$(date +%Y-%m-%dT%H:%M:%SZ) # ISO 8601 | |
FILENAME=$(date +%s) # UNIX timestamp | |
FILE_EXT="jpg" # whatever image format the webcam outputs | |
JPEGINFO_PATH=$(which jpeginfo) # path of jpeginfo executable | |
IDENTIFY_PATH=$(which identify) # path of imagemagick's identify executable | |
OVERLAY_TIME=1 # overlay the current date and time on each webcam image? | |
MOGRIFY_PATH=$(which mogrify) # path of imagemagick's mogrify executable | |
COPY_TO_BASE_DIR=1 # copy the latest webcam image to BASE_DIR/latest.FILE_EXT, | |
# essentially creating a mirror of the webcam? | |
COMPRESS=1 # create daily ZIP archive and MP4 video of yesterday's images? | |
FFMPEG_PATH=$(which ffmpeg) # path of ffmpeg executable | |
VIDEO_FPS=24 # framerate of the generated video | |
# END CONFIG ------------------------------------------------------------------- | |
function echo_debug { | |
echo -e "\033[1;34m$1\033[0m" # bold/blue | |
} | |
function download_image { | |
URL="$WEBCAM_URL" | |
if [ "$APPEND_TIMESTAMP" = "1" ]; then | |
if grep -q '?' <<< "$URL"; then # determine if we need to prepend ? or & | |
URL="$URL"'&' | |
else | |
URL="$URL"'?' | |
fi | |
URL="$URL$(date +%s)" | |
elif [ "$APPEND_TIMESTAMP" != "0" ]; then | |
URL="$URL$APPEND_TIMESTAMP$(date +%s)" | |
fi | |
echo_debug "Downloading $URL to $FILE..." | |
curl $CURL_FLAGS "$URL" > "$FILE" | |
} | |
DAY=$(date -u +"%Y-%m-%d") | |
HOUR=$(date -u +"%H") | |
# create directory BASE_DIR/YYYY-MM-DD/HH if not exists | |
if [ ! -d "$BASE_DIR/$DAY/$HOUR" ]; then | |
echo_debug "Creating directory $BASE_DIR/$DAY/$HOUR..." | |
mkdir -p "$BASE_DIR/$DAY/$HOUR" | |
fi | |
# download image | |
FILE="$BASE_DIR/$DAY/$HOUR/$FILENAME.$FILE_EXT" | |
download_image | |
# check if the downloaded image is corrupt using either jpeginfo or identify and | |
# retry if neccessary - if the second try isn't successful either, remove the | |
# image in order to not upset ffmpeg later on | |
if [ -e "$JPEGINFO_PATH" ] && { [ "$FILE_EXT" = "jpg" ] || [ "$FILE_EXT" = "jpeg" ]; }; then | |
if ! "$JPEGINFO_PATH" -c "$FILE" >/dev/null 2>&1; then | |
echo_debug "Downloaded image is likely corrupt (jpeginfo). Sleeping 2s and retrying..." | |
sleep 2 | |
download_image | |
fi | |
if ! "$JPEGINFO_PATH" -c "$FILE" >/dev/null 2>&1; then | |
echo_debug "Downloaded image is likely corrupt (jpeginfo). Removing corrupt image..." | |
rm "$FILE" | |
fi | |
elif [ -e "$IDENTIFY_PATH" ]; then | |
if [ $("$IDENTIFY_PATH" -verbose "$FILE" 2>&1 >/dev/null | wc -l) -ge 1 ]; then | |
echo_debug "Downloaded image is likely corrupt (identify). Sleeping 2s and retrying..." | |
sleep 2 | |
download_image | |
fi | |
if [ $("$IDENTIFY_PATH" -verbose "$FILE" 2>&1 >/dev/null | wc -l) -ge 1 ]; then | |
echo_debug "Downloaded image is likely corrupt (identify). Removing corrupt image..." | |
rm "$FILE" | |
fi | |
fi | |
# if the image is empty, remove it in order to not upset ffmpeg later on | |
if [ -e "$FILE" ] && [ "$(du -k "$FILE" | cut -f1)" -eq 0 ]; then | |
echo_debug "Downloaded image is empty. Removing empty image..." | |
rm "$FILE" | |
fi | |
# overlay the current date and time on the image | |
if [ "$OVERLAY_TIME" -eq 1 ] && [ -e "$MOGRIFY_PATH" ] && [ -e "$FILE" ]; then | |
echo_debug "Overlaying the current date and time on downloaded image..." | |
"$MOGRIFY_PATH" -fill black -draw "rectangle 0,0 223,15" -fill white -gravity NorthWest -font Courier -pointsize 15 -annotate +8+2 "$(date -u +'%Y-%m-%d %H:%M:%S') UTC" "$FILE" | |
fi | |
# create a mirror of the webcam | |
if [ "$COPY_TO_BASE_DIR" -eq 1 ] && [ -e "$FILE" ]; then | |
echo_debug "Copying the downloaded image to $BASE_DIR/latest.$FILE_EXT" | |
\cp "$FILE" "$BASE_DIR/latest.$FILE_EXT" | |
fi | |
# create ZIP archive and MP4 video of yesterday's images if there are any (and | |
# the ZIP archive doesn't already exist) | |
if [ "$COMPRESS" -eq 1 ]; then | |
if [ "$(uname)" = "Darwin" ]; then | |
YESTERDAY=$(date -j -v-1d -f "%Y-%m-%d" $DAY "+%Y-%m-%d") # Mac OS X | |
else | |
YESTERDAY=$(date -u +"%Y-%m-%d" -d "yesterday") # most Linux distributions | |
fi | |
if [ ! -e "$BASE_DIR/$YESTERDAY.zip" ] && [ -d "$BASE_DIR/$YESTERDAY" ]; then | |
echo_debug "Creating ZIP archive of yesterday's images: $BASE_DIR/$YESTERDAY.zip..." | |
cd "$BASE_DIR" | |
\zip "$YESTERDAY.zip" "$YESTERDAY" # "touch" the ZIP archive | |
zip -rv "$YESTERDAY.zip" "$YESTERDAY" | |
# TODO this works, but it could *really* use some refactoring | |
if [ -e "$FFMPEG_PATH" ]; then | |
echo_debug "Creating $VIDEO_FPS fps video of yesterday's images: $BASE_DIR/$YESTERDAY.mp4..." | |
mkdir -p "$BASE_DIR/$YESTERDAY/temp" | |
find "$BASE_DIR/$YESTERDAY" -name "*.$FILE_EXT" | sort | awk -v q="\"" 'BEGIN{ a=1 }{ printf "cp "q"%s"q" "q"'"$BASE_DIR/$YESTERDAY/temp/"'%05d'".$FILE_EXT"'"q"\n", $0, a++ }' | bash | |
"$FFMPEG_PATH" -framerate "$VIDEO_FPS" -i "$BASE_DIR/$YESTERDAY/temp/"%05d.jpg -c:v libx264 -r "$VIDEO_FPS" -pix_fmt yuv420p "$BASE_DIR/$YESTERDAY.mp4" | |
rm -r "$BASE_DIR/$YESTERDAY/temp" | |
fi | |
echo_debug "Removing directory with yesterday's images..." | |
rm -r "$BASE_DIR/$YESTERDAY" | |
fi | |
fi | |
echo_debug "Finished!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment