It has become increasingly apparent that VHS Tapes that inherently fragile, prone to mold, and urgently require capturing to a digital file format.
Equipment:
VCR - JVC HR-S9500
DVD Recorder (for Passthrough) - Panasonic DMR-E50
USB Capture Device - Hauppauge USB-Live2
The ideal VCR to use for this project is an S-VHS VCR with an S-Video output. I picked a JVC HR-S9500 which met these requirements and also had a built in Timebase corrector (TBC).
If you can't find a VCR with a TBC, I'd recommend purchasing a Panasonic DVD Recorder from the mid 2000's era as these have "Frame adjusters" which work in a similar manner to a TBC and can be quite effective at producing a clean output for your capture card.
For the capture card, I tried 3 devices:
I tried the EasyCAP first as it was one that I had lying about and found the results to be incredibly poor and unusable with a low frame rate, lack of detail, and overly saturated colours. Frankly, it was only worth throwing in the bin!
I had a Dazzle DVC-100 USB Capture Device available to me by a relative. Unfortunately, while the picture quality was OK, the audio was out of sync when capturing on Linux. It was possible to use the device on Windows with VirtualDub but I did not want to do this.
Finally, I went on Amazon and bought a Hauppauge USB-Live2 for a reasonable price of £32 (At the time of writing). While you could pay more for a capture card, I do think the return on results would diminish after this point (especially considering we are dealing with VHS tapes which were never fantastic quality to begin with!)
The first stage of this process is to capture the raw interlaced video from the capture card. For the video codec, I have written a bash script to handle all of my requirements for the process:
#!/bin/bash
# VCR Capture Script for a Hauppage! USB-Live2
# === Declarations ===
videosource="/dev/video2"
audiosource="hw:3"
VideoStandard=5
START_TIME="00:00:00"
RecordTime="02:00:00" # 2 Hours for SP
VIDEO_INPUT=1 #1 for S-Video
VIDEO_WIDTH=768
VIDEO_HEIGHT=576
PIXEL_FORMAT="YUYV"
#=== Configure Capture Card ===
#Set to PAL-I
v4l2-ctl -d $videosource -s PAL-I
#Set the Input to S-Video for the USB-Live2 Card
v4l2-ctl -d $videosource --set-input=$VIDEO_INPUT --set-fmt-video=width=$VIDEO_WIDTH,height=$VIDEO_HEIGHT,pixelformat=$PIXEL_FORMAT --set-ctrl=mute=0
#=== Capture raw and lossless ===
#Determine the filename for the raw file
Filename=$(date +%Y%m%d_%H%M%S)
~/nvidia/ffmpeg/ffmpeg -ar 48000 -f alsa -thread_queue_size 1024 -i $audiosource -f v4l2 -ts abs -channel $VIDEO_INPUT -video_size $VIDEO_WIDTH'x'$VIDEO_HEIGHT -pix_fmt rgb565be -thread_queue_size 1024 -i $videosource -c:v huffyuv -level 3 -g 1 -aspect 4:3 -flags +ilme+ildct -aspect 4:3 -pix_fmt yuv422p -aspect 4:3 -c:a pcm_s16le $Filename.avi
Not only does this script handle the capturing of the video, but it also ensures that the capture card is configured to suit my requirements (e.g. Using S-Video instead of defaulting to Composite, PAL Format)
To transcode the video, I wrote a bash script which will loop through a directory of AVI files and deinterlace and upscale outputting to an MP4 File:
#!/bin/bash
# VHS/Hi8 Deinterlace and Upscale Script
# William Wright M6WIQ
# === Declarations ===
# See https://ffmpeg.org/ffmpeg-filters.html for information,
# remove overscan:
FIELDORDER="tff"
CROP_FRAME="crop=(iw-10):(ih-14):3:0, pad=iw+10:ih+14:(ow-iw)/2:(oh-ih)/2"
# noise reduction
NOISE_REDUCTION="nlmeans=1.0:7:5:3:3"
SHARPEN="unsharp=3:3:1"
DEINTERLACE="bwdif=mode=1:parity=$FIELDORDER:deint=all"
# upscale
SCALING="zscale=w=960:h=720:filter=bicubic"
TRANSCODE_VIDEO_FILTERS="fieldorder=$FIELDORDER,$DEINTERLACE,$NOISE_REDUCTION,$SCALING,$SHARPEN,$CROP_FRAME,setsar=1:1"
PIXEL_FORMAT="yuv420p"
VIDEO_CODEC="hevc_nvenc" #hevc_nvenc
AUDIO_CODEC="aac"
DEINTERLACED_FRAMERATE=50
RC_MODE="vbr"
mkdir output
for f in *.avi
do
OUTPUT="output/${f%.*}_%03d.mp4"
# Check to see if file exists
if [ -f "$OUTPUT" ]; then
echo "$OUTPUT exists."
else
echo "$OUTPUT does not exist."
echo "Converting $f..."
~/nvidia/ffmpeg/ffmpeg -hwaccel cuda -hwaccel_output_format cuda -threads 8 -i "$f" -standard PAL -aspect 4:3 -r $DEINTERLACED_FRAMERATE -c:v $VIDEO_CODEC -rc $RC_MODE -crf 23 -b:v 0 -filter:v "$TRANSCODE_VIDEO_FILTERS" -pix_fmt $PIXEL_FORMAT -movflags +faststart -c:a $AUDIO_CODEC -b:a 256k -hide_banner "$OUTPUT"
done
Essentially, the script functions break down into:
To see the results of this, I have uploaded some of the videos to Youtube...
A simple way to handle the capturing and processing of over 50+ Hours of old VHS Tapes to preserve for the future.
I am extremely grateful for the various sources on the Web which assisted me in developing this process, such as:
LinuxTV.org V4L Capture Script
SuperUser - ffmpeg settings for VHS mpeg2/mp2 to H264/MP4 VBR conversion and reducing file size