<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Knowledge Base (Posts about video)</title><link>https://bgstack15.ddns.net/blog/</link><description></description><atom:link href="https://bgstack15.ddns.net/blog/categories/video.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2025 &lt;a href="mailto:bgstack15@gmail.com"&gt;bgstack15&lt;/a&gt; 
&lt;a rel="license" href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;
&lt;img alt="Creative Commons License BY-SA"
style="border-width:0; margin-bottom:12px;"
src="https://bgstack15.ddns.net/.images/l_by-sa_4.0_88x31.png"&gt;&lt;/a&gt;</copyright><lastBuildDate>Wed, 26 Feb 2025 15:27:11 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Jitsi reenable self view</title><link>https://bgstack15.ddns.net/blog/posts/2025/01/31/jitsi-reenable-self-view/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/jitsi.org/jitsi-meet/"&gt;Jitsi Meet&lt;/a&gt; is great software. It's gotten better and better over time! Unfortunately, there's one little tiny problem. If you hide your self-view, you see a little notification that says you can re-enable the view from Settings. This &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/github.com/jitsi/jitsi-meet/issues/8477"&gt;information is wrong&lt;/a&gt;, however. So you have to run a little javascript scriptlet and somehow reload the page, without it overwriting this value. I haven't quite settled on what exact order of operations (run javascript, reload page, log out of meeting?) needs to happen, but hopefully somebody else can move this further along and make it work in the end.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;a = JSON.parse(localStorage["features/base/settings"]);
a["disableSelfView"] = false;
localStorage.setItem("features/base/settings",JSON.stringify(a));
&lt;/pre&gt;&lt;/div&gt;</description><category>jitsi</category><category>video</category><guid>https://bgstack15.ddns.net/blog/posts/2025/01/31/jitsi-reenable-self-view/</guid><pubDate>Fri, 31 Jan 2025 13:38:00 GMT</pubDate></item><item><title>Lua script for mpv to keep xscreensaver from running</title><link>https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;As noted in the file itself, this is adapted from &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/gist.github.com/elenril/f8ff9475a7882b7a16cdd723c7dce150"&gt;MPV script that deactivates XScreensaver when video playback is active&lt;/a&gt;, and it was officially listed at &lt;a href="https://bgstack15.ddns.net/blog/outbound/https:/github.com/mpv-player/mpv/wiki/User-Scripts#lua-scripts"&gt;User Scripts · mpv-player/mpv Wiki#lua-scripts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://bgstack15.ddns.net/blog/files/2024/listings/xscreensaver.lua.html"&gt;files/2024/listings/xscreensaver.lua&lt;/a&gt;  &lt;a href="https://bgstack15.ddns.net/blog/files/2024/listings/xscreensaver.lua"&gt;(Source)&lt;/a&gt;&lt;/p&gt;&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;-- Ripped from https://gist.github.com/elenril/f8ff9475a7882b7a16cdd723c7dce150 and configured by bgstack15
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;-- linked at https://github.com/mpv-player/mpv/wiki/User-Scripts
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;-- this script periodically deactivates xscreensaver
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;-- when video playback is active
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;local&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; heartbeat&lt;span class="o"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;    &lt;span class="k"&gt;if&lt;/span&gt; mp.get_property_native&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"pause"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; or
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;       mp.get_property_native&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"idle"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;  or
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;       not mp.get_property_native&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"vo-configured"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;        &lt;span class="k"&gt;return&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;    end
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;    mp.command_native_async&lt;span class="o"&gt;(&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;        &lt;span class="o"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;          &lt;span class="nv"&gt;name&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"subprocess"&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;          &lt;span class="nv"&gt;args&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"xscreensaver-command"&lt;/span&gt;, &lt;span class="s2"&gt;"-deactivate"&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;          &lt;span class="nv"&gt;capture_stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; true,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;        &lt;span class="o"&gt;}&lt;/span&gt;,
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;        &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="o"&gt;()&lt;/span&gt; end&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-20"&gt;&lt;code data-line-number="20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;end
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-21"&gt;&lt;code data-line-number="21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-22"&gt;&lt;code data-line-number="22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;mp.add_periodic_timer&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;, heartbeat&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-23"&gt;&lt;code data-line-number="23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-24"&gt;&lt;code data-line-number="24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; _, prop &lt;span class="k"&gt;in&lt;/span&gt; ipairs&lt;span class="o"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;"pause"&lt;/span&gt;, &lt;span class="s2"&gt;"idle"&lt;/span&gt;, &lt;span class="s2"&gt;"vo-configured"&lt;/span&gt;&lt;span class="o"&gt;})&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-25"&gt;&lt;code data-line-number="25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;    mp.observe_property&lt;span class="o"&gt;(&lt;/span&gt;prop, nil, heartbeat&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/#-26"&gt;&lt;code data-line-number="26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;end
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Tells mpv to keep running command &lt;code&gt;xscreensaver-command -deactivate&lt;/code&gt; which simulates user activity. Ergo, it is designed actually for this use case.&lt;/p&gt;
&lt;p&gt;You can place this file as &lt;code&gt;~/.config/mpv/scripts/xscreensaver.lua&lt;/code&gt;.&lt;/p&gt;</description><category>lua</category><category>mpv</category><category>video</category><category>xscreensaver</category><guid>https://bgstack15.ddns.net/blog/posts/2024/05/29/lua-script-for-mpv-to-keep-xscreensaver-from-running/</guid><pubDate>Wed, 29 May 2024 12:53:06 GMT</pubDate></item><item><title>Save videos: 2022 edition</title><link>https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;My current process for running yt-dlp involves &lt;a href="https://manpages.org/detox"&gt;detox&lt;/a&gt;ing the filenames.&lt;/p&gt;
&lt;p&gt;File &lt;code&gt;save-videos.sh&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Startdate: 2022-09-20&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Purpose: single utility that downloads and safely renames provided files&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dependencies:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    yt-dlp&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    detox&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    rename&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    files: config/detoxrc config/safe.tbl&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;"/path/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SUBDIR&lt;/span&gt;&lt;span class="p"&gt;:+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SUBDIR&lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;mkdir -p temp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; temp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;USED_TEMP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;LANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latin-1 &lt;span class="nv"&gt;PYTHONIOENCODING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;latin-1 yt-dlp &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USED_TEMP&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# remove weird characters&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   detox -f &lt;span class="s2"&gt;"config/detoxrc"&lt;/span&gt; -v *
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# strip the dash that precedes the youtube VID&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   rename &lt;span class="s1"&gt;'s/ -([a-zA-Z0-9_]{11}\.)/ $1/'&lt;/span&gt; *
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   mv -i * ..
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/#-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;File &lt;code&gt;config/detoxrc&lt;/code&gt;:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sequence default {
  uncgi;
  iso8859_1 {
    filename "/usr/share/detox/iso8859_1.tbl";
  };
  safe {
    filename "config/safe.tbl";
  };
  wipeup {
    remove_trailing;
  };
};
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And my only differences for &lt;code&gt;config/safe.tbl&lt;/code&gt; are:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="gd"&gt;--- /usr/share/detox/safe.tbl   2022-09-20 15:02:16.000000000 -0400&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+++ config/safe.tbl 2022-09-20 10:08:23.326100599 -0400&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gu"&gt;@@ -99,11 +99,11 @@&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x09       _   # tab&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x0A       _   # new line&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x0D       _   # carriage return&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-0x20       _   # space&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-0x21       _   # !&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+#0x20      _   # space&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+0x21       ''  # !&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x22       _   # "&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x24       _   # $&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gd"&gt;-0x27       _   # '&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="gi"&gt;+0x27       ''  # '&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x2a       _   # *&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x2f       _   # /&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;0x3a       _   # :&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I entirely discard exclamation mark &lt;code&gt;!&lt;/code&gt; and single quote &lt;code&gt;'&lt;/code&gt;, and do not replace spaces at all.&lt;/p&gt;</description><category>detox</category><category>rename</category><category>video</category><category>youtube-dl</category><guid>https://bgstack15.ddns.net/blog/posts/2022/10/20/save-videos-2022-edition/</guid><pubDate>Thu, 20 Oct 2022 12:35:53 GMT</pubDate></item><item><title>My dvd ripping solution, 2022 edition</title><link>https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;Last year, I wrote about my &lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/"&gt;dvd-ripping solution&lt;/a&gt;. Of course, over time my process has improved and evolved.&lt;/p&gt;
&lt;h3&gt;Ripping the DVDs&lt;/h3&gt;
&lt;p&gt;I now use &lt;a href="http://makemkv.com/"&gt;makemkv&lt;/a&gt; again, because Handbrake itself suggests that other tools are better for ripipng from removable media. Handbrake is for transcoding.&lt;/p&gt;
&lt;p&gt;When I stick discs in my (3) drives, I then run a command inside GNU screen.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;time APPLY=1 INPUT=/dev/sr0:/dev/sr1:/dev/sr2 JOBNAME=s3d6 sh -x makemkv.sh
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The jobname is arbitrary and helps keep job outputs distinct when I let them pile up. Here is the script &lt;code&gt;makemkv.sh&lt;/code&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Startdate: 2021-10-02 19:21&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Purpose: rip disc automatically&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# History:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    This is the second version of makemkv.sh (first one was renamed to makemkv-2019.sh)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    2022-08-03 13:11 add unshare to keep makemkv from accessing the network&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Reference:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    /mnt/public/Support/Programs/DVDs/handbrake-internal.sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Flow: use makemkv to make the original rip, and then handbrake to convert to the preferred size/format.&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/dev/sr0"&lt;/span&gt; &lt;span class="c1"&gt;# colon-delimited&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/public/Video/temp/makemkv
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-14"&gt;&lt;code data-line-number="14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &amp;lt; /dev/urandom tr -dc &lt;span class="s1"&gt;'A-Z0-9'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; head -c6 &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-15"&gt;&lt;code data-line-number="15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/1-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-run-makemkv.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-16"&gt;&lt;code data-line-number="16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/2-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-run-handbrake.sh"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-17"&gt;&lt;code data-line-number="17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-18"&gt;&lt;code data-line-number="18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt; &amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-19"&gt;&lt;code data-line-number="19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-20"&gt;&lt;code data-line-number="20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; line &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;":&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;':'&lt;/span&gt; &lt;span class="s1"&gt;'\n'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -viE &lt;span class="s1"&gt;'^\s*$'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-21"&gt;&lt;code data-line-number="21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-22"&gt;&lt;code data-line-number="22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;bline&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; basename &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-23"&gt;&lt;code data-line-number="23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"process &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-24"&gt;&lt;code data-line-number="24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;mminfo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; unshare -r -n makemkvcon info dev:&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-25"&gt;&lt;code data-line-number="25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;#echo "${mminfo}" &amp;gt;&amp;gt; "${TMPFILE}"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-26"&gt;&lt;code data-line-number="26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;mminfo&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -r -e &lt;span class="s1"&gt;'1,/Total/d'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -c Title &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-27"&gt;&lt;code data-line-number="27"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; HandBrakeCLI --markers --format mkv --min-duration &lt;span class="m"&gt;125&lt;/span&gt; --scan --input &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; --output &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  --encoder x264 --rate &lt;span class="m"&gt;30&lt;/span&gt; --native-language eng --title &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-28"&gt;&lt;code data-line-number="28"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;disctitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;raw&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -n -r -e &lt;span class="s1"&gt;'/DVD Title:/{s/.*DVD Title: //;p}'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-29"&gt;&lt;code data-line-number="29"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-30"&gt;&lt;code data-line-number="30"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nv"&gt;$x&lt;/span&gt; -lt &lt;span class="nv"&gt;$count&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-31"&gt;&lt;code data-line-number="31"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;do&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-32"&gt;&lt;code data-line-number="32"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="p"&gt;:+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;bline&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;disctitle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-33"&gt;&lt;code data-line-number="33"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;#mkdir -p "${OUTDIR}"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-34"&gt;&lt;code data-line-number="34"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;#echo makemkvcon mkv "dev:${line}" "${x}" "${OUTDIR}"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-35"&gt;&lt;code data-line-number="35"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"mkdir -p \"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\" ; unshare -r -n makemkvcon mkv \"dev:&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\" \"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\" \"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\""&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-36"&gt;&lt;code data-line-number="36"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;newfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; find &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; -mindepth &lt;span class="m"&gt;1&lt;/span&gt; -maxdepth &lt;span class="m"&gt;1&lt;/span&gt; ! -type d -print -quit &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;/dev/null &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-37"&gt;&lt;code data-line-number="37"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;newfile&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;newfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/*.mkv"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-38"&gt;&lt;code data-line-number="38"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;outfilename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="p"&gt;:+&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;JOBNAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="nv"&gt;_&lt;/span&gt;&lt;span class="si"&gt;}${&lt;/span&gt;&lt;span class="nv"&gt;bline&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;disctitle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;v&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.mkv"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; tr &lt;span class="s1"&gt;' '&lt;/span&gt; &lt;span class="s1"&gt;'_'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-39"&gt;&lt;code data-line-number="39"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"HandBrakeCLI --markers --format mkv --input "&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTDIR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"/*.mkv --output \"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;outfilename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\" --encoder x264 --rate 30 --native-language eng --mixdown 6ch --aencoder ffaac --audio 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, --subtitle 0,1,2,3,4,5,6,7,8,10,11,12,13,14,15,scan"&lt;/span&gt; &amp;gt;&amp;gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-40"&gt;&lt;code data-line-number="40"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nv"&gt;x&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;x+1&lt;span class="k"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-41"&gt;&lt;code data-line-number="41"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-42"&gt;&lt;code data-line-number="42"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-43"&gt;&lt;code data-line-number="43"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-44"&gt;&lt;code data-line-number="44"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# So after all the prep work is done, we need to run step 1 and then step 2&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-45"&gt;&lt;code data-line-number="45"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"BEGIN STEP 1"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-46"&gt;&lt;code data-line-number="46"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APPLY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-47"&gt;&lt;code data-line-number="47"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-48"&gt;&lt;code data-line-number="48"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   sh -x &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-49"&gt;&lt;code data-line-number="49"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-50"&gt;&lt;code data-line-number="50"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   cat &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step1file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-51"&gt;&lt;code data-line-number="51"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-52"&gt;&lt;code data-line-number="52"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"####################################################################"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-53"&gt;&lt;code data-line-number="53"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"####################################################################"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-54"&gt;&lt;code data-line-number="54"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"You may now eject the disc(s)."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-55"&gt;&lt;code data-line-number="55"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"####################################################################"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-56"&gt;&lt;code data-line-number="56"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"####################################################################"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-57"&gt;&lt;code data-line-number="57"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"BEGIN STEP 2"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-58"&gt;&lt;code data-line-number="58"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt; -n &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;APPLY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-59"&gt;&lt;code data-line-number="59"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;then&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-60"&gt;&lt;code data-line-number="60"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   sh -x &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-61"&gt;&lt;code data-line-number="61"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;else&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-62"&gt;&lt;code data-line-number="62"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   cat &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;step2file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-63"&gt;&lt;code data-line-number="63"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-64"&gt;&lt;code data-line-number="64"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"DONE"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/#-65"&gt;&lt;code data-line-number="65"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;date
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;Once that is done, the raw ripped files are stored at glob &lt;code&gt;/mnt/public/Video/temp/makemkv/JOBNAME_sr*/*/*.mkv&lt;/code&gt;, and the handbrake-transcoded files are at glob &lt;code&gt;/mnt/public/Video/temp/makemkv/JOBNAME_sr*_namefromdisc.mkv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now I manually inspect each video file and rename them to the correct episode name, or extra file name (which probably won't be updated in the next step).&lt;/p&gt;
&lt;p&gt;For show episodes, I run a script which I described in that previous post. I have an input csv which I hand-curate from the Wikipedia pages usually, that includes columns &lt;strong&gt;s&lt;/strong&gt;, &lt;strong&gt;sep&lt;/strong&gt;, &lt;strong&gt;ep&lt;/strong&gt;, &lt;strong&gt;airdate&lt;/strong&gt;, &lt;strong&gt;filename&lt;/strong&gt;.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;have,s,ep,sep,title,airdate,filename
1,1,1,01-e02,Encounter at Farpoint,1987-09-28,s01e01-e02 - Encounter at Farpoint
1,1,3,3,The Naked Now,1987-10-05,s01e03 - The Naked Now
1,1,4,4,Code of Honor,1987-10-12,s01e04 - Code of Honor
1,1,5,5,The Last Outpost,1987-10-19,s01e05 - The Last Outpost
1,1,6,6,Where No One Has Gone Before,1987-10-26,s01e06 - Where No One Has Gone Before
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I describe my csv generation process a little more in that &lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/"&gt;previous post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Then I run the next script:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;time&lt;/span&gt; &lt;span class="nv"&gt;tv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;mkv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;helper&lt;/span&gt;.&lt;span class="nv"&gt;py&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;inputcsv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/mnt/public/Video/TV/Star Trek The Next Generation (1987)/STTNG.csv&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;mnt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;public&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;Video&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script is still exactly the same as in the &lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/"&gt;previous post&lt;/a&gt;. I like the metadata of the original airdate on the episode, as well as of course video title. And I have never found a use for the "next file" tags that mkvtoolnix can show you, but I populate them because I can. Maybe it'll be useful someday.&lt;/p&gt;
&lt;p&gt;And then I manually move the files to their intended destinations.&lt;/p&gt;</description><category>handbrake</category><category>jellyfin</category><category>media</category><category>metadata</category><category>mkv</category><category>video</category><guid>https://bgstack15.ddns.net/blog/posts/2022/09/10/my-dvd-ripping-solution-2022-edition/</guid><pubDate>Sat, 10 Sep 2022 13:16:48 GMT</pubDate></item><item><title>Running Jitsi Meet on a virtual directory</title><link>https://bgstack15.ddns.net/blog/posts/2022/06/26/running-jitsi-meet-on-virtual-directory/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;It is possible to configure Jitsi Meet to use a subdirectory, so that you can use &lt;a href="https://www.example.com/jitsi/"&gt;https://www.example.com/jitsi/&lt;/a&gt; but it breaks the Jitsi mobile app. If the entire user base uses desktop-based web browsers, a virtual directory is feasible.&lt;/p&gt;
&lt;p&gt;Select a virtual directory. I used &lt;code&gt;/jitsi/&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Modify Meet server&lt;/h4&gt;
&lt;p&gt;Modify file &lt;code&gt;web/Dockerfile&lt;/code&gt; to have a second RUN statement:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;RUN&lt;/span&gt; &lt;span class="nv"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;base href="/jitsi/" /&amp;gt;&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;jitsi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;meet&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;.&lt;span class="nv"&gt;html&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; \
    &lt;span class="nv"&gt;sed&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;r&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;e&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/#include virtual/{s/"\//"/;};&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;jitsi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;meet&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;index&lt;/span&gt;.&lt;span class="nv"&gt;html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Build this image with &lt;code&gt;docker build .&lt;/code&gt; when running from inside that &lt;code&gt;web/&lt;/code&gt; directory. Record the image name or id number. Modify &lt;code&gt;docker-compose.yml&lt;/code&gt; to use this new image id for service &lt;code&gt;web&lt;/code&gt;, e.g.:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;services:
    # Frontend
    web:
        image: e16e8216e37b
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Modify attribute &lt;code&gt;PUBLIC_URL&lt;/code&gt; in file &lt;code&gt;.env&lt;/code&gt;:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;PUBLIC_URL=https://www.example.com/jitsi/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;An optional step, which supports the legacy http-bind method instead of the current websocket method, is to prepare file &lt;code&gt;~/.jitsi-meet-cfg/web/config.js&lt;/code&gt; by extracting it from a running web instance and modifying it in the following manner.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;sed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'/bosh:/{s/\/http-bind/\/jitsi\/http-bind/;};'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;js&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The file will then resemble included file &lt;a href="https://bgstack15.ddns.net/blog/2022/06/config.js.subdir.example"&gt;config.js.subdir.example&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Restart docker-compose.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;cd ~/docker-jitsi-meet-stable-7287
docker-compose down
docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;Modify httpd server&lt;/h4&gt;
&lt;p&gt;In my public https virtual host, add the directives for this Jitsi meet instance.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="err"&gt;*:443&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   ServerName www.example.com
   ServerAlias www.ipa.internal.com www.internal.com
   DocumentRoot /var/www/external
   Include conf.d/ssl-common.cnf
   Include conf.d/ssl-443.cnf
   ProxyPreserveHost On
   # Below here is for Jitsi Meet
   &lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="err"&gt;mod_proxy.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="err"&gt;mod_proxy_wstunnel.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         ProxyTimeout 900
         &lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/jitsi/xmpp-websocket"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            ProxyPass "ws://server4:8000/xmpp-websocket"
         &lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/jitsi/colibri-ws/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            ProxyPass "ws://server4:8000/colibri-ws/"
         &lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
   Proxypass         /jitsi/     http://server4:8000/
   ProxypassReverse  /jitsi/     http://server4:8000/
&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Reload httpd. The virtual directory should now work on desktop browsers.&lt;/p&gt;
&lt;h2&gt;Files involved&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;server4:/home/jitsi/docker-jitsi-meet-stable-7287/web/Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;server4:/home/jitsi/.jitsi-meet-cfg/web/config.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;h3&gt;Weblinks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/32295168/make-jitsi-meet-work-with-apache-on-a-sub-url"&gt;https://stackoverflow.com/questions/32295168/make-jitsi-meet-work-with-apache-on-a-sub-url&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description><category>directory</category><category>httpd</category><category>jitsi</category><category>video</category><category>virtual</category><guid>https://bgstack15.ddns.net/blog/posts/2022/06/26/running-jitsi-meet-on-virtual-directory/</guid><pubDate>Sun, 26 Jun 2022 12:56:17 GMT</pubDate></item><item><title>Self-hosted Jitsi Meet</title><link>https://bgstack15.ddns.net/blog/posts/2022/06/22/self-hosted-jitsi-meet/</link><dc:creator>bgstack15</dc:creator><description>&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;I set up a self-hosted &lt;a href="https://meet.jit.si"&gt;Jitsi Meet&lt;/a&gt; instance, which is of course the video conferencing software. These are the steps I took and additional research options for future use. No custom SELinux rules were necessary, which is a departure from the norm. I guess docker handles the SELinux parts?&lt;/p&gt;
&lt;h3&gt;Devices&lt;/h3&gt;
&lt;p&gt;I used these systems.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;th&gt;IP address&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;server1&lt;/td&gt;
&lt;td&gt;CentOS 7&lt;/td&gt;
&lt;td&gt;10.43.20.155&lt;/td&gt;
&lt;td&gt;apache httpd server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;server4&lt;/td&gt;
&lt;td&gt;CentOS 7&lt;/td&gt;
&lt;td&gt;10.44.153.156&lt;/td&gt;
&lt;td&gt;docker host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;net1&lt;/td&gt;
&lt;td&gt;ddwrt&lt;/td&gt;
&lt;td&gt;10.43.20.1&lt;/td&gt;
&lt;td&gt;ingress for port forwarding&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Setting up Jitsi Meet&lt;/h2&gt;
&lt;h3&gt;Installing Meet server&lt;/h3&gt;
&lt;p&gt;I already had docker and docker-compose installed on server4. Those steps are outside the scope of this document.&lt;/p&gt;
&lt;p&gt;Follow the directions from &lt;a href="https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/"&gt;reference 1&lt;/a&gt; which are included here briefly.&lt;/p&gt;
&lt;p&gt;Fetch latest release: &lt;a href="https://github.com/jitsi/docker-jitsi-meet/releases/latest"&gt;https://github.com/jitsi/docker-jitsi-meet/releases/latest&lt;/a&gt; and do not clone the git repo. I etracted to the home directory of my service account, so use the directory name from the tarball.&lt;/p&gt;
&lt;p&gt;Configure a &lt;code&gt;.env&lt;/code&gt; file from the env.example file. Mine is included file &lt;a href="https://bgstack15.ddns.net/blog/2022/06/env.internal"&gt;env.internal&lt;/a&gt;. Note that &lt;code&gt;DOCKER_HOST_ADDRESS&lt;/code&gt; should point to the public IP address, so the IPv4 address for &lt;code&gt;www.example.com&lt;/code&gt;. This attribute is important because groups of 3 and more participants use the server as a central point, rather than the peer-to-peer connection of just 2 participants.&lt;/p&gt;
&lt;p&gt;Make directories:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;mkdir -p ~/.jitsi-meet-cfg/{web,transcripts,prosody/config,prosody/prosody-plugins-custom,jicofo,jvb,jigasi,jibri}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Start the application.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;docker-compose up -d
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open the host firewall on server4.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;tf=/usr/lib/firewalld/services/jitsi-meet.xml
sudo touch "&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;" ; sudo chmod 0644 "&lt;span class="cp"&gt;${&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="cp"&gt;}&lt;/span&gt;"
cat &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;EOF&lt;/span&gt; &lt;span class="err"&gt;|&lt;/span&gt; &lt;span class="err"&gt;sudo&lt;/span&gt; &lt;span class="err"&gt;tee&lt;/span&gt; &lt;span class="err"&gt;"${tf}"&lt;/span&gt; &lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/dev/null
&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;service&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;short&amp;gt;&lt;/span&gt;jitsi-meet&lt;span class="nt"&gt;&amp;lt;/short&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt;Jitsi Meet is a web conferencing solution. These rules expect a different host to handle encryption.&lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;port&lt;/span&gt; &lt;span class="na"&gt;protocol=&lt;/span&gt;&lt;span class="s"&gt;"tcp"&lt;/span&gt; &lt;span class="na"&gt;port=&lt;/span&gt;&lt;span class="s"&gt;"8000"/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;port&lt;/span&gt; &lt;span class="na"&gt;protocol=&lt;/span&gt;&lt;span class="s"&gt;"udp"&lt;/span&gt; &lt;span class="na"&gt;port=&lt;/span&gt;&lt;span class="s"&gt;"10000"/&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/service&amp;gt;&lt;/span&gt;
EOF

sudo firewall-cmd --reload
sudo firewall-cmd --permanent --add-service=jitsi-meet
sudo firewall-cmd --reload
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Configuring Apache httpd for reverse proxy&lt;/h3&gt;
&lt;p&gt;Host server1 is the main web server for the Internal network. Modify the main configuration file, &lt;code&gt;/etc/httpd/conf.d/local_mirror.conf&lt;/code&gt; with a new virtual host and listen directive.&lt;/p&gt;
&lt;p&gt;This snippet depends on ssl-pre being included at the top, and also the relevant included files.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;# 5443 is jitsi
Listen *:5443
&lt;span class="nt"&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class="err"&gt;*:5443&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
   Include conf.d/ssl-common.cnf
   Include conf.d/ssl-5443.cnf
   ProxyPreserveHost On
   &lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="err"&gt;mod_proxy.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;IfModule&lt;/span&gt; &lt;span class="err"&gt;mod_proxy_wstunnel.c&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
         ProxyTimeout 900
         &lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/xmpp-websocket"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            ProxyPass "ws://server4:8000/xmpp-websocket"
         &lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
         &lt;span class="nt"&gt;&amp;lt;Location&lt;/span&gt; &lt;span class="err"&gt;"/colibri-ws/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            ProxyPass "ws://server4:8000/colibri-ws/"
         &lt;span class="nt"&gt;&amp;lt;/Location&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
   &lt;span class="nt"&gt;&amp;lt;/IfModule&amp;gt;&lt;/span&gt;
   Proxypass         /     http://server4:8000/
   ProxypassReverse  /     http://server4:8000/
&lt;span class="nt"&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Modify SELinux rules to allow httpd to listen on port 5443.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;sudo semanage port -a -t http_port_t -p tcp 5443
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Reload httpd after testing it.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;systemctl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;reload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;httpd&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open the host firewall on server1. I updated my custom firewall service xml rule and reloaded firewalld.&lt;/p&gt;
&lt;h3&gt;Configure router&lt;/h3&gt;
&lt;p&gt;Device &lt;code&gt;net1&lt;/code&gt; is the current edge router for Internal network. Modify the port forwarding rules to include the following:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Application&lt;/th&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Port from&lt;/th&gt;
&lt;th&gt;IP address&lt;/th&gt;
&lt;th&gt;Port to&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jitsi1&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;5443&lt;/td&gt;
&lt;td&gt;10.43.20.155&lt;/td&gt;
&lt;td&gt;5443&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;jitsi2&lt;/td&gt;
&lt;td&gt;Both&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;td&gt;10.44.153.156&lt;/td&gt;
&lt;td&gt;10000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Files involved&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;server4:/home/jitsi/stable-7287.tar.gz&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;server4:/home/jitsi/docker-jitsi-meet-stable-7287/.env&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;server4:/usr/lib/firewalld/services/jitsi-meet.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;server1:/usr/lib/firewalld/services/http-internal.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;server1:/etc/httpd/conf.d/local_mirror.conf&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;References&lt;/h2&gt;
&lt;h3&gt;Weblinks&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/"&gt;https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Other&lt;/h3&gt;
&lt;p&gt;Original research&lt;/p&gt;</description><category>jitsi</category><category>video</category><guid>https://bgstack15.ddns.net/blog/posts/2022/06/22/self-hosted-jitsi-meet/</guid><pubDate>Wed, 22 Jun 2022 12:54:46 GMT</pubDate></item><item><title>My DVD-ripping solution</title><link>https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/</link><dc:creator>bgstack15</dc:creator><description>&lt;p&gt;This is a work in progress, but its current status is as follows.&lt;/p&gt;
&lt;h3&gt;Ripping the DVDs&lt;/h3&gt;
&lt;p&gt;To rip my DVD collection, use my &lt;a href="https://handbrake.fr/"&gt;handbrake&lt;/a&gt; wrapper
script. My ripping machine uses two disc drives. Run the script once per
drive, and save all output to a temporary file.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;{ INPUT=/dev/sr0 handbrake.sh ; INPUT=/dev/sr1 handbrake.sh ; } &amp;gt; ~/handbrake1
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inspect the script for correctness. Mine looks like:&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;HandBrakeCLI --markers --format mkv --min-duration 125 --input /dev/sr0 --output /mnt/public/Video/temp/TNGS2D3_V1.mkv --encoder x264 --rate 30 --native-language eng --title 1 --audio 1,2, --subtitle 1,2,scan --native-language eng --mixdown 6ch --aencoder ffaac
HandBrakeCLI --markers --format mkv --min-duration 125 --input /dev/sr0 --output /mnt/public/Video/temp/TNGS2D3_V2.mkv --encoder x264 --rate 30 --native-language eng --title 2 --audio 1,2, --subtitle 1,2,scan --native-language eng --mixdown 6ch --aencoder ffaac
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The handbrake.sh script can be found at the bottom of this post and is
explained further there. Run the temp file's commands. I like to do this in a
GNU screen session.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;time sh -x ~/handbrake1
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Adding TV show metadata&lt;/h3&gt;
&lt;p&gt;Prepare a csv with s, sep, ep, airdate, title, and filename columns.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;have,s,ep,sep,title,airdate,filename
1,1,1,01-e02,Encounter at Farpoint,1987-09-28,s01e01-e02 - Encounter at Farpoint
1,1,3,3,The Naked Now,1987-10-05,s01e03 - The Naked Now
1,1,4,4,Code of Honor,1987-10-12,s01e04 - Code of Honor
1,1,5,5,The Last Outpost,1987-10-19,s01e05 - The Last Outpost
1,1,6,6,Where No One Has Gone Before,1987-10-26,s01e06 - Where No One Has Gone Before
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This filename output is supposed to be what Jellyfin wants for &lt;a href="https://jellyfin.org/docs/general/server/media/shows.html"&gt;TV
shows&lt;/a&gt;. I used the
information from Wikipedia and some LibreOffice Calc functions to make this
csv file, and some hand-munging for the double-long episodes.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;="s" &amp;amp; TEXT(A2,"\00") &amp;amp; "e" &amp;amp; TEXT(C2,"00") &amp;amp; " - " &amp;amp; REGEX($D2,"[,!']","")
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I'm a bit obsessive about removing commas, exclamation marks, question marks,
and quote marks from my filenames. Inspect the saved files and rename each one
to the filename string from the csv that corresponds to the correct episode.
To add the mkv metadata including airdate, and next and previous episodes, run
the next script on the directory. This does not currently recurse into
subdirectories.&lt;/p&gt;
&lt;div class="code"&gt;&lt;pre class="code literal-block"&gt;&lt;span class="nv"&gt;time&lt;/span&gt; &lt;span class="nv"&gt;tv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;mkv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;helper&lt;/span&gt;.&lt;span class="nv"&gt;py&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nv"&gt;inputcsv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/mnt/public/Video/TV/Star Trek The Next Generation (1987)/STTNG.csv&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;d&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;mnt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;public&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;Video&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nv"&gt;temp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;&lt;a href="https://b3n.org/automatic-ripping-machine/"&gt;Automatic Ripping Machine&lt;/a&gt; is
just too fully-featured for me.&lt;/p&gt;
&lt;h3&gt;References&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://jellyfin.org/docs/general/server/media/shows.html"&gt;Jellyfin TV show naming scheme&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Scripts&lt;/h2&gt;
&lt;h3&gt;handbrake.sh&lt;/h3&gt;
&lt;p&gt;My handbrake.sh wrapper reads the disc contents to learn the disc title and
the number of video tracks longer than 125 seconds.&lt;/p&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-1"&gt;&lt;code data-line-number=" 1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-2"&gt;&lt;code data-line-number=" 2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# startdate: 2021-03-10 11:36&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-3"&gt;&lt;code data-line-number=" 3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Alternatives:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-4"&gt;&lt;code data-line-number=" 4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#   handbrake preset: /mnt/public/Support/Programs/DVDs/1920x1080.json&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-5"&gt;&lt;code data-line-number=" 5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-6"&gt;&lt;code data-line-number=" 6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sr0 &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;export&lt;/span&gt; INPUT
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-7"&gt;&lt;code data-line-number=" 7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;test&lt;/span&gt; -z &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/mnt/public/Video/temp &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;export&lt;/span&gt; OUTPUT
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-8"&gt;&lt;code data-line-number=" 8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-9"&gt;&lt;code data-line-number=" 9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;raw&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; HandBrakeCLI --markers --format mkv --min-duration &lt;span class="m"&gt;125&lt;/span&gt; --scan --input &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; --output &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  --encoder x264 --rate &lt;span class="m"&gt;30&lt;/span&gt; --native-language eng --title &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-10"&gt;&lt;code data-line-number="10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;disctitle&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;raw&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; sed -n -r -e &lt;span class="s1"&gt;'/DVD Title:/{s/.*DVD Title: //;p}'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-11"&gt;&lt;code data-line-number="11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;raw&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; grep -E &lt;span class="s1"&gt;'^\s*\+'&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="s1"&gt;'BEGIN{x=0} /title [0-9]/{gsub(":","",$NF);x++;title[x]=$NF} /kbps/{audio[x]=audio[x]""$2} !/subtitle tracks:/ &amp;amp;&amp;amp; !/\+ [0-9]+,/ {us=0} /subtitle tracks:/{us=1} us == 1 &amp;amp;&amp;amp; $2 ~ /[0-9]+,/{subtitle[x]=subtitle[x]""$2} END {for(i in title) {{print title[i],audio[i],subtitle[i]}}}'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-12"&gt;&lt;code data-line-number="12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;array&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; awk -v &lt;span class="s2"&gt;"disctitle=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;disctitle&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; -v &lt;span class="s2"&gt;"input=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;INPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; -v &lt;span class="s2"&gt;"output=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;OUTPUT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s1"&gt;'{a=$1;b=$2;c=$3;print "HandBrakeCLI --markers --format mkv --min-duration 125 --input "input" --output "output"/"disctitle"_V"a".mkv --encoder x264 --rate 30 --native-language eng --title "a" --audio "b" --subtitle "c"scan --native-language eng --mixdown 6ch --aencoder ffaac"}'&lt;/span&gt; &lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-13"&gt;&lt;code data-line-number="13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;commands&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;My hard-coded values include outputting to mkv, and x264 video encoding, and
30 bps, with English language. I also tell it to use the specific audio
encoder ffaac which was the first one I tried when trying to get my 6-channel
mixdown (that's 5.1 surround sound) option to work. I'm not a media bitrate
snob; just trying to preserve some semblance of fancier file value than I can
even consume, should I ever upgrade my viewing equipment in the next 40 years.&lt;/p&gt;
&lt;h3&gt;tv-mkv-helper.py&lt;/h3&gt;
&lt;div class="code"&gt;&lt;table class="codetable"&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-1"&gt;&lt;code data-line-number="  1"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/usr/bin/env python3&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-2"&gt;&lt;code data-line-number="  2"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Startdate: 2021-08-07&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-3"&gt;&lt;code data-line-number="  3"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Purpose: given INCSV="/mnt/public/Video/TV/Star Trek The Next Generation 1987)/STTNG.csv"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-4"&gt;&lt;code data-line-number="  4"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    with columns s, ep, sep, title, airdate, filename,&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-5"&gt;&lt;code data-line-number="  5"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    update files in provided directory, whose name matches the filename column, with the mkv properties&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-6"&gt;&lt;code data-line-number="  6"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Usage:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-7"&gt;&lt;code data-line-number="  7"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    time tv-mkv-helper.py --inputcsv "/mnt/public/Video/TV/Star Trek The Next Generation (1987)/STTNG.csv" -d /mnt/public/Video/temp/&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-8"&gt;&lt;code data-line-number="  8"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# References:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-9"&gt;&lt;code data-line-number="  9"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    /mnt/public/Support/Programs/DVDs/handbrake-internal.sh&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-10"&gt;&lt;code data-line-number=" 10"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dependencies:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-11"&gt;&lt;code data-line-number=" 11"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    STTNG.csv sorted ascending, with columns s, sep, title, airdate, filename&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-12"&gt;&lt;code data-line-number=" 12"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;#    mkvpropedit&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-13"&gt;&lt;code data-line-number=" 13"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-14"&gt;&lt;code data-line-number=" 14"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-15"&gt;&lt;code data-line-number=" 15"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-16"&gt;&lt;code data-line-number=" 16"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;###############################################################&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-17"&gt;&lt;code data-line-number=" 17"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_file_to_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-18"&gt;&lt;code data-line-number=" 18"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;episode_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-19"&gt;&lt;code data-line-number=" 19"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"r"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-20"&gt;&lt;code data-line-number=" 20"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;csv_reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-21"&gt;&lt;code data-line-number=" 21"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_reader&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-22"&gt;&lt;code data-line-number=" 22"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-23"&gt;&lt;code data-line-number=" 23"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-24"&gt;&lt;code data-line-number=" 24"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;# sanity check for the columns we want&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-25"&gt;&lt;code data-line-number=" 25"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;"s"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-26"&gt;&lt;code data-line-number=" 26"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inputcsv needs column named 's' for season number."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-27"&gt;&lt;code data-line-number=" 27"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;#elif "ep" not in headers:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-28"&gt;&lt;code data-line-number=" 28"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="c1"&gt;#   error_string = "Inputcsv needs column named 'ep' for episode number."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-29"&gt;&lt;code data-line-number=" 29"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="s2"&gt;"sep"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-30"&gt;&lt;code data-line-number=" 30"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inputcsv needs column named 'sep' for season episode number."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-31"&gt;&lt;code data-line-number=" 31"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="s2"&gt;"airdate"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-32"&gt;&lt;code data-line-number=" 32"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inputcsv needs column named 'airdate'."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-33"&gt;&lt;code data-line-number=" 33"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="s2"&gt;"filename"&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-34"&gt;&lt;code data-line-number=" 34"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Inputcsv needs column named 'filename'."&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-35"&gt;&lt;code data-line-number=" 35"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;error_string&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-36"&gt;&lt;code data-line-number=" 36"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-37"&gt;&lt;code data-line-number=" 37"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-38"&gt;&lt;code data-line-number=" 38"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-39"&gt;&lt;code data-line-number=" 39"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-40"&gt;&lt;code data-line-number=" 40"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csv_reader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-41"&gt;&lt;code data-line-number=" 41"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-42"&gt;&lt;code data-line-number=" 42"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;ep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-43"&gt;&lt;code data-line-number=" 43"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;episode_array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-44"&gt;&lt;code data-line-number=" 44"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;episode_array&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-45"&gt;&lt;code data-line-number=" 45"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-46"&gt;&lt;code data-line-number=" 46"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;############################################################&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-47"&gt;&lt;code data-line-number=" 47"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_directory_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-48"&gt;&lt;code data-line-number=" 48"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-49"&gt;&lt;code data-line-number=" 49"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;episodes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_file_to_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-50"&gt;&lt;code data-line-number=" 50"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;episodes&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-51"&gt;&lt;code data-line-number=" 51"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Aborting."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-52"&gt;&lt;code data-line-number=" 52"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-53"&gt;&lt;code data-line-number=" 53"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# simple one-level down method. This might be insufficient someday.&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-54"&gt;&lt;code data-line-number=" 54"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-55"&gt;&lt;code data-line-number=" 55"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".mkv"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-56"&gt;&lt;code data-line-number=" 56"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"----------------------"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-57"&gt;&lt;code data-line-number=" 57"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Checking file &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-58"&gt;&lt;code data-line-number=" 58"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;filename_sans_ext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;splitext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-59"&gt;&lt;code data-line-number=" 59"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="c1"&gt;# loop through episodes to find this file&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-60"&gt;&lt;code data-line-number=" 60"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="c1"&gt;# need enumerate, per https://stackoverflow.com/questions/1011938/loop-that-also-accesses-previous-and-next-values/1011962#1011962&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-61"&gt;&lt;code data-line-number=" 61"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;episodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-62"&gt;&lt;code data-line-number=" 62"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;         &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ep&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;episodes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-63"&gt;&lt;code data-line-number=" 63"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-64"&gt;&lt;code data-line-number=" 64"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'filename'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;filename_sans_ext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-65"&gt;&lt;code data-line-number=" 65"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-66"&gt;&lt;code data-line-number=" 66"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;previous&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;episodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'filename'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-67"&gt;&lt;code data-line-number=" 67"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-68"&gt;&lt;code data-line-number=" 68"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;next_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;episodes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'filename'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-69"&gt;&lt;code data-line-number=" 69"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               &lt;span class="n"&gt;fix_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-70"&gt;&lt;code data-line-number=" 70"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-71"&gt;&lt;code data-line-number=" 71"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'filename'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-72"&gt;&lt;code data-line-number=" 72"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;season&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'s'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-73"&gt;&lt;code data-line-number=" 73"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;seasonep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sep'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-74"&gt;&lt;code data-line-number=" 74"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;next_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;next_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-75"&gt;&lt;code data-line-number=" 75"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;prev_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;previous&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-76"&gt;&lt;code data-line-number=" 76"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;                  &lt;span class="n"&gt;airdate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'airdate'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-77"&gt;&lt;code data-line-number=" 77"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;               &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-78"&gt;&lt;code data-line-number=" 78"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-79"&gt;&lt;code data-line-number=" 79"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;############################################&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-80"&gt;&lt;code data-line-number=" 80"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fix_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;season&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;seasonep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;airdate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;next_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-81"&gt;&lt;code data-line-number=" 81"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"Please fix &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; to have"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-82"&gt;&lt;code data-line-number=" 82"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"title: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-83"&gt;&lt;code data-line-number=" 83"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"season: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;season&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-84"&gt;&lt;code data-line-number=" 84"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"seasonep: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;seasonep&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-85"&gt;&lt;code data-line-number=" 85"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"airdate: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;airdate&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-86"&gt;&lt;code data-line-number=" 86"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"next_name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;next_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-87"&gt;&lt;code data-line-number=" 87"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"prev_name: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prev_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-88"&gt;&lt;code data-line-number=" 88"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next_name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;next_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".mkv"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-89"&gt;&lt;code data-line-number=" 89"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;next_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;next_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".mkv"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-90"&gt;&lt;code data-line-number=" 90"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;".mkv"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-91"&gt;&lt;code data-line-number=" 91"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;prev_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;".mkv"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-92"&gt;&lt;code data-line-number=" 92"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;date_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;airdate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;"T12:00:00Z"&lt;/span&gt; &lt;span class="c1"&gt;# just set it to noon UTC, so the EST/EDT time will still be the same day.&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-93"&gt;&lt;code data-line-number=" 93"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;#cmd_string = f"mkvpropedit --set 'title={title}' --set 'date={date_string}' --set 'segment-filename={filename}.mkv' --set 'prev-filename={prev_name}' --set 'next-filename={next_name}'"&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-94"&gt;&lt;code data-line-number=" 94"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;cmd_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mkvpropedit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'title=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'date=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;date_string&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'segment-filename=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'prev-filename=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prev_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--set"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s1"&gt;'next-filename=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;next_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-95"&gt;&lt;code data-line-number=" 95"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cmd_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-96"&gt;&lt;code data-line-number=" 96"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-97"&gt;&lt;code data-line-number=" 97"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;aux_cmd_array&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"mkvpropedit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--delete"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-98"&gt;&lt;code data-line-number=" 98"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next_name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;next_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-99"&gt;&lt;code data-line-number=" 99"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;aux_cmd_array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"next-filename"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-100"&gt;&lt;code data-line-number="100"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;prev_name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-101"&gt;&lt;code data-line-number="101"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;aux_cmd_array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"prev-filename"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-102"&gt;&lt;code data-line-number="102"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="c1"&gt;# if we added anything to the auxiliary command array, then run it&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-103"&gt;&lt;code data-line-number="103"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aux_cmd_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"--delete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-104"&gt;&lt;code data-line-number="104"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aux_cmd_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-105"&gt;&lt;code data-line-number="105"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;      &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-106"&gt;&lt;code data-line-number="106"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-107"&gt;&lt;code data-line-number="107"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="c1"&gt;# argparse stuff&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-108"&gt;&lt;code data-line-number="108"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;argparse&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-109"&gt;&lt;code data-line-number="109"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;parser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;argparse&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ArgumentParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-110"&gt;&lt;code data-line-number="110"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-i"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--inputcsv"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Episode CSV, with columns s, sep, title, filename, airdate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-111"&gt;&lt;code data-line-number="111"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"-d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"--directory"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;help&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Path to directory where files should be given metadata"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-112"&gt;&lt;code data-line-number="112"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse_args&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-113"&gt;&lt;code data-line-number="113"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-114"&gt;&lt;code data-line-number="114"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-115"&gt;&lt;code data-line-number="115"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-116"&gt;&lt;code data-line-number="116"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-117"&gt;&lt;code data-line-number="117"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"__main__"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-118"&gt;&lt;code data-line-number="118"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;"running with inputcsv=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, directory=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="linenos linenodiv"&gt;&lt;a href="https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/#-119"&gt;&lt;code data-line-number="119"&gt;&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;&lt;td class="code"&gt;&lt;code&gt;   &lt;span class="n"&gt;fix_directory_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;inputcsv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;
&lt;p&gt;In a departure from my normal style where I put all the functions in a library
and call it, I wanted a self-contained script with the argument parsing. It
was quick and dirty. And all I'm doing is adding the 3 or 4 mkv attributes to
the mkv files whose filename matches an entry in the csv. I do all this using
a custom csv, because I'm too lazy to learn how to use some fancy TheTVDB api
or whatever. I'm obsessive enough to be fine with manually scraping metadata
from Wikipedia tv show episode lists.&lt;/p&gt;</description><category>handbrake</category><category>jellyfin</category><category>media</category><category>metadata</category><category>mkv</category><category>notes</category><category>video</category><guid>https://bgstack15.ddns.net/blog/posts/2021/08/12/my-dvd-ripping-solution/</guid><pubDate>Thu, 12 Aug 2021 13:14:52 GMT</pubDate></item><item><title>Convert vhs video tape to mkv file in Linux</title><link>https://bgstack15.ddns.net/blog/posts/2019/07/17/convert-vhs-video-tape-to-mkv-file-in-linux/</link><dc:creator>bgstack15</dc:creator><description>&lt;h6&gt;Last updated 2019-09-11&lt;/h6&gt;
&lt;p&gt;I still own video tapes (VHS) and I have finally gotten around to getting a
nice setup for saving them down to hard disk so I can clear out the old video
tape collection. This is how I did it. First of all, I knew I needed an RCA-
to-something adapter. I found an "&lt;a href="https://www.amazon.com/UCEC-Capture-Adapter-Converter-support/dp/B00WSAWZ1M/ref=sr_1_8?crid=100QJKR988Z8K&amp;amp;keywords=av+to+usb+converter&amp;amp;qid=1561291750&amp;amp;s=gateway&amp;amp;sprefix=av+to+usb+%2Caps%2C162&amp;amp;sr=8-8"&gt;AV to USB
converter&lt;/a&gt;"
[amazon.com] that does the trick. When attached to a Ubuntu 16.04 system, it
shows up as /dev/video0. No additional steps required! To quote &lt;a href="http://thealaskalinuxuser.com/"&gt;one of my
role models&lt;/a&gt; [thealaskalinuxuser.com] on the
Internet: "Linux -- keep it simple." Now, I discovered over time that the
audio input just didn't work. But the video comes in perfectly! I was using
&lt;a href="https://www.videolan.org/vlc/"&gt;vlc&lt;/a&gt; [videolan.org] for the input capture. To
get the audio to work, I had to find an RCA to mini-phono cable which I
already owned. An example product is &lt;a href="https://www.monoprice.com/product?p_id=5597"&gt;on
monoprice.com&lt;/a&gt; [monoprice.com]. I
also had to fiddle with the audio input settings to get the input to work
right. I had to poke around with pulseaudio, alsa, and vlc to get the audio
input to work the way I needed it. For my setup (pictured below), I needed to
make sure my input source was mic (the front jack on my desktop computer) and
not line, which is probably the input in the back. I chose to set my mic boost
(akin to gain) really low, and capture volume really high.
&lt;img alt="" src="https://bgstack15.ddns.net/blog/2019/07/convert-vhs-setup.jpg"&gt;
&lt;img alt="screenshot of alsa mixer on capture settings
screen" src="https://bgstack15.ddns.net/blog/2019/06/alsamixer-capture.png"&gt; I
needed to set pulseaudio to allow the stereo input. I have discovered that
pulseaudio is fragile, and also never remembers the settings I choose for it,
so for every reboot or login or pulseaudio --start command, I have to go
readjust the "profile." I am starting to understand why people smarter (and
more verbose) than me tend to dislike pulseaudio. &lt;img alt="pavucontrol showing
configuration" src="https://bgstack15.ddns.net/blog/2019/06/pavucontrol.png"&gt;
With alsa and pulse set up correctly, it is now a matter of getting vlc to
accept the audio input while accepting the video input. I had to discover how
my system identifies the audio jack.&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arecord&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="o"&gt;****&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CAPTURE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Hardware&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Devices&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;****&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HDA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Intel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCH&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CX20641&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Analog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CX20641&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Analog&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;Subdevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;HDA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Intel&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;PCH&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;CX20641&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Analog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;CX20641&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Alt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Analog&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;Subdevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USB20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;TO&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USB2&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;USB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Audio&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;USB&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Audio&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;Subdevices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;subdevice&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;By trial and error, I learned the mic input is card 0, device 2. In alsa
terms, that's alsa://0,2. So, to put it all together, I had to set VLC to open
a "capture device" of /dev/video0, with audio device of hw:0,2. To get the
audio and video to both be output by VLC, I had to go into advanced optiosn
and se audio input = 0. &lt;img alt="screenshot of vlc with /dev/video0, hw:0,2 and audio
input=0" src="https://bgstack15.ddns.net/blog/2019/06/vlc-settings-2.png"&gt; VLC
always defaults to audio input=-1, so no audio will come through. When I
selected the Play button, it presents both audio and video from the VCR! So,
with the video on the screen that I want, I pressed the record button (from
the toolbar visible when you select View -&amp;gt; Advanced controls). VLC records by
default to avi format, which is not my preferred method, even though it is a
temporary format. So, I had to set all the settings again, and then select the
drop-down arrow beside the Play button, and select "Convert." A new window
appears, and I select the file format I want and the output file.
&lt;img alt="" src="https://bgstack15.ddns.net/blog/2019/06/convert-options.png"&gt; With
all the options set, I now return to the first options screen and select the
"Convert" button. After running through the whole video, I come back and hit
stop in VLC. I use &lt;a href="https://handbrake.fr/"&gt;HandBrake&lt;/a&gt; [handbrake.fr] to
convert the file to the format I want. The details of that are beyond the
scope of this post. For a bonus, I discovered that killing vlc safely closes
the written file, so it is still viewable. So I just run a command in a
terminal to kill vlc after the published length of the videotape:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$ sleep &lt;span class="k"&gt;$((&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="m"&gt;120&lt;/span&gt; &lt;span class="k"&gt;))&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; killall vlc
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I could have done something fancier with xdotool to select the "stop" button,
but why bother?&lt;/p&gt;
&lt;h4&gt;Addendum&lt;/h4&gt;
&lt;p&gt;For some reason, when I capture video (possibly because of the &lt;a href="https://en.wikipedia.org/wiki/NTSC#Frame_rate_conversion"&gt;NTSC
framerate&lt;/a&gt;
conversation), the audio gets a little bit out of sync with the video.
Thankfully, there is a tool that can change the scale of the audio to video:
mkvmerge, which is a part of
&lt;a href="https://mkvtoolnix.download/doc/mkvmerge.html"&gt;mkvtoolnix&lt;/a&gt; suite. After much
experimentation, I am satisfied that a safe number to use to scale the audio
perfectly from my VCR for all content is in this command:&lt;/p&gt;
&lt;pre class="code literal-block"&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;mkvmerge -y '1:0,100.060552/100' -o new.mkv old.mkv
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That is take stream 1 (zero-indexed, and usually the audio in a simple
captured video file) and stretch it with an anchor point of zero to
100.060552% of the original speed. So it slows down the audio, and then the
audio syncs perfectly with the video, for a 2-hour movie.&lt;/p&gt;</description><category>audio</category><category>convert</category><category>mkv</category><category>record</category><category>video</category><guid>https://bgstack15.ddns.net/blog/posts/2019/07/17/convert-vhs-video-tape-to-mkv-file-in-linux/</guid><pubDate>Wed, 17 Jul 2019 13:05:22 GMT</pubDate></item></channel></rss>