Archiving VCR or any other
RCA media
After my Father passed away, I volunteered to archive his Video
Cassette Recorder (VCR) collection to disk for the family. You might
be aware that Europe used Phase Alternating Line (PAL) is
a colour encoding system for
analog
television. It was one of three major analogue colour television
standards, the others being
NTSC and
Ireland used PAL-I, a version based on CCIR System I,
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.
Hardware
RSAConnector to your media device
RSA2HDMIcard.
HDMI to USB CaptureCard.
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.
Connection
First drop to a console and list the connected usb devices
$ lsusb | sort | tee before.txt
Connect the VCR with RSA Cables to the AV2HDMI converter.Connect the AV2HDMI converter with a HDMI cable to the HDMI2USBconverter.
Connect the HDMI2USB converter to a Linux PC with a usb cable.After waiting a few seconds, you can list the usb devices again and
do a diff to see which has been added.
$ lsusb | sort | tee after.txt
$ diff before.txt after.txt
11a12
> Bus 003 Device 021: ID 534d:2109 MacroSilicon USB Video
While we know the USB device ID, we now need to know if/how the
hardware is mapped into Linux.
We need a way to be able to identify which /dev/video?
device I need to capture from.
First unplug the HDMI2USB capture card, and get a list of the video
$ for i in /sys/class/video4linux/video*/device/uevent ;do echo "${i} ===";cat "${i}";done | tee before.txt
Plug back in the card and give it a few seconds to be recognised.
Then run the same command and diff the output to see the
$ for i in /sys/class/video4linux/video*/device/uevent ;do echo "${i} ===";cat "${i}";done | tee after.txt
$ diff before.txt after.txt
28a29,42
> /sys/class/video4linux/video4/device/uevent ===
> DEVTYPE=usb_interface
> DRIVER=uvcvideo
> PRODUCT=534d/2109/2100
> TYPE=239/2/1
> INTERFACE=14/1/0
> MODALIAS=usb:v534Dp2109d2100dcEFdsc02dp01ic0Eisc01ip00in00
> /sys/class/video4linux/video5/device/uevent ===
> DEVTYPE=usb_interface
> DRIVER=uvcvideo
> PRODUCT=534d/2109/2100
> TYPE=239/2/1
> INTERFACE=14/1/0
> MODALIAS=usb:v534Dp2109d2100dcEFdsc02dp01ic0Eisc01ip00in00
In my case I'm interested in the PRODUCT=534d/2109/2100.
From which we can find the changing path, which in this case is
/sys/class/video4linux/video5/
Similarly we also need to know which ALSA Audio Device it
Again unplug the HDMI2USB capture card, and get a list of the audio
$ arecord -l | tee before.txt
Plug back in the card and give it a few seconds to be recognised.
Then run the same command and diff the output to see the
$ arecord -l | tee after.txt
$ diff before.txt after.txt
7a8,10
> card 2: MS2109 [MS2109], device 0: USB Audio [USB Audio]
> Subdevices: 1/1
> Subdevice #0: subdevice #0
In my case it reports as MS2109 from which we can find
Software
Due to the limitations of
this brand of video capture we need to force capture to use mjpg format at 30
Select Open Media > Capture Devices Select Video Device Name to
the video device you found above. So as an example
/dev/video4 Also set the "Audio device name" to the alsa
Once audio and video were working, I switched to using ffmpeg as I'm more comfortable scripting
Bash script
This is very much a "me" script, so edit it to your hardware and
#!/bin/bash
Copyright Ken Fallon 2024 (c) "No Rights Reserved"
Released to the Public Domain via Creative Commons 0
https://creativecommons.org/public-domain/cc0/
video_device="$( grep -l 'PRODUCT=534d/2109/2100' /sys/class/video4linux/video*/device/uevent | \
head -1 | \
awk -F '/' '{print $5}' )"
video_device_path="/dev/${video_device}"
if [ -z "${video_device}" ]
then
echo "ERROR: Cannot find the HDMP2USB stick video stream" 1>&2
exit 1
else
echo "INFO: Found the HDMP2USB stick video on \"${video_device_path}\"" 1>&2
fi
audio_device_id="$( arecord -l | grep 'MS2109' | awk -F 'card |:' '{print $2}' )"
if [ -z "${audio_device_id}" ]
then
echo "ERROR: Cannot find the HDMP2USB stick audio stream" 1>&2
exit 1
else
echo "INFO: Found the HDMP2USB stick audio on \"${audio_device_id}\"" 1>&2
fi
ffmpeg \
-f v4l2 \
-framerate 30 \
-video_size 720x480 \
-input_format mjpeg \
-thread_queue_size 512 \
-i "${video_device_path}" \
-f alsa \
-i hw:"${audio_device_id}" \
-c:v copy \
-c:a flac \
output-flac.mkv
The break down of the ffmpeg options are as follows, for
more information see man ffmpeg or view online man pages.
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 "ntsc", corresponding to a frame rate of "30000/1001".
-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 "copy" (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 "c" 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.
We used the v4l2 for the Video4Linux format.
A frame rate of 30, and input format of mjpg which are limitations of the
card. Given the source PAL-I has 625
lines, a video_size of 720x480 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 flac.
I just want to dump the incoming stream to a file so that it can be
Recording
for vcr in {0..113}; do ;-)
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
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
I used the timeout command to run a
command with a time limit
This would prevent already massive files filling the disk with hours
timeout --preserve-status --kill-after=5m --verbose 210m record-720x480.bash
Problems
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.
With each hour of recording coming in at 6.6G, some tapes lead to 60G
encrypted disk was struggled with the huge files that were been
So keeping it simple I called out my HP t610
Flexible Thin Client with 2nd hand 1T hard disk, and set it up with
a clean install of Debian.
This fixed the issue and allowed me to get consistent recordings, all
be it in a not so handy format.
Post processing
scrubb
forward and back, to see if there was anything recorded on the tapes.
Unfortunately the mkv flac/mjpeg format doesn't allow
scrubbing,
so the recorded media first needed to be transcoded to a format that did
allow scrubbing, but also reduced the file size dramatically.
By specifying the filename as next this command converted the media
to mp4. ffmpeg -i ${next} ${next%.*}.mp4
This reduces the size by about 50%.
Once converted this allowed me to use LosslessCut The Swiss Army
Knife of Lossless Video/Audio Editing, to quickly preview and cut out
the sections I needed without having to reprocess everything.
flatpak run no.mifi.losslesscut
Links
The following are the links I gathered while compiling this project.
Most are from searching for the usb id into a search engine
https://en.wikipedia.org/wiki/RCA_connectorhttps://www.amazon.de/dp/B0CJQX2H9Shttps://www.bol.com/nl/nl/p/mini-hdmi2av-up-scaler-1080p/9300000030484510/https://github.com/yume-chan/ms2109-playerhttps://ciko.io/posts/cheap_usb_hdmi/https://www.baeldung.com/linux/ffmpeg-webcam-stream-videohttps://recolic.net/blog/post/macrosilicon-ms2109-hdmi-to-usb-capture-not-working-on-linuxhttps://superuser.com/questions/1838120/how-to-specify-audio-input-to-ffplayhttps://opensource.com/article/17/6/ffmpeg-convert-media-file-formatshttps://shotstack.io/learn/how-to-use-ffmpeg/https://blog.trixpark.com/live-streaming-with-ffmpeg-a-comprehensive-guide-with-examples/https://www.diyaudio.com/community/threads/macrosilicon-2109-cheap-usb-hdmi-a-v-capture.357873/https://forum.videohelp.com/threads/404784-%5BSolved%5DUSB-capture-device-stuck-on-10-fps