Saving Your Analog Data from Oblivion

Audio Cleanup

When you capture the audio of a VHS tape with the process outlined here, it is likely to be noticeably noisy. In addition to the noise contained in the VHS and generated by the VCR (see the box titled "Removing Audio Noise from Old VHS Tapes" ), the capture card also produces its own noise. Especially true when using cheap capture devices, the capture card will always introduce a barely audible buzzing sound to the resulting recording.

Removing Audio Noise from Old VHS Tapes

Some tapes are so worn that you might want to remove more than the capture card noise. If the VHS suffers from a constant hiss throughout the reproduction, you may want to try the following approach.

Instead of extracting a noise sample by the method described for capture card noise, take a sample during a portion of the VHS tape that should be silent. Many commercial tapes have silent parts at the beginning and end. To capture the hissing noise that occurs throughout the tape, record a few seconds of such segments. Then use this sample for generating a noise profile, as described in the article.

This process is highly destructive. Some might call it butchering the VHS, and they may be right. This will remove the hiss, but it may introduce sound artifacts that can be worse than the original noise. Use more conservative noise reduction values (less than 0.2) if you take this route. Experiment until you get the result you want.

To mitigate the noise introduced by the capture card, you can use SoX. First, capture an audio segment that only contains the noise introduced by the capture card. With your EasyCAP connected to the VCR when it is not generating any sound output (e.g., when the tape is paused), capture a few seconds of an audio segment as follows:

gst-launch-1.0 -q alsasrc device=$alsadevice ! wavenc ! fdsink | sox -t wav - -n trim 0 1 noiseprof noiseprofile

This will create a file named noiseprofile that contains a description of the noise introduced by EasyCAP. This profile can be used for reducing the noise in the audio you capture.

Now, the tape's digitized audio can be extracted from its file and cleaned with:

ffmpeg -i vhs.mkv -acodec pcm_s16le -vn vhs_tmpaud.wav
sox vhs_tmpaud.wav vhs_tmpaud-clean.wav noisered 0.21

A clean version of the audio will be recorded to vhs_tmpaud-clean.wav. The last value of the sox command above defines the denoiser's aggressiveness. Higher values mean more noise reduction, but at the expense of sound fidelity. Denoising is a destructive procedure that may wipe information away. Values that are too high will cause audible sound artifacts that are in fact worse than the original noise. Values between 0.21 and 0.31 are reasonable.

Finally, the audio is muxed back with the video stream. In this example, a video-only stream is extracted from vhs.mkv and stored in vhs_video_only.mkv. Then this video stream is combined with the clean version of the audio just generated, and the whole file is stored as vhs_whole.mkv:

ffmpeg -i vhs.mkv -vcodec copy -an vhs_video_only.mkv
ffmpeg -i vhs_video_only.mkv -i vhs_tmpaud-clean.wav -map 0:v -map 1:a -c:v copy -c:a copy vhs_whole.mkv

The Transcoding Process

You now have a video file with clean audio that uses about 15GB of disk space. This file may be transcoded into some more practical format using any encoder, such as HandBrake or MEncoder. However, I used FFmpeg in my example, because it is easily available and well documented.

For the excess video usually found at the beginning and end of a recording, trim it out with the following command:

ffmpeg -i vhs_whole.mkv -acodec copy -vcodec copy -ss $start_position -to $end_position vhs_trim.mkv

Start and end positions are values in the form hours:minutes:seconds, such as 01:30:50.

Listing 3 transcodes the captured video file and the cleaned audio file into vhs_final.mkv.

Listing 3

Transcoding into the Final Format

ffmpeg -i vhs_trim.mkv
       -vf "crop=(iw-10):(ih-14):3:0,pad=iw+10:ih+14:(ow-iw)/2:(oh-ih)/2,hqdn3d=2:1:2:3"
       -c:v libx264 -flags +ilme+ildct -profile:v high -tune:v animation
       -preset veryslow -crf 26 -c:a libfdk_aac -b:a 224k -f matroska vhs_final.mkv

