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:
parent
a0ce31232f
commit
c8f30dac49
|
@ -0,0 +1,15 @@
|
|||
<!-- begin `.page-end.html`. see `.page-start.html` for previous -->
|
||||
|
||||
</main>
|
||||
<footer>
|
||||
<p>VTT Embed is Open Source and self-hostable!
|
||||
<a href="https://sr.ht/~u9000/vtt-embed">Check it out on
|
||||
Sourcehut</a>.
|
||||
</p>
|
||||
<p>© DJ Chase, 2024. Licensed under the
|
||||
<a href="https://spdx.org/licenses/AFL-3.0.html">Academic Free
|
||||
License version 3.0 (AFL 3.0)</a>.
|
||||
</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
|
@ -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 -->
|
20
README.md
20
README.md
|
@ -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 script’s 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 you’d like to embed; it is the
|
||||
only required parameter. `format` is the [youtube-dl][3] format you’d like to
|
||||
|
@ -107,6 +113,16 @@ be used to embed a video’s 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 you’d 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 @@ else’s 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. It’s 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/
|
||||
|
|
147
vtt-embed.sh
147
vtt-embed.sh
|
@ -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_&_&\;_g;
|
||||
s_'_'\;_g;
|
||||
s_\"_"\;_g;
|
||||
s_<_<\;_g;
|
||||
s_>_>\;_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><video controls>
|
||||
<source media="(prefers-reduced-data: reduce)" src="$scriptURL?format=worst&url=$url">
|
||||
<source src="$scriptURL?url=$url">
|
||||
<track src="https://example.com/captions.vtt" kind="captions" srclang="en" label="English">
|
||||
<p>It looks like your browser doesn’t support HTML video. You can still
|
||||
<a href="$scriptURL?url=$url">download
|
||||
the video</a> and watch it locally. You can also
|
||||
<a href="https://example.com/captions.vtt">download the captions
|
||||
file</a> if your video player can import it.
|
||||
</p>
|
||||
</video></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 you’d 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
|
||||
|
|
Loading…
Reference in New Issue