A Video Converter in Visual Basic .NET
This is a simple video converter developed with .NET while playing with ffmpeg.
Ffmpeg is an open source command line audio / video converter. ffmpeg uses command line arguments for its conversion and this is what we are going to do with our .NET application. We will execute ffmpeg from our application and send these parameters to ffmpeg without displaying the command line window.
The application uses a background worker.
BackgroundWorker prevents our form from hanging while the conversion is in progress. I had that problem whenever I started the ffmpeg process.
BackgroundWorker component gives you the ability to execute time-consuming operations asynchronously (“in the background”), on a thread different from your application’s main UI thread. To use a
BackgroundWorker, you simply tell it what time-consuming worker method to execute in the background, and then you call the
RunWorkerAsync method. Your calling thread continues to run normally while the worker method runs asynchronously. When the method is finished, the
BackgroundWorker alerts the calling thread by firing the
RunWorkerCompleted event, which optionally contains the results of the operation. (MSDN 2008)
Ffmpeg is freely available on the internet. You need to have the binary version, i.e., ffmpeg.exe in the application directory of your project. It is included in the zip file.
How to Create the Converter
Let’s get started by using ffmpeg.exe. Open the command prompt in your Windows environment and navigate to the directory where ffmpeg.exe is located.
Now let’s say ffmpeg is located in C:\ i.e., C:\ffmpeg.exe, we navigate to our C: directory on the command prompt and type in a few commands into ffmpeg. Let’s say we have a .avi video file in our C: directory and want to convert that video to a .flv file, we just need to enter the command:
ffmpeg -i input.avi output.flv
Note that different arguments can be parsed to ffmpeg for various kinds on conversion, but for the purpose of this tutorial, we will stick to the very basic commands needed to convert our video file. What that argument above does is that it creates a converted video version of the file input.avi to output.flv in our C: directory. Basically, this is what our program is going to do but this time around without the command prompt. We will be sending the arguments through our program to ffmpeg. For more documentation on how to use ffmpeg, checkout this FFmpeg site…
Now let’s begin with our program in .NET.
Insert three textboxes, a trackbar, a background worker, open and save dialog boxes and four command buttons into your new form. You also need to place ffmpeg.exe in the /bin folder of your application directory.
dialogOpen tools enable us to specify where our file is located and where we want to save the output file. The
backgroundWorker tool allows us to run the ffmpeg process in a different thread from our application’s UI thread, this allows our application to run properly without interruption from ffmpeg process while the actual conversion is in progress.
Let’s create a function that performs the conversion:
We created a function
Function startConversion() Control.CheckForIllegalCrossThreadCalls = False Dim input As String = Me.dlgOpen.FileName 'the input file Dim output As String = Me.dlgSave.FileName 'the output file 'ffmpeg location Dim exepath As String = Application.StartupPath + "\bin\ffmpeg.exe" Dim quality As Integer = TrackBar1.Value * 2 Dim startinfo As New System.Diagnostics.ProcessStartInfo Dim sr As StreamReader Dim cmd As String = " -i """ + input + """ -ar 22050 -qscale " _ & quality & " -y """ + output + """" 'ffmpeg commands -y to force overwrite ' the –qscale option allows us to set the quality of our video with our trackbar Dim ffmpegOutput As String 'all parameters required to run the process 'ffmpeg uses standard error to display its output startinfo.FileName = exepath startinfo.Arguments = cmd startinfo.UseShellExecute = False startinfo.WindowStyle = ProcessWindowStyle.Hidden startinfo.RedirectStandardError = True 'redirect ffmpegs output 'to our application startinfo.RedirectStandardOutput = True 'we don’t really need this startinfo.CreateNoWindow = True proc.StartInfo = startinfo proc.Start() ' start the process Me.lblInfo.Text = "Conversion in progress... Please wait..." sr = proc.StandardError 'standard error is used by ffmpeg Me.btnStart.Enabled = False Do If BackgroundWorker1.CancellationPending Then 'check if a cancellation request was made and 'exit the function if true Exit Function End If ffmpegOutput = sr.ReadLine 'displays ffmpeg’s output 'in the textbox one line at a time Me.txtProgress.Text = ffmpegOutput Loop Until proc.HasExited And ffmpegOutput = Nothing Or ffmpegOutput = "" Me.txtProgress.Text = "Finished !" Me.lblInfo.Text = "Completed!" MsgBox("Completed!", MsgBoxStyle.Exclamation) Me.btnStart.Enabled = True Return 0 End Function
startConversion()which performs the actual conversion of the file with ffmpeg.
False prevents Visual Studio from catching calls on a different thread that accesses a control’s
Handle property when an application is being debugged because we will be calling our controls from another thread separate from our form’s thread, i.e., the
backgroundWorker process where our function is located.
This command is parsed to ffmpeg.exe to do the actual conversion for us.
Dim cmd As String = " -i """ + input + """ -ar 22050 -qscale " _ & quality & " -y """ + output + """"
-i input” specifies our input file, e.g., sample.avi, the “
-ar 22050” specifies the audio sampling frequency as 22050 which is common for flash video files, we can also specify a different one like 44100 which is actually the default in ffmpeg. “
-qscale” specifies the quality of the video e.g.,. “
-qscale 2” is of higher quality than “
-qscale 10”. The value of our quality variable is retrieved from the trackbar. We want our users to specify the quality of the video they want using the trackbar.
startinfo contains properties that allows us to specify that our process is being run. The
WindowStyleproperty is set to hidden, this prevents the command prompt console from showing.
RedirectStandardOutputproperty is used to redirect whatever is displayed on the command prompt to a different control. But ffmpeg uses
standardErrorto display its conversion output, this is why we have to use the
RedirectStandardErrorand set its value to
BackgroundWorker1.CancellationPendingshows that a cancellation request was sent to terminate the process, we use this property to exit our function, this actually kills the ffmpeg process.
ffmpegOutput is used to display the output from ffmpeg by assigning
sr.ReadLine to it.
startButton, insert the following code:
Private Sub btnStart_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStart.Click If txtOpen.Text = "" Or txtOpen.Text <> dlgOpen.FileName Then MsgBox("Select a file to convert", MsgBoxStyle.Information, "Select a file") Exit Sub ElseIf txtSave.Text = "" Or txtSave.Text <> dlgSave.FileName Then MsgBox("Select your output filename", MsgBoxStyle.Information, "Select a file") Exit Sub End If BackgroundWorker1.RunWorkerAsync() ‘start the background worker End Sub
RunWorkerAsync()action of the
backgroundWorkeris used to start the process. What this does is that it executes the
startConversion()function we inserted in the
On the save dialog tool, insert the following code:
On our stop button, we send a
Private Sub dlgSave_FileOk(ByVal sender As System.Object, _ ByVal e As System.ComponentModel.CancelEventArgs) Handles dlgSave.FileOk dlgSave.OverwritePrompt = True dlgSave.DereferenceLinks = True dlgSave.CreatePrompt = True dlgSave.DefaultExt = ".flv" 'this program converts to flv only, 'you can allow the user to save in any 'format by including more video file 'extension in the save option dialog box txtSave.Text = dlgSave.FileName End Sub 'To stop the conversion process, we send a notification to the 'backgroundWorker and kill the ffmpeg process Private Sub btnStop_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles btnStop.Click On Error GoTo handle BackgroundWorker1.CancelAsync() If btnStart.Enabled = False Then lblInfo.Text = ("Conversion Canceled!") MsgBox("Conversion has been cancelled!", MsgBoxStyle.Exclamation) btnStart.Enabled = True Else MsgBox("Start conversion first", MsgBoxStyle.Critical) End If proc.Kill() handle: Exit Sub End Sub
CancelAsync()request to the
backgroundWorker. This request enables us to handle anything we need to display or do before we end the process. For example, we can display a message box that confirms cancellation and also perform a different task on the process before the process ends.
backgroundWorker calls the conversion function here:
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, _ ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork startConversion() End Sub