The second line in Listing 3 is a set of video filters that are applied to the encoding; crop removes the overscan at the picture's borders, and pad replaces it with simple black bands. hqdn3d is a video denoiser (see the "Removing Video Noise" box).

Removing Video Noise

VHS tapes often contain grainy artifacts. This video noise makes the file more difficult to compress with video encoders and delivers poor output quality, as well. Unless your source material is very high quality with no noticeable defects, applying a denoiser video filter to your captured file might be a good idea.

I used the high-quality denoise 3D (hqdn3d) filter in Listing 3. Hqdn3d accepts four different parameters that regulate its aggressiveness. These parameters are luma_spatial, chroma_spatial, luma_tmp, and chroma_tmp. Each accepts values from   to 255. luma_spatial and chroma_spatial affect the dissipation of static noise (the noise that is analyzed in each frame without taking other frames into account). luma_tmp and chroma_tmp describe the treatment of noise that shows up through multiple frames.

Denoising is a destructive action. To remove the grain and video defects, the video is smoothed and can become blurry if an aggressive filter is used (Figure 3). Remember that fine details, such as hair or wrinkles, may be mistaken for video noise and subsequently removed by the filter. For this reason, it is better to use conservative values for the denoiser. Hqdn3d's documentation recommends not using values greater than 10 for the luma_spatial and chroma_spatial and than 13 for luma_tmp and chroma_tmp. These suggested limits are still very high. You might want to experiment with different numbers until you achieve a result you like.

Figure 3: Before (top) and after (bottom) the application of an aggressive denoiser.

The veryslow H.264 preset ensures that the best quality-to-size ratio is obtained at the expense of encoding time (for other presets, see Table 4). The ilme and ildct flags ensure that interlacing information is preserved. The tune:v option serves to adjust the H.264 encoder to the content type being transcoded; I used animation in Listing 3 (for other tune options, see Table 5). libfdk_aac encodes the sound into Advance Audio Coding (AAC) at 224Kbps. (See also the "Patent-Encumbered Codecs" box.)

Table 4

H.264 Presets











Table 5

Some Possible Tune Options






High-quality movie content


Source material with a lot of grain

Patent-Encumbered Codecs

H.264 and AAC video and audio compression standards, respectively, are certainly unsuitable for hard-core FOSS proponents who live in regions where software patents apply or plan to distribute content to those regions. If codec licensing or patent trolling is a problem, alternative codecs can be used.

VP8, Google's attempt to establish a patent-free competitor to H.264, is good enough, but it has two problems. First, it is less popular, so you are less likely to find support for it in home appliances. Second, Google has the bad habit of booting projects up, backing them with lots of resources, then suddenly realizing they are not profitable and dropping them altogether. This is the current state of VPX codecs. While VP8 is still useful, you can't count on Google to update the specification or their libraries.

Vorbis and Opus are good lossy audio codecs that can replace AAC, but as with VP8, they lack support from many domestic multimedia appliances.

Matroska is an open multimedia container that does not need replacement to keep your movie collection FOSS friendly.

The profile:v switch selects an encoding profile. Files encoded with a high profile setting will be playable by most modern multimedia appliances. The baseline profile may be used in order to ensure compatibility with older appliances, at the expense of compression efficency. [5]

Wrapping Up

The last thing you need to do is provide (optional) metadata to the file. Listing 4 shows an example metadata.xml file. Matroska metadata is not well documented, but if you want to delve deeper, see some examples online [7].

Listing 4

Example Metadata File

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Tags SYSTEM "matroskatags.dtd">
  <!-- movie -->
      <String>Happy Rottweiler</String>
      <String>Rubén Llorente</String>

The final step is to merge the metadata with the Matroska file, as follows:

mkvpropedit "vhs_final.mkv" --edit info --set "title=Happy Rottweiler" -t global:metadata.xml --edit track:a1 --set "language=spa" --set "flag-default=1"

This command sets the file's title Happy Rottweiler, merges the metadata file metadata.xml with the vhs_final.mkv file, and sets the audio track number 1 language value to Spanish. The only audio track is set as the default audio track.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More