Files
site/public/blog/2022/12/10/watching-youtube-in-private/index.html
2023-12-17 19:51:40 -05:00

268 lines
15 KiB
HTML

<!DOCTYPE html>
<html><head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"><title>Watching YouTube in private - davegallant</title><link rel="icon" type="image/png" href=https://davegallant.ca/favicon.ico /><meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="" />
<meta property="og:image" content=""/>
<meta property="og:title" content="Watching YouTube in private" />
<meta property="og:description" content="" />
<meta property="og:type" content="article" />
<meta property="og:url" content="/blog/2022/12/10/watching-youtube-in-private/" /><meta property="article:section" content="post" />
<meta property="article:published_time" content="2022-12-10T21:46:55-05:00" />
<meta property="article:modified_time" content="2022-12-10T21:46:55-05:00" />
<meta name="twitter:card" content="summary"/>
<meta name="twitter:title" content="Watching YouTube in private"/>
<meta name="twitter:description" content=""/>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@1,500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Fira+Sans&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Roboto+Mono" rel="stylesheet">
<link rel="stylesheet" type="text/css" media="screen" href="/css/main.3547bd7f78e8240e2e642eaae27e96ba31dec26821aff923eb7ffc098ac3aaee.css" />
<link id="darkModeStyle" rel="stylesheet" type="text/css" href="/css/dark.c0351bf49d41b33a222e1a32cc0387e850b010f77ab2d79a9d39c72c03afcfdb.css" disabled />
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
tex2jax: {
inlineMath: [['$','$'], ['\\(','\\)']],
displayMath: [['$$','$$'], ['\[','\]']],
processEscapes: true,
processEnvironments: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
TeX: { equationNumbers: { autoNumber: "AMS" },
extensions: ["AMSmath.js", "AMSsymbols.js"] }
}
});
</script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css">
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js"></script>
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" onload="renderMathInElement(document.body);"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
renderMathInElement(document.body, {
delimiters: [
{left: "$$", right: "$$", display: true},
{left: "$", right: "$", display: false}
]
});
});
</script>
<link rel="stylesheet" type="text/css" href="/css/custom.d96bfb9e3314a7699144ab6ae7331d424cbd7fb34a2e890b17e7bb7db4e30f3a.css">
</head>
<body>
<div class="content"><header>
<div class="main">
<a href="/">davegallant</a>
</div>
<nav>
<a href="/">Posts</a>
<a href="/about">About</a>
<a href="/index.xml">RSS</a>
</nav>
<script
type="text/javascript"
src="https://storage.ko-fi.com/cdn/widget/Widget_2.js"
></script>
<span id="dark-mode-toggle" onclick="toggleTheme()"></span>
<script src="/js/themetoggle.js"></script>
<link href="/css/copy-code-button.min.css" rel="stylesheet">
</header>
<main>
<article>
<div class="title">
<h1 class="title">Watching YouTube in private</h1>
<div class="meta">Posted on Dec 10, 2022</div>
</div>
<section class="body"><p>I recently stumbled upon <a href="https://yewtu.be">yewtu.be</a> and found it intriguing. It not only allows you to watch YouTube without <em>being on YouTube</em>, but it also allows you to create an account and subscribe to channels without a Google account. What sort of wizardry is going on under the hood? It turns out that it&rsquo;s a hosted instance of <a href="https://invidious.io/">invidious</a>.</p>
<p><img src="computerphile.png" alt="image"></p>
<p>The layout is simple, and <strong>JavaScript is not required</strong>.</p>
<p>I started using <a href="https://yewtu.be">yewtu.be</a> as my primary client for watching videos. I subscribe to several YouTube channels and I prefer the interface invidiuous provides due to its simplicity. It&rsquo;s also nice to be in control of my search and watch history.</p>
<p>A few days ago, yewtu.be went down briefly, and that motivated me enough to self-host invidious. There are several other hosted instances listed <a href="https://docs.invidious.io/instances/">here</a>, but being able to easily backup my own instance (including subscriptions and watch history) is more compelling in my case.</p>
<h3 id="hosting-invidious">Hosting invidious<a href="#hosting-invidious" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>The quickest way to get invidious up is with docker-compose as mentioned in the <a href="https://docs.invidious.io/installation/">docs</a>.</p>
<p>I made a few modifications, and ended up with:</p>
<div class="highlight"><pre tabindex="0" style="color:#d8dee9;background-color:#2e3440;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#81a1c1">version</span><span style="color:#eceff4">:</span> <span style="color:#a3be8c">&#34;3&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#81a1c1">services</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">invidious</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> quay.io/invidious/invidious
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> unless-stopped
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">ports</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> - <span style="color:#a3be8c">&#34;0.0.0.0:3000:3000&#34;</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">environment</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">INVIDIOUS_CONFIG</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">|</span><span style="color:#616e87">
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> db:
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> dbname: invidious
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> user: kemal
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> password: kemal
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> host: invidious-db
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> port: 5432
</span></span></span><span style="display:flex;"><span><span style="color:#616e87"> check_tables: true</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">healthcheck</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">test</span><span style="color:#eceff4">:</span> wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">interval</span><span style="color:#eceff4">:</span> 30s
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">timeout</span><span style="color:#eceff4">:</span> 5s
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">retries</span><span style="color:#eceff4">:</span> <span style="color:#b48ead">2</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">depends_on</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> - invidious-db
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">invidious-db</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">image</span><span style="color:#eceff4">:</span> docker.io/library/postgres:14
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">restart</span><span style="color:#eceff4">:</span> unless-stopped
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> - postgresdata:/var/lib/postgresql/data
</span></span><span style="display:flex;"><span> - ./config/sql:/config/sql
</span></span><span style="display:flex;"><span> - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">environment</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_DB</span><span style="color:#eceff4">:</span> invidious
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_USER</span><span style="color:#eceff4">:</span> kemal
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">POSTGRES_PASSWORD</span><span style="color:#eceff4">:</span> kemal
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">healthcheck</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">test</span><span style="color:#eceff4">:</span> <span style="color:#eceff4">[</span><span style="color:#a3be8c">&#34;CMD-SHELL&#34;</span><span style="color:#eceff4">,</span> <span style="color:#a3be8c">&#34;pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB&#34;</span><span style="color:#eceff4">]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#81a1c1">volumes</span><span style="color:#eceff4">:</span>
</span></span><span style="display:flex;"><span> <span style="color:#81a1c1">postgresdata</span><span style="color:#eceff4">:</span>
</span></span></code></pre></div><p>After invidious was up and running, I installed <a href="https://tailscale.com/">Tailscale</a> on it to leverage its MagicDNS, and I&rsquo;m now able to access this instance from anywhere at <a href="http://invidious:3000/feed/subscriptions">http://invidious:3000/feed/subscriptions</a>.</p>
<h3 id="redirecting-youtube-links">Redirecting YouTube links<a href="#redirecting-youtube-links" class="hanchor" ariaLabel="Anchor">#</a></h3>
<p>I figured it would be nice to redirect existing YouTube links that others send me, so that I could seamlessly watch the videos using invidious.</p>
<p>I went looking for a way to redirect paths at the browser level. I found the lightweight proxy <a href="https://requestly.io/">requestly</a>, which can be used to modify http requests in my browser. I created the following rules:</p>
<p><img src="requestly-rules.png" alt="requestly"></p>
<p>Now the link <a href="https://www.youtube.com/watch?v=-lz30by8-sU">https://www.youtube.com/watch?v=-lz30by8-sU</a> will redirect to <a href="http://invidious:3000/watch?v=-lz30by8-sU">http://invidious:3000/watch?v=-lz30by8-sU</a></p>
<p>I&rsquo;m still looking for ways to improve this invidious setup. There doesn&rsquo;t appear to be a way to stream in 4K yet.</p></section>
<script
type="text/javascript"
src="https://storage.ko-fi.com/cdn/widget/Widget_2.js"
></script>
<script type="text/javascript">
kofiwidget2.init("Buy me a coffee", "#a15bc2", "F1F2S4LWI");
kofiwidget2.draw();
</script>
<div class="post-tags">
<nav class="nav tags">
<ul class="tags">
<li><a href="/tags/invidious">invidious</a></li>
<li><a href="/tags/degoogle">degoogle</a></li>
<li><a href="/tags/youtube">youtube</a></li>
<li><a href="/tags/yewtu.be">yewtu.be</a></li>
<li><a href="/tags/tailscale">tailscale</a></li>
<li><a href="/tags/privacy">privacy</a></li>
<li><a href="/tags/self-hosted">self-hosted</a></li>
</ul>
</nav>
</div>
</article>
</main>
<section id='comments' class='comments'>
<div class='container sep-before'>
<div class='comments'><script>
var getTheme = window.localStorage && window.localStorage.getItem("theme-storage");
getTheme = getTheme == null ? 'light' : getTheme;
let theme = getTheme === 'dark' ? 'github-dark' : 'github-light';
let s = document.createElement('script');
s.src = 'https://utteranc.es/client.js';
s.setAttribute('repo', 'davegallant\/davegallant.github.io');
s.setAttribute('issue-term', 'pathname');
s.setAttribute('theme', theme);
s.setAttribute('crossorigin', 'anonymous');
s.setAttribute('async', '');
document.querySelector('div.comments').innerHTML = '';
document.querySelector('div.comments').appendChild(s);
</script>
</div>
</div>
</section><footer>
<script src="https://storage.ko-fi.com/cdn/scripts/overlay-widget.js"></script>
<div style="display: flex"><a class="soc" href="mailto:me@davegallant.ca" rel="me" title="Email"
><i data-feather="at-sign"></i
></a>
<a class="border"></a><a class="soc" href="https://linktr.ee/davegallant" rel="me" title="LinkTree"
><i data-feather="compass"></i
></a>
<a class="border"></a><a class="soc" href="https://github.com/davegallant" rel="me" title="GitHub"
><i data-feather="github"></i
></a>
<a class="border"></a><a class="soc" href="https://mastodon.social/@davegallant" rel="me" title="Mastodon"
><i data-feather="speaker"></i
></a>
<a class="border"></a><a class="soc" href="https://www.linkedin.com/in/dave-gallant/" rel="me" title="LinkedIn"
><i data-feather="linkedin"></i
></a>
<a class="border"></a></div>
<div class="footer-info">
2023 Dave Gallant
</div>
<script src="/js/copy-code-button.js"></script>
</footer>
<script async src="https://www.googletagmanager.com/gtag/js?id=G-V8WJDERTX9"></script>
<script>
var doNotTrack = false;
if (!doNotTrack) {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-V8WJDERTX9', { 'anonymize_ip': false });
}
</script>
<script>
feather.replace();
</script></div>
</body>
</html>