Created
June 17, 2021 20:34
-
-
Save schauveau/c4519b341a23c6bad3c870b3761bc5d2 to your computer and use it in GitHub Desktop.
A bash script to play video URL on a remote Kodi server.
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 | |
# | |
# A small shell script that uses kodi-send and youtube-dl to play | |
# videos (or audio) URLs on a Kodi server. | |
# | |
# Examples: | |
# - send a Youtube page | |
# kodi-start-video.sh https://www.youtube.com/watch?v=Xwn8fQSW7-8 | |
# - send a DailyMotion page | |
# kodi-start-video.sh https://www.dailymotion.com/video/x7syshi | |
# - send a MP4 file | |
# kodi-start-video.sh https://sample-videos.com/video123/mp4/480/big_buck_bunny_480p_30mb.mp4 | |
# - send the URL in primary buffer | |
# kodi-start-video.sh primary | |
# - send the URL in clipboard buffer | |
# kodi-start-video.sh clipboard | |
# | |
# The script does not download the video. Youtube-dl is only used | |
# to extract the video stream URL from the web page. | |
# | |
# | |
# Dependencies: | |
# | |
# - kodi-send to send the commands to Kodi. | |
# - youtube-dl (https://youtube-dl.org/) to extract the URL of the video stream | |
# - wl-paste to read the selection (on Wayland). | |
# - xclip to read the selection (on X11). | |
# - Common shell utilities: grep, head, sed, ... | |
# | |
# On Debian: sudo apt install kodi-eventclients-kodi-send sed wl-clipboard | |
# | |
# TODO: | |
# - Append to current playlist. How? The "Cast Kodi" Firefox extension can do it. JSON? | |
# - Add all videos in a playlist. | |
# - Use the Json interface instead of kodi-send? (see https://kodi.wiki/view/JSON-RPC_API) | |
# | |
VERB=yes | |
YOUTUBE_DL="youtube-dl" | |
# For Youtube URL only: Set to "yes" if you have the Youtube add-on | |
# installed on Kodi and you want to use it instead of using youtube-to | |
# to extract the video stream url. | |
WITH_YOUTUBE_ADDON="yes" | |
# Youtube-dl rules to select the video quality. | |
# See also FORMAT SELECTION in youtube-dl man page | |
# Remark: Using bestvideo+bestaudio is not a good idea since that would produce | |
# 2 separate video and audio streams and we cannot mux them together. | |
H=720 # Maximum Video Height for my Raspberry Pi | |
FORMAT="best[height<=$H]/bestvideo[height<=$H]/bestaudio" | |
SERVER=kodi.schauveau.local | |
PORT=9777 | |
usage () { | |
APP=$(basename $0) | |
cat <<EOF | |
Usage: $APP [OPTION]... [ URL | clipboard | primary ] | |
Start playing a video URL on a Kodi server. | |
-k KODI Set the Kodi server (currently $SERVER) | |
-p PORT Set the Kodi port (currently $PORT) | |
-d Send the URL directly to Kodi (mostly for debugging) | |
If the special values "clipboard" and "primary" are used then the | |
URL is obtained from the 1st word of the clipboard or primary | |
selection. | |
EOF | |
exit 0 | |
} | |
read-primary () { | |
if [[ -n "$WAYLAND_DISPLAY" ]] ; then | |
wl-paste --primary --type text/plain | |
elif [[ -n "$DISPLAY" ]] ; then | |
# Not really tested | |
xclip -selection primary -o -t TEXT | |
else | |
echo "Sorry! Cannot read the primary selection" | |
fi | |
} | |
read-clipboard () { | |
if [[ -n "$WAYLAND_DISPLAY" ]] ; then | |
wl-paste --type text/plain | |
elif [[ -n "$DISPLAY" ]] ; then | |
# Not really tested | |
xclip -selection clipboard -o -t TEXT | |
else | |
echo "Sorry! Cannot read the clipboard" | |
fi | |
} | |
# | |
# Extract the first non-blank word from the input. | |
# | |
keep-first-word () { | |
grep -E '[[:alnum:]]' | head -n 1 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]].*//' | |
} | |
send-command () { | |
KODI=( kodi-send --host "$SERVER" --port "$PORT" ) | |
CMD=( "${KODI[@]}" --action="$1" ) | |
if [[ $VERB == "yes" ]] ; then | |
echo -n "#" ; printf " %q" "${CMD[@]}" ; echo | |
fi | |
"${CMD[@]}" | |
} | |
get-stream-from-url () { | |
"$YOUTUBE_DL" -f "$FORMAT" -g "$URL" | |
} | |
start-youtube () { | |
echo "Starting Youtube video $1" | |
send-command "PlayMedia(plugin://plugin.video.youtube/?action=play_video&videoid=$1)" | |
} | |
SRC=arg | |
DIRECT=no | |
while getopts ":dcpk:" option; do | |
case "${option}" in | |
k) SERVER="$OPTARG" ;; | |
p) PORT="$OPTARG" ;; | |
d) DIRECT=yes ;; | |
\?) usage ;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
case "$1" in | |
clipboard) | |
URL="$( read-clipboard | keep-first-word )" | |
echo "Using 1st word of clipboard as URL ($URL)" | |
;; | |
primary) | |
URL="$( read-primary | keep-first-word )" | |
echo "Using 1st word of clipboard as URL ($URL)" | |
;; | |
*) | |
URL="$1" | |
;; | |
esac | |
if [[ -z "$URL" ]] ; then | |
echo "Error: No URL found" | |
exit 1 | |
fi | |
if [[ "$DIRECT" == "no" ]] ; then | |
if [[ "$WITH_YOUTUBE_ADDON" == "yes" ]] ; then | |
YT_ID="[-a-zA-Z0-9_]{11}" # A Youtube ID is exactly 11 characters in a-z,A-Z,0-9,- and _ | |
if [[ "$URL" =~ ^https://www.youtube.com/watch\?(.*&)*v=($YT_ID) ]] ; then | |
# A long Youtube URL such as https://www.youtube.com/watch?v=DXUAyRRkI6k | |
start-youtube "${BASH_REMATCH[2]}" | |
exit 0 | |
elif [[ "$URL" =~ ^https://youtu.be/($YT_ID) ]] ; then | |
# A short Youtube URL such as https://youtu.be/DXUAyRRkI6k | |
start-youtube "${BASH_REMATCH[1]}" | |
exit 0 | |
fi | |
fi | |
if [[ "$URL" =~ ^https?://.*\.(mp3|m3u|mp4|ogg|mpeg|avi|webm)$ ]] ; then | |
# Recognize some common video or audio extensions. | |
DIRECT=yes | |
elif [[ "$URL" =~ ^https?:// ]] ; then | |
# For other URLs, obtain the video stream using youtube-dl | |
# That works ... most of the time. | |
STREAM=$(get-stream-from-url "$URL" | head -n 1) | |
if [[ -n "$STREAM" ]] ; then | |
send-command "PlayMedia($STREAM)" | |
else | |
echo "Error: Failed to extract a video stream from URL." | |
echo " Falling back to direct play..." | |
DIRECT=yes | |
fi | |
else | |
DIRECT=yes | |
fi | |
fi | |
if [[ "$DIRECT" = "yes" ]] ; then | |
send-command "PlayMedia($URL)" | |
fi | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment