First Bash Script

After spending quite an intimate week with a nice Linux Shell Scripting tutorial recommended to me by Uncle Raju I thought it would be great to actually put those scripting skills to use. My father has a very expansive collection of home videos spanning all the way to the 1980s of our family. Sadly enough, they are not very accessible. It’s definitely a very involved process when it comes to being able to watch them.

A typical rip, the VIDEO_TS.VOB is the main menu of the DVD

The videos were ripped straight from DVDs and VHS tapes and thus they are split up across multiple files. Take for example, the video of my younger brother’s first birthday. The entire movie is split across four.VOB files that must be watched through something like VLC Media Player or mpv. Not quite easy to just cast that video to the TV or something like that. I wanted it to be easy for my parents to watch these old movies so I thought it would be great to use a library like FFmpeg to convert all those home movies to a more universal format such as .mp4. This was so I could push all the converted movies to Plex and now they would be easily available to watch everywhere.

Converting and Combining

Converting a .VOB to a .mp4 was simple enough

	ffmpeg -hwaccel cuda -i /path/to/input.vob \
         -preset slow \
	 -c:v hevc_nvenc  \
	 -c:a copy \
	 /path/to/output.mp4

However, since the movies were split into three or four files, I would also have to combine all of the outputs to a single file. This would mean using the concat demuxer which involved creating a .txt with all the files to combine as follows:

# Files to combine
file '/path/to/file1.mp4'
file '/path/to/file2.mp4'
file '/path/to/file3.mp4'

Then simply calling this command.

ffmpeg -f concat  -i to_combine.txt -c copy output.mp4

Writing the Scripts

As you can see, this is definitely something that can be automated using a bash script very easily. This would definitely be the first time I would be writing my own bash script to solve a problem on my own. Definitely exciting!

I thought it would be useful to lay out the steps for this little script for myself…

  1. Loop through all of the .VOB files in the current directory and convert them using ffmpeg to temp/*.mp4.
  2. List all the temp/*.mp4 files in the temp directory and store them in the temp/to_combine.txt.
  3. Combine the temporary temp/*.mp4 to /path/to/output.mp4
  4. Delete the temp folder.

I also had a slight extra problem with the ripped DVDs and VHS where the audio was only coming through a single channel since the audio was mono. This would mean I would only hear the videos through my left ear. Nonetheless it was easily fixed by adding the following arguments

-map_channel 0.1.0 -map_channel 0.1.0.

More information about Map can be found here. I was able to come up with the following script after everything was said and done.

#!/bin/bash

filestring=`ls *.VOB`
readarray -t files <<< "$filestring"
mkdir output
mkdir temp

# Convert videos to HEVC.
convert() {
	outputname=${1%.VOB}
	echo Converting "$1..."

	# Convert video to MP4 using HEVC.
	ffmpeg -hwaccel cuda -i "$1" \
	 -c:v hevc_nvenc \
	 -preset slow \
	 -c:a copy \
	 "./temp/$outputname.mp4"

	# Add file to output list.
	echo "file '$outputname.mp4'" >> temp/output.txt

	echo Done. Output "$outputname.mp4"
}

fix_audio() {
	echo "Fixing audio..."
	ffmpeg.exe -i "$1" -map_channel 0.1.0 -map_channel 0.1.0 -c:v copy "$2"
}



# Convert all files to HEVC.
for file in "${files[@]}"
do
	convert "$file"
done

# Combine all files.
echo "Combining files."
ffmpeg.exe -f concat -i temp/output.txt -c copy temp/movie.mp4

# Fix audio.
fix_audio "temp/movie.mp4" "output/movie.mp4"

echo "Cleaning up temp files."
rm -rf temp

wait
echo "Finished converting movie."

Results

There is definitely a lot more I can do with this script and it can be improved significantly I am sure. The end result was definitely worth it!