vtt-embed/vtt-embed.sh

157 lines
3.7 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# © DJ Chase, 2024. Licensed under the Academic Free License version 3.0.
readonly HTTP_FOUND='302 Found'
readonly HTTP_BAD_REQUEST='400 Bad Request'
readonly HTTP_NOT_FOUND='404 Not Found'
readonly HTTP_METHOD_NOT_ALLOWED='405 Method Not Allowed'
# SC2155 is about munging return codes, which is fine here
# shellcheck disable=SC2155
readonly HTML_PAGE_START="$(
dirname "${DOCUMENT_ROOT}${SCRIPT_NAME}"
)/.page-start.html"
# shellcheck disable=SC2155
readonly HTML_PAGE_END="$(
dirname "${DOCUMENT_ROOT}${SCRIPT_NAME}"
)/.page-end.html"
percentDecode() \
{
# usage: foo | percentDecode
# shellcheck disable=SC2059
printf "$(sed 's/+/ /g; s/%/\\x/g' | tr -d '\r')"
}
htmlEncode() \
{
# usage: foo | htmlEncode
sed "
s_&_&amp\;_g;
s_'_&#39\;_g;
s_\"_&quot\;_g;
s_<_&lt\;_g;
s_>_&gt\;_g
"
}
error() \
{
# usage: error <status_code> [<message>]
printf 'Status: %s\n' "$1"
if [ "$2" ]
then
printf 'Content-type: text/plain; charset=utf-8\n\n'
[ "$REQUEST_METHOD" = 'HEAD' ] && exit 0
printf '%s\n\n' "$1" "$2"
else
printf '\n'
fi
# exit 0 so that the webserver doesn't return "Internal Server Error"
exit 0
}
if [ "$REQUEST_METHOD" = 'GET' ] || [ "$REQUEST_METHOD" = 'HEAD' ]
then
if [ "$QUERY_STRING" ]
then
format="$(
printf '%s\n' "$QUERY_STRING" \
| sed 's/&/\n/g' \
| grep '^format=' \
| cut -d = -f 2- \
| percentDecode
)"
: "${format:=best}"
pageURL="$(
printf '%s\n' "$QUERY_STRING" \
| sed 's/&/\n/g' \
| grep '^url=' \
| cut -d = -f 2- \
| percentDecode
)"
[ "$pageURL" ] \
|| error "$HTTP_BAD_REQUEST" \
'You need to include the `url` parameter'
ytdlOutput="$(
youtube-dl --format "$format" --get-url -- "$pageURL" \
2>&1
)"
# shellcheck disable=SC2181
if [ "$?" -eq 0 ]
then
printf 'Status: %s\n' "$HTTP_FOUND"
# `head -n 1` in case someone sets a format of
# 'bestaudio+bestvideo' or similar, since we can only
# redirect to one URL at a time
printf 'Location: %s\n\n' "$(
printf '%s\n' "$ytdlOutput" \
| sed '/^$/d' \
| head -n 1
)"
else
error "$HTTP_NOT_FOUND" "$ytdlOutput"
fi
else
printf 'Content-Type: text/html; charset=utf-8\n\n'
[ "$REQUEST_METHOD" = 'HEAD' ] && exit 0
cat "$HTML_PAGE_START" "$HTML_PAGE_END"
fi
elif [ "$REQUEST_METHOD" = 'POST' ]
then
postBody="$(tr -d '\r' | sed 's/&/\n/g')"
url="$(
# field is already percent encoded
printf '%s' "$postBody" \
| grep '^url=' \
| cut -d = -f 2- \
| htmlEncode
)"
scriptURL="$(
printf 'https://%s%s' "$SERVER_NAME" "$SCRIPT_NAME" \
| htmlEncode
)"
printf 'Content-Type: text/html; charset=utf-8\n\n'
cat "$HTML_PAGE_START" - "$HTML_PAGE_END" <<EOF
<hr/>
<p>Use this code to embed the video:</p>
<pre><code>&lt;video controls&gt;
&lt;source media="(prefers-reduced-data: reduce)" src="$scriptURL?format=worst&amp;url=$url"&gt;
&lt;source src="$scriptURL?url=$url"&gt;
&lt;track src="https://example.com/captions.vtt" kind="captions" srclang="en" label="English"&gt;
&lt;p&gt;It looks like your browser doesnt support HTML video. You can still
&lt;a href="$scriptURL?url=$url"&gt;download
the video&lt;/a&gt; and watch it locally. You can also
&lt;a href="https://example.com/captions.vtt"&gt;download the captions
file&lt;/a&gt; if your video player can import it.
&lt;/p&gt;
&lt;/video&gt;</code></pre>
<p>Remember to replace <code>https://example.com/captions.vtt</code> with the
link to your captions file (WebVTT). See
<a href="https://dj-chase.com/unlisted/vtt-embed-example-cc.vtt">the demo
caption file</a> if youd like an example of what that looks like.</p>
EOF
else
printf 'Status: %s\n' "$HTTP_METHOD_NOT_ALLOWED"
printf 'Allow: GET, POST, HEAD\n\n'
fi