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