Skip to content

Instantly share code, notes, and snippets.

@StefanHamminga
Last active November 18, 2020 06:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save StefanHamminga/1d78baa1bc87f2d7383c4027c2b90ec8 to your computer and use it in GitHub Desktop.
Save StefanHamminga/1d78baa1bc87f2d7383c4027c2b90ec8 to your computer and use it in GitHub Desktop.
piplay - Raspberry Pi Omxplayer wrapper script with support for wildcards, streaming (YouTube, etc) and skipping of played files.
#!/bin/bash
# piplay - Raspberry Pi Omxplayer wrapper script.
# Required packages on Debian: omxplayer youtube-dl attr
# TODO / future plans: Use the D-Bus interface to store media playback position and resume from there.
REQUIREMENTS=(omxplayer youtube-dl find sort getfattr setfattr nice ionice)
# Subtitle languages, in order of preferences. Format: movie.mkv & movie.en.srt => en
SUBTITLELANGUAGES=( nl nld dut en eng )
usage() {
echo -e "
\e[1mpiplay\e[0m Wrapper script for the Raspberry Pi Omxplayer.
Plays most things you throw at it. Wildcard support using find, http(s)
playback using youtube-dl. Marks fully played files with the extended user
attribute 'user.piplay'='played'. This allows using wildcards to play a bunch
of files, yet skipping already played files. Shuffle is also supported.
Sets ionice to class 2 (best-effort) and priority 0 (highest). Sets nice value
to -4 (if allowed, see limits.conf).
Usage:
\e[1mpiplay\e[0m [options] file|url|wildcard file2 ...
-u, --unwatched List all unwatched files in current directory and exit.
-r, --replay Replay media files, clearing played attributes.
-s, --shuffle Randomize playback order for anything after the option.
-w, --watched Don't play, just mark as watched.
-c, --clear Clear playing and watched flags from input and exit.
-d, --debug Don't execute, just echo each command.
file File, wildcard, url to play. Add as many as you want,
in any order you want. Go nuts.
"
exit $1
}
YTGFORMAT="best[vcodec!=vp9][height<=?1080]"
NICE="-n -4"
IONICE="-c 2 -n 0"
OMXOPTS="-b -o hdmi"
OMX="nice $NICE ionice $IONICE omxplayer $OMXOPTS"
DEBUG=""
# Test if all required commands are present, if not, show the user what to install
for REQ in "${REQUIREMENTS[@]}"; do
command -v $REQ >/dev/null || { echo -e "piplay: Error, please install a package for command \e[91m$REQ\e[0m"; exit 1; }
done
if [ "$1" = "" ]; then
usage 0
fi
shopt -s nocasematch
action() {
ACTION=$1
shift
echo -e "$ACTION \e[92m$*\e[0m"
# echo -n -e "\033]2;$* | piplay\007"
echo -n -e "\033]30;$* | piplay\007"
}
# Disable this and CTRL-C will only break playback of the current item, instead of overall.
trap "echo -e '\e[91mUser requested exit\e[0m'; exit 1" SIGINT SIGTERM
# Store arguments in an array, for shuffle support
OPTS=( "$@" )
shuffle() {
local i tmp size max rand
size=${#OPTS[*]}
max=$(( 32768 / size * size ))
for ((i=size-1; i>0; i--)); do
while (( (rand=$RANDOM) >= max )); do :; done
rand=$(( rand % (i+1) ))
tmp=${OPTS[i]} OPTS[i]=${OPTS[rand]} OPTS[rand]=$tmp
done
}
find_sub() {
FILENAME=${1%.*}
for SUBLANG in "${SUBTITLELANGUAGES[@]}"; do
if [ -f "$FILENAME.$SUBLANG.srt" ]; then
export SUB_FILE="$FILENAME.$SUBLANG.srt"
return
fi
done
if [ -f "$FILENAME.srt" ]; then
export SUB_FILE="$FILENAME.srt"
return
fi
unset SUB_FILE
}
while true; do
OPT=${OPTS[0]}
if [ "$OPT" = "" ]; then
action Finished
exit 0
fi
OPTS=( "${OPTS[@]:1}" )
if [ "$OPT" = "-u" ] || [ "$OPT" = "--unwatched" ]; then
find ./ \
-regextype sed \
-regex '.*\.*\(aac\|ac3\|avi\|cda\|flac\|m4a\|m4v\|mkv\|mp3\|mp4\|ogg\|ogm\|ogv\|wav\|wmv\)$' \
-exec sh -c "getfattr --only-values -n user.piplay \"{}\" 2>/dev/null | grep -q played || echo \"{}\" | sed -r s,^\.\/,," \; | sort
# -exec sh -c "getfattr --only-values -n user.piplay \"{}\" 2>/dev/null | grep -q played || ls --color \"{}\"" \; | sort
exit 0
elif [ "$OPT" = "-d" ] || [ "$OPT" = "--debug" ]; then
DEBUG="echo"
elif [ "$OPT" = "-r" ] || [ "$OPT" = "--replay" ]; then
REPLAY="true"
elif [ "$OPT" = "-s" ] || [ "$OPT" = "--shuffle" ]; then
SHUFFLE="-R"
shuffle
elif [ "$OPT" = "-w" ] || [ "$OPT" = "--watched" ]; then
JUSTMARK="true"
elif [ "$OPT" = "-c" ] || [ "$OPT" = "--clear" ]; then
JUSTCLEAR="true"
elif [[ $OPT =~ ^https?:// ]]; then
action Playing $OPT
$DEBUG $OMX `youtube-dl -g -f $YTGFORMAT "$OPT"`
elif [[ $OPT =~ ^rt(mp|sp):// ]]; then
action Playing $OPT
$DEBUG $OMX "$OPT"
else
while read -u 3 file; do
if [ "$JUSTCLEAR" = "true" ]; then
$DEBUG setfattr -x user.piplay "${file}" && \
action "Cleared piplay status for:" $file
elif [ "$JUSTMARK" = "true" ]; then
$DEBUG setfattr -n user.piplay -v "played" "${file}" && \
action "Marked as played:" $file
elif [ "$REPLAY" = "true" ]; then
$DEBUG setfattr -x user.piplay "${file}"
action Playing $file
find_sub "${file}"
$DEBUG setfattr -n user.piplay -v "playing" "${file}"
if [ "${SUB_FILE}" != "" ]; then
$DEBUG $OMX --subtitle "${SUB_FILE}" "${file}" && \
$DEBUG setfattr -n user.piplay -v "played" "${file}" && \
action "Marked as played:" $file
else
$DEBUG $OMX "${file}" && \
$DEBUG setfattr -n user.piplay -v "played" "${file}" && \
action "Marked as played:" $file
fi
elif [[ `getfattr --only-values -n user.piplay "${file}" 2>/dev/null` != "played" ]]; then
action Playing $file
find_sub "${file}"
$DEBUG setfattr -n user.piplay -v "playing" "${file}"
if [ "${SUB_FILE}" != "" ]; then
$DEBUG $OMX --subtitle "${SUB_FILE}" "${file}" && \
$DEBUG setfattr -n user.piplay -v "played" "${file}" && \
action "Marked as played:" $file
else
$DEBUG $OMX "${file}" && \
$DEBUG setfattr -n user.piplay -v "played" "${file}" && \
action "Marked as played:" $file
fi
else
echo -e "Alread played \e[91m${file}\e[0m"
fi
# Clean out pending keyboard commands:
read -t 0.05 -n 10000 discard || true
done 3<<< `find -L "$OPT" -type f | sort -f $SHUFFLE`
fi
# Clean out pending keyboard commands:
read -t 0.05 -n 10000 discard || true
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment