<h1 id="archiving-vcr-or-any-other-rca-media">Archiving VCR or any other
RCA media</h1>
<p>After my Father passed away, I volunteered to archive his <a
href="https://en.wikipedia.org/wiki/Videocassette_recorder">Video
Cassette Recorder</a> (VCR) collection to disk for the family. You might
be aware that Europe used <b>Phase Alternating Line</b> (<b>PAL</b>) is
a colour encoding system for
<a href="https://en.wikipedia.org/wiki/Analog_television" title="Analog television">analog
television</a>. It was one of three major analogue colour television
standards, the others being
<a href="https://en.wikipedia.org/wiki/NTSC" title="NTSC">NTSC</a> and
<a href="https://en.wikipedia.org/wiki/SECAM" title="SECAM">SECAM</a>.</p>
<p>Ireland used PAL-I, a version based on <a
href="https://en.wikipedia.org/wiki/CCIR_System_I">CCIR System I</a>,
which meant that none of the VCR players in the Netherlands would work.
So in addition to having to carry 113 Video Cassettes on a RyanAir
Flight, I also needed to bring the Video Player as well.</p>
<h2 id="hardware">Hardware</h2>
<ul>
<li><a href="https://en.wikipedia.org/wiki/RCA_connector">RSA
Connector</a> to your media device</li>
<li><a
href="https://www.bol.com/nl/nl/p/mini-hdmi2av-up-scaler-1080p/9300000030484510/">RSA2HDMI</a>
card.</li>
<li><a href="https://www.amazon.de/dp/B0CJQX2H9S">HDMI to USB Capture
Card</a>.</li>
</ul>
<p>These are the ones I used but I don't recommend them one way or the
other. The parts are fairly generic so use what you can get.</p>
<a href="eps/hpr4185/hpr4185/setup.jpeg">
<img src="eps/hpr4185/hpr4185/setup-thumbnail.jpeg" alt="The setup showing VCR to RSA to HDMI to USB" />
</a>

<h2 id="connection">Connection</h2>
<p>First drop to a console and list the connected usb devices</p>
<p><code>$ lsusb | sort | tee before.txt</code></p>
<ul>
<li>Connect the VCR with RSA Cables to the AV2HDMI converter.</li>
<li>Connect the AV2HDMI converter with a HDMI cable to the HDMI2USB
converter.</li>
<li>Connect the HDMI2USB converter to a Linux PC with a usb cable.</li>
</ul>
<p>After waiting a few seconds, you can list the usb devices again and
do a diff to see which has been added.</p>
<pre><code>$ lsusb | sort | tee after.txt
$ diff before.txt after.txt
11a12
&gt; Bus 003 Device 021: ID 534d:2109 MacroSilicon USB Video</code></pre>
<p>While we know the USB device ID, we now need to know if/how the
hardware is mapped into Linux.</p>
<p>We need a way to be able to identify which <code>/dev/video?</code>
device I need to capture from.</p>
<p>First unplug the HDMI2USB capture card, and get a list of the video
devices.</p>
<pre><code>$ for i in  /sys/class/video4linux/video*/device/uevent ;do echo &quot;${i} ===&quot;;cat &quot;${i}&quot;;done | tee before.txt</code></pre>
<p>Plug back in the card and give it a few seconds to be recognised.
Then run the same command and <code>diff</code> the output to see the
differences.</p>
<pre><code>$ for i in  /sys/class/video4linux/video*/device/uevent ;do echo &quot;${i} ===&quot;;cat &quot;${i}&quot;;done | tee after.txt
$ diff before.txt after.txt
28a29,42
&gt; /sys/class/video4linux/video4/device/uevent ===
&gt; DEVTYPE=usb_interface
&gt; DRIVER=uvcvideo
&gt; PRODUCT=534d/2109/2100
&gt; TYPE=239/2/1
&gt; INTERFACE=14/1/0
&gt; MODALIAS=usb:v534Dp2109d2100dcEFdsc02dp01ic0Eisc01ip00in00
&gt; /sys/class/video4linux/video5/device/uevent ===
&gt; DEVTYPE=usb_interface
&gt; DRIVER=uvcvideo
&gt; PRODUCT=534d/2109/2100
&gt; TYPE=239/2/1
&gt; INTERFACE=14/1/0
&gt; MODALIAS=usb:v534Dp2109d2100dcEFdsc02dp01ic0Eisc01ip00in00
</code></pre>
<p>In my case I'm interested in the <code>PRODUCT=534d/2109/2100</code>.
From which we can find the changing path, which in this case is
<code>/sys/class/video4linux/video5/</code></p>
<p>Similarly we also need to know which ALSA Audio Device it
exposed.</p>
<p>Again unplug the HDMI2USB capture card, and get a list of the audio
devices.</p>
<pre><code>$ arecord -l | tee before.txt
</code></pre>
<p>Plug back in the card and give it a few seconds to be recognised.
Then run the same command and <code>diff</code> the output to see the
differences.</p>
<pre><code>$ arecord -l | tee after.txt
$ diff before.txt after.txt
7a8,10
&gt; card 2: MS2109 [MS2109], device 0: USB Audio [USB Audio]
&gt;   Subdevices: 1/1
&gt;   Subdevice #0: subdevice #0</code></pre>
<p>In my case it reports as <code>MS2109</code> from which we can find
the changing <code>card 2</code></p>
<h2 id="software">Software</h2>
<p>Due to the <a
href="https://github.com/yume-chan/ms2109-player">limitations</a> of
this brand of video capture we need to force capture to use <a
href="https://en.wikipedia.org/wiki/Motion_JPEG">mjpg</a> format at 30
frames per second.</p>
<p>I first used <a href="https://www.videolan.org/vlc/">vlc</a> to test
the capture</p>
<p>Select Open Media &gt; Capture Devices Select Video Device Name to
the video device you found above. So as an example
<code>/dev/video4</code> Also set the "Audio device name" to the alsa
card, eg <code>hw: 2,0:</code></p>
<a href="eps/hpr4185/hpr4185/vlc-settings.png">
<img src="eps/hpr4185/hpr4185/vlc-settings-thumbnail.png" alt="Screenshot of menu detailed above" />
</a>

<p>Once audio and video were working, I switched to using <a
href="https://ffmpeg.org/">ffmpeg</a> as I'm more comfortable scripting
with it.</p>
<h2 id="bash-script">Bash script</h2>
<p>This is very much a "me" script, so edit it to your hardware and
requirements.</p>
<pre><code>#!/bin/bash

Copyright Ken Fallon 2024 (c) &quot;No Rights Reserved&quot;
Released to the Public Domain via Creative Commons 0
https://creativecommons.org/public-domain/cc0/

video_device=&quot;$( grep -l &#39;PRODUCT=534d/2109/2100&#39; /sys/class/video4linux/video*/device/uevent | \
head -1 | \
awk -F &#39;/&#39; &#39;{print $5}&#39; )&quot;
video_device_path=&quot;/dev/${video_device}&quot;
if [ -z &quot;${video_device}&quot; ]
then
  echo &quot;ERROR: Cannot find the HDMP2USB stick video stream&quot; 1&gt;&amp;2
  exit 1
else
  echo &quot;INFO: Found the HDMP2USB stick video on \&quot;${video_device_path}\&quot;&quot; 1&gt;&amp;2
fi

audio_device_id=&quot;$( arecord -l | grep &#39;MS2109&#39; | awk -F &#39;card |:&#39; &#39;{print $2}&#39; )&quot;
if [ -z &quot;${audio_device_id}&quot; ]
then
  echo &quot;ERROR: Cannot find the HDMP2USB stick audio stream&quot; 1&gt;&amp;2
  exit 1
else
  echo &quot;INFO: Found the HDMP2USB stick audio on \&quot;${audio_device_id}\&quot;&quot; 1&gt;&amp;2
fi

ffmpeg \
-f v4l2 \
-framerate 30 \
-video_size 720x480 \
-input_format mjpeg \
-thread_queue_size 512 \
-i &quot;${video_device_path}&quot; \
-f alsa \
-i hw:&quot;${audio_device_id}&quot; \
-c:v copy \
-c:a flac \
output-flac.mkv</code></pre>
<p>The break down of the <code>ffmpeg</code> options are as follows, for
more information see <code>man ffmpeg</code> or view <a
href="https://manpages.org/ffmpeg">online man pages</a>.</p>
<pre><code>SYNOPSIS
ffmpeg [global_options] {[input_file_options] -i input_file} ... {[output_file_options] output_file} ...

-f fmt (input/output)
    Force input or output file format. The format is normally auto detected for input files and guessed from
    the file extension for output files, so this option is not needed in most cases.

-framerate
    Set the grabbing frame rate. Default is &quot;ntsc&quot;, corresponding to a frame rate of &quot;30000/1001&quot;.

-video_size
    Set the video frame size.

-input_format
    Set the preferred pixel format (for raw video) or a codec name. This option allows one to select the input
    format, when several are available.

-thread_queue_size size (input)
    This option sets the maximum number of queued packets when reading from the file or device. With low
    latency / high rate live streams, packets may be discarded if they are not read in a timely manner;
    raising this value can avoid it.

-i filename (input)
    input file name

-f fmt (input/output)
    Force input or output file format. The format is normally auto detected for input files and guessed from
    the file extension for output files, so this option is not needed in most cases.

-c[:stream_specifier] codec (input/output,per-stream)
-codec[:stream_specifier] codec (input/output,per-stream)
    Select an encoder (when used before an output file) or a decoder (when used before an input file) for one
    or more streams. codec is the name of a decoder/encoder or a special value &quot;copy&quot; (output only) to indicate
    that the stream is not to be re-encoded.

    For example

            ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT

    encodes all video streams with libx264 and copies all audio streams.

    For each stream, the last matching &quot;c&quot; option is applied, so

            ffmpeg -i INPUT -map 0 -c copy -c:v:1 libx264 -c:a:137 libvorbis OUTPUT

    will copy all the streams except the second video, which will be encoded with libx264, and the 138th audio,
    which will be encoded with libvorbis.</code></pre>
<p>We used the <code>v4l2</code> for the <a
href="https://en.wikipedia.org/wiki/Video4Linux">Video4Linux</a> format.
A frame rate of <code>30</code>, and input format of <a
href="https://en.wikipedia.org/wiki/Motion_JPEG">mjpg</a> which are <a
href="https://github.com/yume-chan/ms2109-player">limitations</a> of the
card. Given the source <a
href="https://en.wikipedia.org/wiki/CCIR_System_I">PAL-I</a> has 625
lines, a video_size of <code>720x480</code> is reasonable. After ffmpeg
complained, I added thread_queue_size of 512 to help out. Then the rest
is specifying the input for the video, and setting the audio to <a
href="https://en.wikipedia.org/wiki/FLAC">flac</a>.</p>
<p>I just want to dump the incoming stream to a file so that it can be
processed later.</p>
<h2 id="recording">Recording</h2>
<p>for vcr in {0..113}; do ;-)</p>
<p>The intention was to put in a tape in the morning before going to
work. Swap it for another when I got home, and yet another when I went
to bed.</p>
<p>As there was no mechanism to know when the recording was done, I
first checked the length of the tape by Fast Forwarding it to the
end.</p>
<p>I used the <code>timeout</code> command to <a
href="https://www.man7.org/linux/man-pages/man1/timeout.1.html">run a
command with a time limit</a></p>
<p>This would prevent already massive files filling the disk with hours
of static.</p>
<pre><code>timeout --preserve-status --kill-after=5m --verbose 210m record-720x480.bash</code></pre>
<h2 id="problems">Problems</h2>
<p>While it worked fine for some, there was an intermittent problem that
would cause the laptop to freeze. It would eventually recover after a
few days, but I lost a lot of time and couldn't trust the process. I
checked the memory and hard disk, even writing to usb and a nas.</p>
<p>With each hour of recording coming in at 6.6G, some tapes lead to 60G
files.</p>
<p>I suspect that my <a
href="https://en.wikipedia.org/wiki/Linux_Unified_Key_Setup">luks</a>
encrypted disk was struggled with the huge files that were been
produced.</p>
<p>So keeping it simple I called out my <a
href="https://hackerpublicradio.org/eps/hpr4125/index.html">HP t610
Flexible Thin Client</a> with 2nd hand 1T hard disk, and set it up with
a clean install of <a href="https://www.debian.org/">Debian</a>.</p>
<p>This fixed the issue and allowed me to get consistent recordings, all
be it in a not so handy format.</p>
<h2 id="post-processing">Post processing</h2>
<p>I wanted to be able to
<a href="https://en.wikipedia.org/wiki/Scrubbing_(audio)">scrubb</a>
forward and back, to see if there was anything recorded on the tapes.
Unfortunately the mkv flac/mjpeg format doesn't allow
<a href="https://en.wikipedia.org/wiki/Scrubbing_(audio)">scrubbing</a>,
so the recorded media first needed to be transcoded to a format that did
allow scrubbing, but also reduced the file size dramatically.</p>
<p>By specifying the filename as next this command converted the media
to mp4. <code>ffmpeg -i ${next} ${next%.*}.mp4</code></p>
<p>This reduces the size by about 50%.</p>
<p>Once converted this allowed me to use <a
href="https://www.mifi.no/losslesscut/">LosslessCut</a> The Swiss Army
Knife of Lossless Video/Audio Editing, to quickly preview and cut out
the sections I needed without having to reprocess everything.</p>
<p><code>flatpak run no.mifi.losslesscut</code></p>
<h2 id="links">Links</h2>
<p>The following are the links I gathered while compiling this project.
Most are from searching for the usb id into a search engine
"534d:2109".</p>
<ul>
<li><a
href="https://en.wikipedia.org/wiki/RCA_connector">https://en.wikipedia.org/wiki/RCA_connector</a></li>
<li><a
href="https://www.amazon.de/dp/B0CJQX2H9S">https://www.amazon.de/dp/B0CJQX2H9S</a></li>
<li><a
href="https://www.bol.com/nl/nl/p/mini-hdmi2av-up-scaler-1080p/9300000030484510/">https://www.bol.com/nl/nl/p/mini-hdmi2av-up-scaler-1080p/9300000030484510/</a></li>
<li><a
href="https://github.com/yume-chan/ms2109-player">https://github.com/yume-chan/ms2109-player</a></li>
<li><a
href="https://ciko.io/posts/cheap_usb_hdmi/">https://ciko.io/posts/cheap_usb_hdmi/</a></li>
<li><a
href="https://www.baeldung.com/linux/ffmpeg-webcam-stream-video">https://www.baeldung.com/linux/ffmpeg-webcam-stream-video</a></li>
<li><a
href="https://recolic.net/blog/post/macrosilicon-ms2109-hdmi-to-usb-capture-not-working-on-linux">https://recolic.net/blog/post/macrosilicon-ms2109-hdmi-to-usb-capture-not-working-on-linux</a></li>
<li><a
href="https://superuser.com/questions/1838120/how-to-specify-audio-input-to-ffplay">https://superuser.com/questions/1838120/how-to-specify-audio-input-to-ffplay</a></li>
<li><a
href="https://opensource.com/article/17/6/ffmpeg-convert-media-file-formats">https://opensource.com/article/17/6/ffmpeg-convert-media-file-formats</a></li>
<li><a
href="https://shotstack.io/learn/how-to-use-ffmpeg/">https://shotstack.io/learn/how-to-use-ffmpeg/</a></li>
<li><a
href="https://blog.trixpark.com/live-streaming-with-ffmpeg-a-comprehensive-guide-with-examples/">https://blog.trixpark.com/live-streaming-with-ffmpeg-a-comprehensive-guide-with-examples/</a></li>
<li><a
href="https://www.diyaudio.com/community/threads/macrosilicon-2109-cheap-usb-hdmi-a-v-capture.357873/">https://www.diyaudio.com/community/threads/macrosilicon-2109-cheap-usb-hdmi-a-v-capture.357873/</a></li>
<li><a
href="https://forum.videohelp.com/threads/404784-%5BSolved%5DUSB-capture-device-stuck-on-10-fps">https://forum.videohelp.com/threads/404784-%5BSolved%5DUSB-capture-device-stuck-on-10-fps</a></li>
</ul>
