Creating a Video Converter Using VB.NET

Introduction

I have always been fascinated with programs like DVD Fab, or XiliSoft. I literally have millions of DVDs. I am a movie freak. Now, I have many imported DVDs of movies I can remember from when I was just a little boy. The problem is: not every one puts the DVD back into its case once it has been watched, causing the disks to scratch. That is why I have decided to make my own movie converter, so that I can backup my movies on my 2 TB hard drive.

Our Program

Our program for this article is called HTG_NCode. It is a normal Windows Forms application, and it has only one form inside it. Feel free to start your project now. Honestly, do not expect too much from this project, as I am only one dumb guy trying to figure out how things work. That is my aim with all my articles. I want to show you how stuff works and give you enough knowledge to further elaborate on your own projects. Yip, I shouldn't have said that, because now most readers aren't reading any more...

For those of you who are serious and as curious as I am, and still reading, here is a break down of what we will do in this project:

  • Make use of a freeware program (which we have to download and copy to our application folder) called ffmpeg.exe to handle all of the conversions for us. Why? Well, VB.NET's capabilities with these types of things are very limited; non-existant really. Sad. But why a separate program? OK, it will take (me) years to figure out each file's different signature. A file signature is a short code at the beginning and or end of each file identifying what type of file it is. This is also how anti viruses work. They check if the file's signature is correct or not. If it is not, it is regarded as a potential threat. Obviously, we are not here to talk about anti viruses; so I just have one more thing to add. Have a look at the following three pictures. They show file signatures for .gif, png, and jpg files. Why I am showing you this is so that you can see for yourself. These are just pictures' signatures, I know, but you get the idea, don't you? In case you're wondering, here is a list of more appropriate file signatures:
    • AVI: 52 49 46 46 xx xx xx xx 43 44 44 41 66 6D 74 20
    • MP4: 00 00 00 18 66 74 79 70 33 67 70 35
    • WMV: 30 26 B2 75 8E 66 CF 11 A6 D9 00 AA 00 62 CE 6C
    • MKV: 1A 45 DF A3 93 42 82 88 6D 61 74 72 6F 73 6B 61
    • VOB: 00 00 01 BA
    • FLV: 46 4C 56 01

Gif file signature
Image 1 - Gif file signature

Jpeg file signature
Image 2 - Jpeg file signature

Png file signature
Image 3 - Png file signature

  • Do a basic (default) conversion
  • Set up the program to do more than just convert:
    • We will determine the quality of the converted file
    • Set the video size. This will be how big on TV the file will show. So, you can set it so that it shows full screen, instead of a small window inside your tv
    • Set the Audio bitrate
    • Determine if a DVD has been inserted or not
    • Set a Volume label for your output file
  • And most importantly: have some fun!

Creating a Video Converter Using VB.NET

Right, let us get started!

Design

Design your form to look similar to the next screenshot. You are welcome to use your own names for controls here, as long as you keep track of them. With all my code segments I will use my own names, as it is in the attached project.

[Design.jpg]
Image 4 - Our Design

List Controls

There are three list controls, as you can see in the above screenshot. Edit their Items properties as follows:

Output Format avi
mp4
wmv
mkv
vob
flv
Output Audio 64 kbps
96 kbps
128 kbps
192 kbps
256 kbps
320 kbps
Video Size

These items I found on ffmpeg's Documentation site

'sqcif' 128x96
'qcif' 176x144
'cif' 352x288
'4cif' 704x576
'16cif' 1408x1152
'qqvga' 160x120
'qvga' 320x240
'vga' 640x480
'svga' 800x600
'xga' 1024x768
'uxga' 1600x1200
'qxga' 2048x1536
'sxga' 1280x1024
'qsxga' 2560x2048
'hsxga' 5120x4096
'wvga' 852x480
'wxga' 1366x768
'wsxga' 1600x1024
'wuxga' 1920x1200
'woxga' 2560x1600
'wqsxga' 3200x2048
'wquxga' 3840x2400
'whsxga' 6400x4096
'whuxga' 7680x4800
'cga' 320x200
'ega' 640x350
'hd480' 852x480
'hd720' 1280x720
'hd1080' 1920x1080
 

Now we can move on to the code.

Creating a Video Converter Using VB.NET

Code

Imports

As usual, I list the necessary Imports first:

Imports System.Runtime.InteropServices 'used for APIs
Imports System 'System imports
Imports System.IO 'File input / output
Imports System.Text 'Advanced Text capabilities

Declarations:

 
 
 
 
 

    'Gets Drive Names
    Private Declare Function GetLogicalDriveStrings Lib "kernel32.dll" _
        Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As Int32, _
                                         ByVal lpBuffer As String) As Int32

    'Checks for free space on disk
    Declare Auto Function GetDiskFreeSpace Lib "kernel32.dll" ( _
     ByVal lpRootPathName As String, _
     ByRef lpSectorsPerCluster As UInt32, _
     ByRef lpBytesPerSector As UInt32, _
     ByRef lpNumberOfFreeClusters As UInt32, _
     ByRef lpTotalNumberOfClusters As UInt32) As Integer

    'Determines drive Type
    Private Declare Function GetDriveType Lib "kernel32.dll" Alias "GetDriveTypeA" ( _
            ByVal nDrive As String) As Int32

    Private Const DRIVE_CDROM As Long = 5 'DVD / CD ROM constant

    Private strDriveLetter As String 'Stores Drive Letter
    Private strFinalOutput As String 'Stores Final Output Location
    Private strFWOE As String 'Stores Filename Without Path & Extension
    Private strOutExt As String 'Stores Selected Output File Format
    Private strOutAudio As String 'Stores Audio Bitrate
    Private strVidSize As String 'Stores Video Size

    Private intQuality As Integer 'Stores Output Quality

    Private blnDVD As Boolean 'Has A DVD Been Inserted

    Private prcFFMPEG As New Process 'FFMPEG Process Object

ConvertFile function

    Private Function ConvertFile() 'Function To Convert File

        Control.CheckForIllegalCrossThreadCalls = False 'Disable Illegal Crossthread Calls From Controls

        Dim strOutput As String 'Output File Name
        Dim strFFMPEGOut As String 'Lines Read From Input / Source File

        Dim strSource As String = txtSource.Text 'Source
        Dim strFFMPEGCmd As String = " -i """ & strSource & """ -ar 2250 -b 64k -r 24 -y """ & strOutput & """"

        Dim psiProcInfo As New System.Diagnostics.ProcessStartInfo 'Proc Info Object For FFMPEG.EXE

        Dim srFFMPEG As StreamReader 'Reads Source File's Lines

        '        Dim cmd As String = " -i """ & input & """ -ar " & strOutAudio & " -b 64k -r 24 -s " & strVidSize & "-qscale " & intQuality & " -y """ & output & """" 'ffmpeg commands -y replace

        If strFinalOutput <> "" And strFWOE <> "" And strOutExt <> "" And strOutAudio <> "" And strVidSize <> "" Then

            strOutput = strFinalOutput & strFWOE & strOutExt

        Else

            MessageBox.Show("Ensure all settings are properly made!") 'If Something Not Set

            Exit Function

        End If


        psiProcInfo.FileName = Application.StartupPath + "\ffmpeg.exe" 'Location Of FFMPEG.EXE
        psiProcInfo.Arguments = strFFMPEGCmd 'Command String
        psiProcInfo.UseShellExecute = False

        psiProcInfo.WindowStyle = ProcessWindowStyle.Hidden

        psiProcInfo.RedirectStandardError = True
        psiProcInfo.RedirectStandardOutput = True
        psiProcInfo.CreateNoWindow = True

        prcFFMPEG.StartInfo = psiProcInfo

        prcFFMPEG.Start() 'Start Process

        Me.Text = "Converting..."

        srFFMPEG = prcFFMPEG.StandardError 'Enable Error Checking For FFMPEG.EXE

        Me.btnStart.Enabled = False

        Do

            If bgwConvert.CancellationPending Then 'Cancelled?

                Exit Function

            End If

            strFFMPEGOut = srFFMPEG.ReadLine 'Read Source File Line By Line

        Loop Until prcFFMPEG.HasExited And strFFMPEGOut = Nothing Or strFFMPEGOut = "" 'Read Until There Is Nothing Left

        Me.Text = "Done!"

        Me.btnStart.Enabled = True

        Return 0

    End Function

The above function launches ffmpeg.exe with specific arguments. We make use of a BackgroundWorker here because some files are huge and will take some time to finish the conversion. We also do not want our program to freeze do we? You have to remember that not all settings can be applied with all the various output file types. You have to read the ffmpeg documentation properly to see which setting works where. This line (which has been commented out):

        '        Dim cmd As String = " -i """ & input & """ -ar " & strOutAudio & " -b 64k -r 24 -s " & strVidSize & "-qscale " & intQuality & " -y """ & output & """" 'ffmpeg commands -y replace

Will mostly work only with AVI output files. So make sure your settings are compatible with your output.

GetDVDRomDriveLetter Function

    'Function Determines DVD / CD ROM Drive Letter
    Private Function GetDVDRomDriveLetter() As String

        Dim lngDriveType As Long 'Holds Drive Type
        Dim lngCurrentDrive As Long 'Current Drive Counter

        Dim strDrive As String 'Holds Final Drive Letter

        lngCurrentDrive = 1 'First Drive

        Dim strDrives As String 'Holds All Drives
        strDrives = Space(150) 'Ensure There Is Enough Space To hold All Drive Letters

        Dim lRetVal As Long 'GetLogicalDriveStrings Retun Value
        lRetVal = GetLogicalDriveStrings(150, strDrives) 'Get All Drive Strings

        If lRetVal = 0 Then 'If GetLogicalDriveStrings() Failed, Reset Variables & Exit

            GetDVDRomDriveLetter = vbNullString

            Exit Function

        End If

        strDrive = Mid(strDrives, lngCurrentDrive, 3) 'Get Current Drive's Letter

        Do

            lngDriveType = GetDriveType(strDrive) 'Determine Drive Type Of Current Drive


            If lngDriveType = DRIVE_CDROM Then 'If Type Is DVD / CD Store That Drive Letter

                GetDVDRomDriveLetter = strDrive

                Exit Function

            End If

            lngCurrentDrive = lngCurrentDrive + 4 'Increment Counter 

            strDrive = Mid(strDrives, lngCurrentDrive, 3) 'Get Drive Letter

        Loop While (Mid(strDrives, lngCurrentDrive, 1) <> vbNullChar) 'Continue While Drive String Is Valid

    End Function

With this function, we determine our DVD / CD ROM's drive letter.

GetDVDRomInfo Sub

    Private Sub GetDVDRomInfo() 'Sub To Check If Disk Has Any Content

        strDriveLetter = GetDVDRomDriveLetter() 'Use Correct Drive Letter For DVD / CD ROM

        If (GetDiskFreeSpace(strDriveLetter, 0, _
                            0, 0, 0) > 0) Then 'If Disk Has Content

            txtSource.Text = strDriveLetter 'Add Drive Letter To Source Textbox
            txtVolumeLabel.Text = Dir(strDriveLetter, FileAttribute.Volume) 'Add Volume Label

            ReadDVDRomFiles() 'Read DVD Contents

            blnDVD = True 'Set DVD Boolean To True

        Else 'Disk Is Empty

            txtSource.Text = ""
            txtVolumeLabel.Text = ""

            blnDVD = False

        End If

    End Sub

Here we make use of the correct drive letter to determine the content of the inserted disk.

ReadDVDRomFiles Sub

    Private Sub ReadDVDRomFiles() 'Reads DVD / CD Contents

        Dim diFolder As New IO.DirectoryInfo(strDriveLetter & "Video_Ts".ToUpper()) 'Determines If VIDEO_TS Folder Is Present

        Dim arrFIFiles As IO.FileInfo() = diFolder.GetFiles("*.vob") 'List All .VOB Files

        Dim fiFile As IO.FileInfo

        For Each fiFile In arrFIFiles

            lstFiles.Items.Add(fiFile.Name)

        Next

    End Sub

If the disk was not empty, we determine if any playable DVD content could be found.

LoadFiles Sub

    Private Sub LoadFiles() 'Add Files From Selected Folder

        Dim FilePath As String

        For Each FilePath In Directory.GetFiles(fbdSource.SelectedPath)

            lstFiles.Items.Add(FilePath)

        Next

    End Sub

We use the above sub to read the contents of the hard disk folder we have selected.

Creating a Video Converter Using VB.NET

Events

    Private Sub frmHNMain_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        GetDVDRomInfo() 'Read Disk Info, If Present

    End Sub

    Private Sub btnBrowseSource_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowseSource.Click

        If fbdSource.ShowDialog = DialogResult.OK Then 'Determine Sourse Of File To Convert

            If Not blnDVD Then 'If No DVD Is Present

                txtSource.Text = fbdSource.SelectedPath 'Use FBD Selected Folder Path As Source
                txtVolumeLabel.Text = fbdSource.SelectedPath.Substring(fbdSource.SelectedPath.LastIndexOf("\") + 1)

                LoadFiles() 'Read FBD Selected Folder Contents

            Else

                txtSource.Text = fbdSource.SelectedPath
                txtVolumeLabel.Text = Dir(strDriveLetter, FileAttribute.Volume)

            End If

        End If

    End Sub

    Private Sub btnBrowseOutput_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowseOutput.Click

        If fbdOutput.ShowDialog = DialogResult.OK Then 'Where Output File(s) Should Be Saved

            strFinalOutput = fbdOutput.SelectedPath & "\"
            txtOutput.Text = fbdOutput.SelectedPath & "\"

        End If

    End Sub

    Private Sub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExit.Click

        Application.Exit() 'Exit

    End Sub

    Private Sub lstFiles_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstFiles.SelectedIndexChanged

        If Not blnDVD Then

            txtSource.Text = lstFiles.SelectedItem.ToString

            strFWOE = Path.GetFileNameWithoutExtension(lstFiles.SelectedItem.ToString) 'Get Selected File's Name Only

        Else

            txtSource.Text = strDriveLetter & lstFiles.SelectedItem.ToString & "\"

        End If

    End Sub

    Private Sub cboOutputFormat_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboOutputFormat.SelectedIndexChanged

        strOutExt = "." & cboOutputFormat.SelectedItem.ToString 'Store Selected String

    End Sub

    Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click

        If txtSource.Text = "" Then

            MessageBox.Show("Select A Source Folder!") 'Make Sure Source Has Been Selected
            Exit Sub

        ElseIf txtOutput.Text = "" Then

            MessageBox.Show("Select An Output Folder!") 'Make Sure Output Has Been Selected

            Exit Sub

        End If

        bgwConvert.RunWorkerAsync() 'Start Conversion

    End Sub

    Private Sub bgwConvert_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwConvert.DoWork

        ConvertFile() 'Function / Sub That Must Start

    End Sub

    Private Sub btnStop_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStop.Click

        bgwConvert.CancelAsync()

        If btnStart.Enabled = False Then

            MessageBox.Show("Conversion Cancelled!") 'User Cancelled
            btnStart.Enabled = True

        Else

            MessageBox.Show("Click Start First!") 'Not Selected Start

        End If

        prcFFMPEG.Kill() 'Done

    End Sub

    Private Sub cboAudio_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboAudio.SelectedIndexChanged

        strOutAudio = cboAudio.SelectedItem.ToString.Substring(0, cboAudio.SelectedItem.ToString.LastIndexOf(" ") + 1) 'Store Audio String

    End Sub

    Private Sub lstVideoSize_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lstVideoSize.SelectedIndexChanged

        strVidSize = lstVideoSize.SelectedItem.ToString.Substring(0, lstVideoSize.SelectedItem.ToString.LastIndexOf(" ") + 1) 'Store Video Size

    End Sub

    Private Sub trkQuality_Scroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles trkQuality.Scroll

        intQuality = trkQuality.Value * 2 'Set Quality Of Output File

    End Sub

Most of the above events, are quite self explanitory. The last three, however, may not be. We had to do some string manipulation here in order to get the correct data to be used with ffmpeg as an argument.

Short and sweet :)

Conclusion

There you have it. You now have a lot of work to do from your side. I hope my article was helpful in your endeavors in file encoding. Until next time!



About the Author

Hannes du Preez

Hannes du Preez is a Microsoft MVP for Visual Basic. He is a trainer at a South African-based company. He is the co-founder of hmsmp.co.za, a community for South African developers.

Related Articles

Downloads

Comments

  • There are no comments yet. Be the first to comment!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds