Compare commits
2 Commits
c791be328e
...
85122ba2e9
Author | SHA1 | Date | |
---|---|---|---|
85122ba2e9 | |||
6e363f0787 |
@ -11,6 +11,10 @@ The server will search YouTube for `<query>`, pick the first result, pick the be
|
||||
|
||||
Example: [`https://u2b.cx/nyan cat`](https://u2b.cx/nyan%20cat) will give you the raw mp4 file for [https://www.youtube.com/watch?v=QH2-TGUlwu4](https://www.youtube.com/watch?v=QH2-TGUlwu4), the first result on [https://www.youtube.com/results?search_query=nyan+cat](https://www.youtube.com/results?search_query=nyan+cat).
|
||||
|
||||
### GET `https://u2b.cx/id/<video id>`
|
||||
|
||||
Bypasses search to serve the video directly.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
|
12
server.py
12
server.py
@ -5,11 +5,10 @@ from threading import Event
|
||||
from datetime import datetime, timedelta
|
||||
from os import environ
|
||||
import logging
|
||||
import re
|
||||
|
||||
def getBestMp4UrlFromInfo(info):
|
||||
entries = info.get('entries')
|
||||
if not entries: return None
|
||||
formats = entries[0].get('formats')
|
||||
formats = info['entries'][0].get('formats') if info.get("entries") else info.get("formats")
|
||||
if not formats: return None
|
||||
valid = list(filter(lambda x: x['ext'] == "mp4" and x['vcodec'] != 'none' and x['acodec'] != 'none', formats))
|
||||
if not valid: return None
|
||||
@ -38,7 +37,10 @@ class Handler(BaseHTTPRequestHandler):
|
||||
self.send_error(404)
|
||||
return
|
||||
|
||||
query = unquote(self.path[1:])
|
||||
path = unquote(self.path)
|
||||
match = re.match("\/(?:id\/|(?:https?:\/\/)?(?:(?:www\.)?youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/))([A-Za-z0-9_-]{11})", path)
|
||||
query = match[1] if match else "ytsearch:" + path[1:]
|
||||
|
||||
dict = query_dicts.get(query)
|
||||
|
||||
if not dict or 'expire' in dict and datetime.now() >= dict['expire']:
|
||||
@ -50,7 +52,7 @@ class Handler(BaseHTTPRequestHandler):
|
||||
ips_running_ytdl.append(client_ip)
|
||||
query_dicts[query] = dict = {'event': Event()}
|
||||
with YoutubeDL() as ydl:
|
||||
info = ydl.extract_info("ytsearch:" + query, download=False)
|
||||
info = ydl.extract_info(query, download=False)
|
||||
url = getBestMp4UrlFromInfo(info)
|
||||
dict['url'] = url
|
||||
dict['expire'] = getExpireDatetime(url)
|
||||
|
@ -10,21 +10,74 @@
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
code {
|
||||
white-space: nowrap;
|
||||
color: brown;
|
||||
}
|
||||
</style>
|
||||
</head><body>
|
||||
<i><h2>Problem:</h2></i>
|
||||
<h2 id="Problem">Problem:</h2>
|
||||
<img src="VRChat_2023-03-21_22-37-32.758_1920x1080.png" alt="A video player in VRChat" style="max-height: 50vh" />
|
||||
<p>No video! No PC to put video! No URLs memorized! What do???</p>
|
||||
<i><h2>SOLUTION!</h2></i>
|
||||
<h2 id="Solution">SOLUTION!</h2>
|
||||
<ol>
|
||||
<li>Type the following exactly into the URL bar: <code>https://u2b.cx/</code></li>
|
||||
<li>TIP: Press the <img alt="copy" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADUAAAA0CAMAAAAdZIDnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADYUExURRwiKxwqMhsvNhwvNhwuNhwmLxwkLRo9QxhKUBdQVhZTWRZSWBdOVBhGTBsyORlCSRVVXBAdIw8XHQ8VGxNUWRdPVRs0Oxs3PhZUWhJFShlESxJJTxwkLBhJTxArMRVYXho6QBAqLxo6QRhLURApLxVZXxo7Qf///8rKy/39/VZYWfv7+2ZnaFBRU2RlZhRaYBo7QhhIThAxNhVXXRlARxRUWw8VHBZRWBswOBE2PRRYXxlCSBJKUBFITRNKURZTWxlFSxwpMRwtNRo8QxlGTBlFTBo4PxwjLAQa4UkAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADhSURBVEhL7dbXDoIwFIDhulFxD3Di3nvvPd7/jSxyIhjBHJF4I99VT5M/KU1ISr5gsdpw7A4oiNPFuD1eJNbnl6pAMBSOoEVjcTHieJiREox4ymQKRiyenjGdycKEJeToXTB5mLCEAq2KJZiwyhWzkv1ZVX2AjWdaVQ0W6oyu4IRUHTZlb6oGrJuv32ZWSoZWrbaeivppJYMdmXbVgUTtZ9Gu3jErJbNS0ld1e/S90R/AhDXk6NtmNIYJaTKd0crKzmHGWSzF1xfh2MVqjbXZ7vb3ihyOy9MZaXS5StHHCLkBefveLzCsA+EAAAAASUVORK5CYII=" width="24" height="24" /> button on the lower left 😉</li>
|
||||
<li>Now after that just type what you wanna watch. For example, if you wanna play nyan cat, type in like so: <code>https://u2b.cx/nyan cat</code></li>
|
||||
<li>The first result from YouTube will start playing. YAAY!</li>
|
||||
<li>TIP: When you wanna watch again, press the <img alt="paste" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADUAAAA0CAMAAAAdZIDnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADeUExURRwiKxwqMhsvNxwvNhwtNRsyORhGTBdOVBZRVhZSWBZRVxhLURo+RBwkLBs2PBdPVRNUWg8ZHw8VGw8WHBAdIxVXXBlFSxwlLhhKUBJHTA8WGxZUWho5QBszOhJKTxo6QRVYXhArMBhJTxwkLRo7QRVZXxAqLxo7QhApL6Skpf///1ZXWVxdXvf39/Hx8bKzs7KysrGxsrCxsUlKTBVZXhs4PhVYXREwNhwjLBsvNhRUWxlBRxlBSBE2PRsxOBwoMBZTWhNMUhFITRJHThRYXxdMUhs3PhlFTBo9RBwuNtYqywoAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADwSURBVEhL7dbZboJQEIDhcalacatWRLHWvfUUF1AsLlXrUvX9X6gcnFhCghliYlLDf3OYSb6Qk3ABXFEgGCIWRgHwEInGHonFhUTSQql05ilLLfecFzkqSEXc0CrJZVO9yDhSq/CXvVZxolarNwCaLZyotQVTvXlV776y9c9VhzF8cuSqPhRFYV3GzAM3ttwUs8r2Toczd4XQJDdQ53x1v6rfHwxUVdU0ja6G+D1Z4e4vN3U5X9nzlb1r1AgnapbSxzhR+5QMgEk8hyOx6Yz/SM29XewrveBqKa6+19Q2290PRwCGPovsiYmH4wl5DuAXf0nZllJEIHwAAAAASUVORK5CYII=" width="24" height="24" /> button on the lower right so you don't have to type it all again 👌</li>
|
||||
<li>TIP: Press the copy <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADUAAAA0CAMAAAAdZIDnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADYUExURRwiKxwqMhsvNhwvNhwuNhwmLxwkLRo9QxhKUBdQVhZTWRZSWBdOVBhGTBsyORlCSRVVXBAdIw8XHQ8VGxNUWRdPVRs0Oxs3PhZUWhJFShlESxJJTxwkLBhJTxArMRVYXho6QBAqLxo6QRhLURApLxVZXxo7Qf///8rKy/39/VZYWfv7+2ZnaFBRU2RlZhRaYBo7QhhIThAxNhVXXRlARxRUWw8VHBZRWBswOBE2PRRYXxlCSBJKUBFITRNKURZTWxlFSxwpMRwtNRo8QxlGTBlFTBo4PxwjLAQa4UkAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADhSURBVEhL7dbXDoIwFIDhulFxD3Di3nvvPd7/jSxyIhjBHJF4I99VT5M/KU1ISr5gsdpw7A4oiNPFuD1eJNbnl6pAMBSOoEVjcTHieJiREox4ymQKRiyenjGdycKEJeToXTB5mLCEAq2KJZiwyhWzkv1ZVX2AjWdaVQ0W6oyu4IRUHTZlb6oGrJuv32ZWSoZWrbaeivppJYMdmXbVgUTtZ9Gu3jErJbNS0ld1e/S90R/AhDXk6NtmNIYJaTKd0crKzmHGWSzF1xfh2MVqjbXZ7vb3ihyOy9MZaXS5StHHCLkBefveLzCsA+EAAAAASUVORK5CYII=" width="24" height="24" /> button on the lower left 😉</li>
|
||||
<li>Now after that just type what you want to watch. Here are just a few examples:</li>
|
||||
<ul>
|
||||
<li><code>https://u2b.cx/nyan cat</code></li>
|
||||
<li><code>https://u2b.cx/never gonna give you up</code></li>
|
||||
<li><code>https://u2b.cx/arabic cat</code></li>
|
||||
<li><code>https://u2b.cx/gangnam style</code></li>
|
||||
<li><code>https://u2b.cx/miku</code></li>
|
||||
<li><code>https://u2b.cx/despacito</code></li>
|
||||
<li><code>https://u2b.cx/baby shark dance</code></li>
|
||||
<li><code>https://u2b.cx/technology connections</code></li>
|
||||
</ul>
|
||||
<li>Just like with the Discord music bots, the first search result from YouTube will start playing.</li>
|
||||
<li>TIP: Next time, press the paste <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADUAAAA0CAMAAAAdZIDnAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAADeUExURRwiKxwqMhsvNxwvNhwtNRsyORhGTBdOVBZRVhZSWBZRVxhLURo+RBwkLBs2PBdPVRNUWg8ZHw8VGw8WHBAdIxVXXBlFSxwlLhhKUBJHTA8WGxZUWho5QBszOhJKTxo6QRVYXhArMBhJTxwkLRo7QRVZXxAqLxo7QhApL6Skpf///1ZXWVxdXvf39/Hx8bKzs7KysrGxsrCxsUlKTBVZXhs4PhVYXREwNhwjLBsvNhRUWxlBRxlBSBE2PRsxOBwoMBZTWhNMUhFITRJHThRYXxdMUhs3PhlFTBo9RBwuNtYqywoAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADwSURBVEhL7dbZboJQEIDhcalacatWRLHWvfUUF1AsLlXrUvX9X6gcnFhCghliYlLDf3OYSb6Qk3ABXFEgGCIWRgHwEInGHonFhUTSQql05ilLLfecFzkqSEXc0CrJZVO9yDhSq/CXvVZxolarNwCaLZyotQVTvXlV776y9c9VhzF8cuSqPhRFYV3GzAM3ttwUs8r2Toczd4XQJDdQ53x1v6rfHwxUVdU0ja6G+D1Z4e4vN3U5X9nzlb1r1AgnapbSxzhR+5QMgEk8hyOx6Yz/SM29XewrveBqKa6+19Q2290PRwCGPovsiYmH4wl5DuAXf0nZllJEIHwAAAAASUVORK5CYII=" width="24" height="24" /> button on the lower right so you don't have to type the whole thing all over again 👍</li>
|
||||
</ol>
|
||||
<i><h3>Demo</h3></i>
|
||||
<h3 id="Demo">Demo</h3>
|
||||
<video controls style="max-height: 80vh"><source src="com.vrchat.oculus.quest-20230321-223838.mp4" type="video/mp4"/></video>
|
||||
<i><h3>Problems?</h3></i>
|
||||
<p>If you encounter any issues, please submit on <a href="https://gitea.moe/lamp/u2b.cx/issues">issue tracker</a>. You can use Discord or GitHub account.</p>
|
||||
<h3 id="Advanced_usage">Advanced Usage</h3>
|
||||
<p>For PC users or world creators who want to make a particular video work on Quest, u2b.cx can also be used as an alternative to sites like <a href="https://nextnex.com" target="_blank">nextnex.com</a> and <a href="https://ytdlh.cf/" target="_blank">ytdlh.cf</a> by using the following syntax: <code>https://u2b.cx/id/<youtube video id></code></p>
|
||||
<p>Paste a YouTube URL here to have it converted for you: <input id="input" type="text" placeholder="https://www.youtube.com/watch?v=dQw4w9WgXcQ" style="width: 309px" /> <span id="output_container" style="display: none"> ➡ <code><span id="output"></span></code> <button id="copy_btn">Copy</button></span></p>
|
||||
<script>
|
||||
var input = document.getElementById("input");
|
||||
var output = document.getElementById("output");
|
||||
var output_container = document.getElementById("output_container");
|
||||
var copy_btn = document.getElementById("copy_btn");
|
||||
input.oninput = function() {
|
||||
var match = input.value.match(/[A-Za-z0-9_-]{11}/);
|
||||
if (match) {
|
||||
output.innerText = `https://u2b.cx/id/${match[0]}`;
|
||||
output_container.style.display = '';
|
||||
} else {
|
||||
output.innerText = '';
|
||||
output_container.style.display = "none";
|
||||
}
|
||||
};
|
||||
copy_btn.onclick = function() {
|
||||
navigator.clipboard.writeText(output.innerText);
|
||||
copy_btn.disabled = true;
|
||||
copy_btn.innerText = "Copied";
|
||||
setTimeout(function(){
|
||||
copy_btn.disabled = false;
|
||||
copy_btn.innerText = "Copy";
|
||||
}, 1000);
|
||||
}
|
||||
</script>
|
||||
<p>For potential support of prefixing implementations, known YouTube URL formats will also be parsed for the ID. This means any one of the following will bypass the YouTube search and look up the video directly:</p>
|
||||
<ul>
|
||||
<li><code>https://u2b.cx/id/dQw4w9WgXcQ</code> (recommended)</li>
|
||||
<li><code>https://u2b.cx/https://www.youtube.com/watch?v=dQw4w9WgXcQ</code></li>
|
||||
<li><code>https://u2b.cx/https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ</code></li>
|
||||
<li><code>https://u2b.cx/http://youtube.com/watch?v=dQw4w9WgXcQ</code></li>
|
||||
<li><code>https://u2b.cx/youtube.com/watch?v=dQw4w9WgXcQ</code></li>
|
||||
<li><code>https://u2b.cx/https://youtu.be/dQw4w9WgXcQ</code></li>
|
||||
<li><code>https://u2b.cx/https://youtube/shorts/dQw4w9WgXcQ</code></li>
|
||||
</ul>
|
||||
<p>Anything else will be sent to YouTube search, which will probably still get what you want.</p>
|
||||
<h3 id="Problems">Problems?</h3>
|
||||
<p>If you encounter any issues such as a service outage, please submit to the <a href="https://gitea.moe/lamp/u2b.cx/issues/new">issue tracker</a>. Thanks.</p>
|
||||
</body></html>
|
||||
|
Loading…
Reference in New Issue
Block a user