Introduction
Today, we are going to make a video converter using ffmpeg and VB.NET 2010. The source files will be included, except MediaInfo.dll, MediaInfoNet.dll and ffmpeg, you must download these yourself but a quick Google search will suffice. Once you have downloaded these files, copy both medialinfo.dll files and ffmpeg.exe to your project/bin folder.
To follow along, here's what you will need on your form: 5 buttons, add video, browse, convert, cancel, exit, a progressbar, 17 labels for showing imported video stats (optional) and a couple for general labeling purposes.
RichTextBox
, to show the ffmpeg standarderror out
TextBox
, to show save path Combobox
, for preset options, and a menu strip LinkLabel
, you can use a button, instead I use this to hide the RichTextBox
- Background Worker. this is named
Bgw1
in the source files
Add the following items to the menustrip, file, under file add: Add video, SaveTo, and Exit. Next on the menustrip is Clear Information (optional), and I add a Convert
, this is also optional.
Be sure to name your buttons and labels for example, btnAddVideo
, lblFrameCount
, etc. it's easer when coding.
Screenshot.png
Notice how the preset combobox
is located above the save location. This is to make the user select a preset first in order to give the savefiledialog
filter the correct value, for example preset option1
could be High Quality AVI and preset option2
could be High Quality MP4, so when the user browses for a save location, the correct file extension is added automatically.
Background
Many tutorials use the ffmpeg
standard error to parse the time to try and calculate the remaining time left of the conversion process. I had many problems trying this, so I decided to parse the frame value of the standard error out. We do this using mediainfoNet
, MediaInfoNet.dll calls MediaInfo.dll, so make sure both are located in your project/bin folder.
Using the Code
Imports MediaInfoNET
Imports System.IO
Public Class Form1
Dim OFD As OpenFileDialog
Dim SFD As SaveFileDialog
Dim mFile As MediaFile
Dim InputFile As String
Dim OutputFile As String
Dim pathResult As String
Dim FCount As Integer
Dim KB As Integer
Dim MB As Integer
Dim GB As Integer
Private prcFFMPEG As New Process
Dim psiProcInfo As New System.Diagnostics.ProcessStartInfo
Dim strFFCMD As String
Dim ffReader As StreamReader
Dim strFFOUT As String
Dim currentFramestr As String
Dim currentFrameInt As Integer
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Load
RichTextBox1.Visible = False
Me.Height = 441
ProgressBar1.Value = 0
Button5.Enabled = False
KB = 1024
MB = KB * 1024
GB = MB * 1024
End Sub
Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked
If Me.Height = 441 Then
Me.Height = 508
RichTextBox1.Visible = True
Label12.Visible = False
Else
Me.Height = 441
RichTextBox1.Visible = False
Label12.Visible = True
End If
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
OFD = New OpenFileDialog
If OFD.ShowDialog = Windows.Forms.DialogResult.OK _
Then
mFile = New MediaFile(OFD.FileName)
InputFile = OFD.FileName
pathResult = Path.GetFileNameWithoutExtension_
(OFD.FileName)
Label3.Text = "Name: " & _
pathResult
If mFile.FileSize > 1070000000 _
Then
Label4.Text = "FileSize: " & String.Format("{0:0.00}", _
mFile.FileSize / KB / MB) & " GB."
Else
Label4.Text = "FileSize: " & String.Format("_
{0:0.00}", mFile.FileSize / MB) & " MB."
End If
Label5.Text = "Duration: " & _
mFile.Video(0).DurationString
Label6.Text = "Format: " & _
mFile.Video(0).Format
Label7.Text = "Codec: " & _
mFile.Video(0).CodecID
Label8.Text = "Resolution: " & _
mFile.Video(0).FrameSize
Label9.Text = "Framerate: " & _
mFile.Video(0).FrameRate & "fps"
Label14.Text = "NumberOfFrames: " & _
mFile.Video(0).SourceFile.FrameCount.ToString
Label15.Text = "VideoStreams: " & mFile.Video(0).StreamType & _
" " & mFile.Video(0).StreamIndex
Label16.Text = "AudioStreams: " & mFile.Audio(0).StreamType & _
" " & mFile.Video(0).StreamIndex
Label1.Text = "AudioCodec: " & _
mFile.Audio(0).CodecID
Label17.Text = "Audio Bitrate: " & _
mFile.Audio(0).Bitrate
Label18.Text = "Audio Samplerate: " & _
mFile.Audio(0).SamplingRate
FCount = Integer.Parse_
(mFile.Video(0).SourceFile.FrameCount)
End If
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
SFD = New SaveFileDialog
SFD.AddExtension = True
SFD.Filter = ""
If ComboBox1.SelectedIndex = 1 Then
SFD.Filter = "Mp4 (.mp4)|*.mp4"
End If
If ComboBox1.SelectedIndex = 2 Then
SFD.Filter = "Mp4 (.mp4)|*.mp4"
End If
If SFD.ShowDialog = Windows.Forms.DialogResult.OK Then
TextBox1.Text = SFD.FileName
OutputFile = SFD.FileName
End If
End Sub
Private Sub Convert()
Control.CheckForIllegalCrossThreadCalls = False
If ComboBox1.SelectedIndex = 1 Then
strFFCMD = " -i " & Chr(34) & InputFile & Chr(34) & _
" -c:v libx264 -s 1280x720 -pix_fmt yuv420p -qp 20 -profile high444 _
-c:a libvo_aacenc -b:a 128k -ar 44100 -ac 2 " & OutputFile
End If
If ComboBox1.SelectedIndex = 2 Then
strFFCMD = " -i " & Chr(34) & InputFile & Chr(34) & " _
-c:v libx264 -s 1280x720 -pix_fmt yuv420p -qp 20 -profile high444 _
-c:a libvo_aacenc -b:a 128k -ar 44100 -ac 2 " & OutputFile
End If
psiProcInfo.FileName = Application.StartupPath + "\ffmpeg.exe"
psiProcInfo.Arguments = strFFCMD
psiProcInfo.UseShellExecute = False
psiProcInfo.WindowStyle = ProcessWindowStyle.Hidden
psiProcInfo.RedirectStandardError = True
psiProcInfo.RedirectStandardOutput = True
psiProcInfo.CreateNoWindow = True
prcFFMPEG.StartInfo = psiProcInfo
prcFFMPEG.Start()
ffReader = prcFFMPEG.StandardError
Do
If Bgw1.CancellationPending Then
Exit Sub
End If
Button5.Enabled = True
Button3.Enabled = False
strFFOUT = ffReader.ReadLine
RichTextBox1.Text = strFFOUT
If strFFOUT.Contains("frame=") Then
currentFramestr = Mid(strFFOUT, 7, 6)
currentFrameInt = CInt(currentFramestr)
End If
Dim percentage As String = _
CType((ProgressBar1.Value / ProgressBar1.Maximum * 100), Integer).ToString & "%"
ProgressBar1.Maximum = FCount + 1000
ProgressBar1.Value = (currentFrameInt)
Label12.Text = "Current Encoded Frame: _
" & currentFrameInt
Label11.Text = percentage
Loop Until prcFFMPEG.HasExited And strFFOUT = Nothing Or strFFOUT = ""
If ProgressBar1.Value <> ProgressBar1.Maximum Then
ProgressBar1.Value = ProgressBar1.Maximum
End If
MsgBox("The Conversion Process has Completed.", _
MsgBoxStyle.Information, "Finished.")
Button5.Enabled = False
Button3.Enabled = True
ProgressBar1.Value = 0
Label11.Text = _ProgressBar1.Value & "%"
Label12.Text = "Current Encoded Frame: "
If Me.Height = 508 Then
Me.Height = 441
RichTextBox1.Visible = False
End If
End Sub
Private Sub Bgw1_DoWork(ByVal sender As System.Object, _
ByVal e As System.ComponentModel.DoWorkEventArgs) Handles Bgw1.DoWork
Convert()
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button3.Click
If InputFile = "" Then
MsgBox("No input file selected please press the _
'Add File' button.", MsgBoxStyle.Exclamation, "Error")
Else
Bgw1.RunWorkerAsync()
End If
End Sub
Private Sub Button5_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button5.Click
Bgw1.CancelAsync()
prcFFMPEG.Kill()
MsgBox("The Conversion Process has been Cancelled.", _
MsgBoxStyle.Information = MsgBoxStyle.YesNo, "Information")
ProgressBar1.Value = 0
Label11.Text = ProgressBar1.Value & "%"
If Me.Height = 508 Then
Me.Height = 441
RichTextBox1.Visible = False
Label12.Text = "Current Encoded Frame: "
End If
End Sub
Private Sub ClearAllInfo()
Label3.Text = "Name: "
Label4.Text = "FileSize: "
Label4.Text = "FileSize: "
Label5.Text = "Duration: "
Label6.Text = "Format: "
Label7.Text = "Codec: "
Label8.Text = "Resolution: "
Label9.Text = "Framerate: "
Label14.Text = "NumberOfFrames: "
Label15.Text = "VideoStreams: "
Label16.Text = "AudioStreams: "
Label1.Text = "AudioCodec: "
Label17.Text = "Audio Bitrate: "
Label18.Text = "Audio Samplerate: "
InputFile = ""
OutputFile = ""
TextBox1.Clear()
End Sub
Private Sub ClearInformationToolStripMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ClearInformationToolStripMenuItem.Click
ClearAllInfo()
End Sub
Points of Interest
The code for the progressbar
was surprisingly accurate with small sized videos, but for some reason mediainfo
didn't get the same frame count because we are converting, changing fps
, so to compensate we make sure the progressbar
maximum is always 1000 higher than the current value.
History
- 24th January, 2016: Initial version