Add frontend

Now if you visit the script without and query string, it’ll ask you for
a URL and then generate the HTML code for you.
This commit is contained in:
DJ Chase 2024-01-18 16:37:45 -05:00
parent a0ce31232f
commit c8f30dac49
4 changed files with 181 additions and 32 deletions

15
.page-end.html Normal file
View File

@ -0,0 +1,15 @@
<!-- begin `.page-end.html`. see `.page-start.html` for previous -->
</main>
<footer>
<p>VTT&nbsp;Embed is Open Source and self-hostable!
<a href="https://sr.ht/~u9000/vtt-embed">Check it out on
Sourcehut</a>.
</p>
<p>©&nbsp;DJ Chase, 2024. Licensed under the
<a href="https://spdx.org/licenses/AFL-3.0.html">Academic Free
License version 3.0 (AFL&nbsp;3.0)</a>.
</p>
</footer>
</body>
</html>

31
.page-start.html Normal file
View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>VTT Embed</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style.css">
</head>
<body>
<main>
<h1>VTT Embed</h1>
<p><strong>Add captions to embedded YouTube videos
(and others)</strong></p>
<hr/>
<p>Use this form to get the code to embed a video:</p>
<form accept-charset="utf-8" method="post">
<label for="url">Enter video/page URL:</label>
<br/>
<input type="url" name="url" id="url"
placeholder="https://www.youtube.com/watch?v=vv208qmcVeo">
<br/>
<input type="submit" value="Submit">
</form>
<!-- code gets inserted here by script on submit -->
<!-- end `.page-start.html`. see `.page-end.html` to next part -->

View File

@ -21,6 +21,12 @@ select the source video — and optionally the format — you want via URL
parameters. This makes it extremely easy to set up and allows you to use it in
many different ways.
**What follows is a more advanced description of how to use it. If you just go
to the scripts address (see the hosted instance link above) there is a nice UI
which will generate the embed code for you.** [Skip this section](#support)
---
There are two parameters you can use: `url` and `format`. `url` is the
percent-encoded URL of to the page with the video youd like to embed; it is the
only required parameter. `format` is the [youtube-dl][3] format youd like to
@ -107,6 +113,16 @@ be used to embed a videos audio only:
as a video on YouTube (no captions)</a>.</p>
```
## Support
The fastest way to get support would be to
[join the VTT Embed room on Matrix][5].
You can also [email me][6] if youd prefer, but it will definately be slower.
[5]: matrix:r/vtt-embed:riot.firechicken.net?action=join
[6]: mailto:u9000@posteo.mx
## Copyright
VTT Embed is designed not to get you a DMCA request as long as you are allowed
@ -116,9 +132,9 @@ elses video you of course assume responsibility.
VTT Embed does not host, stream, or copy videos. Instead, it merely locates the
direct link on the provided page and redirects clients to it. Its similar to
[Invidious][5], except even more hands-off. Using it to embed a video is
[Invidious][7], except even more hands-off. Using it to embed a video is
therefore as safe or safer than embedding a video from Invidious. It should also
be as safe as embedding a video directly from YouTube, as long as you are
allowed to embed the video from YouTube in the first place.
[5]: https://invidious.io/
[7]: https://invidious.io/

View File

@ -3,8 +3,18 @@
# © DJ Chase, 2024. Licensed under the Academic Free License version 3.0.
readonly HTTP_FOUND='302 Found'
readonly HTTP_NOT_FOUND='404 Not 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() \
{
@ -14,6 +24,19 @@ percentDecode() \
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>]
@ -23,6 +46,9 @@ error() \
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'
@ -33,37 +59,98 @@ error() \
}
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 ]
if [ "$REQUEST_METHOD" = 'GET' ] || [ "$REQUEST_METHOD" = 'HEAD' ]
then
printf 'Status: %s\n' "$HTTP_FOUND"
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
)"
# `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
[ "$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
error "$HTTP_NOT_FOUND" "$ytdlOutput"
printf 'Status: %s\n' "$HTTP_METHOD_NOT_ALLOWED"
printf 'Allow: GET, POST, HEAD\n\n'
fi