Introduction
I have on several occasions scoured the net for a simple to use WPF webcam control and either my search queries were awful or I just wasn't comfortable with whatever I found. This webcam interest was recently increased when I read an article, here on CodeProject, that referred to an application that made use of a webcam. It was a Silverlight article and the ease with which one could utilize a webcam in Silverlight made me envious of WPF's little brother (or is it sister?). The VideoBrush in Silverlight is especially a nice touch.
It is with this pain and envy in mind that I decided to try my hand at creating a WPF control that could;
- Display webcam video with little coding effort,
- Allow saving of webcam video to harddisk, with little coding effort,
- Save the webcam video in a variety of video formats.
Background
With the previously mentioned goals in mind I created a WPF UserControl that has the following features;
- Displays webcam video,
- Enables saving of webcam videos to harddisk,
- Enables saving of webcam videos in either; .wmv, .mp4, or .flv format.
The Webcam
control makes heavy use of the Expression Encoder 4 SDK. You therefore need to have the SDK installed on your machine to make use of the UserControl
. You can download the SDK from here.
Requirements
To make use of the Webcam control you require;
- .NET Framework 4.0,
- Expression Encoder SDK
Using the Webcam Control
To use the Webcam
control in your WPF application add a reference to WebcamControl.dll and a using/imports statement for WebcamControl
at the top of your class.
Add a reference to Microsoft.Expression.Encoder.dll . Do this by using the Add Reference dialog box, selecting the .NET tab, and selecting Microsoft.Expression.Encoder from the listbox. The Expression Encoder assemblies should be available if you have installed Expression Encoder 4.
The following example, which is the downloadable sample application, shows the use of the Webcam
control. The sample application contains; a ContentControl
that will host the Webcam
control, two ComboBox
es for displaying the names of audio and video devices connected to the machine, and four buttons.
Imports Microsoft.Expression.Encoder.Devices
Imports WebcamControl
Class MainWindow
Dim webCamCtrl As New Webcam
Private Sub MainWindow_Loaded(ByVal sender As Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
FindDevices()
Dim path As String = "C:\VideoClips"
If Directory.Exists(path) = False Then
Directory.CreateDirectory(path)
End If
webCamCtrl.VideoDirectory = path
webCamCtrl.VidFormat = VideoFormat.wmv
ContentControl1.Content = webCamCtrl
VidDvcsComboBox.SelectedIndex = 0
AudDvcsComboBox.SelectedIndex = 0
End Sub
Private Sub FindDevices()
Dim vidDevices = EncoderDevices.FindDevices(EncoderDeviceType.Video)
Dim audDevices = EncoderDevices.FindDevices(EncoderDeviceType.Audio)
For Each dvc In vidDevices
VidDvcsComboBox.Items.Add(dvc.Name)
Next
For Each dvc In audDevices
AudDvcsComboBox.Items.Add(dvc.Name)
Next
End Sub
Private Sub StartButton_Click(ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles StartButton.Click
Try
webCamCtrl.StartCapture()
Catch ex As Microsoft.Expression.Encoder.SystemErrorException
MessageBox.Show("Device is in use by another application")
End Try
End Sub
Private Sub EndButton_Click(ByVal sender As Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles EndButton.Click
webCamCtrl.StopCapture()
End Sub
Private Sub RecordButton_Click(ByVal sender As System.Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles RecordButton.Click
webCamCtrl.StartRecording()
End Sub
Private Sub StopRecordButton_Click(ByVal sender As Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles StopRecordButton.Click
webCamCtrl.StopRecording()
End Sub
Private Sub VidDvcsComboBox_SelectionChanged(ByVal sender As Object, _
ByVal e As System.Windows.Controls.SelectionChangedEventArgs) _
Handles VidDvcsComboBox.SelectionChanged
webCamCtrl.VideoDevice = VidDvcsComboBox.SelectedValue
End Sub
Private Sub AudDvcsComboBox_SelectionChanged(ByVal sender As Object, _
ByVal e As System.Windows.Controls.SelectionChangedEventArgs) _
Handles AudDvcsComboBox.SelectionChanged
webCamCtrl.AudioDevice = AudDvcsComboBox.SelectedValue
End Sub
End Class
As you can see from the sample code using the Webcam
control is not a hard affair once you have the necessary references and imports/using statements.
NB: The VideoDevice
and AudioDevice
properties of Webcam
control are dependency properties and can therefore be data-bound to the SelectedValue
property of the necessary ComboBox
.
Webcam
The following are the members of interest in class Webcam
;
Properties
| Name | Description | Type |
| VideoDirectory | Gets or Sets the folder where the recorded webcam video will be saved. This is a dependency property. | String |
| VidFormat | Gets or Sets the video format in which the webcam video will be saved. This is a dependency property. (The default format is .wmv) | VideoFormat |
| VideoDevice | Gets or Sets the name of the video device to be used. This is a dependency property. | String |
| AudioDevice | Gets or Sets the name of the audio device to be used. This is a dependency property. | String |
| IsRecording | Gets a value indicating whether video recording is taking place. This is a read-only property. | Boolean |
Methods
| Name | Description |
| StartCapture | Displays webcam video on control. (Throws a Microsoft.Expression.Encoder.SystemErrorException if a specified device is already in use by another application) |
| StopCapture | Stops the capturing/display of webcam video. (Stops any current recording of webcam video) |
| StartRecording | Starts the recording of webcam video to a video file. (Throws a DirectoryNotFoundException if the directory specified in the VideoDirectory property is not found) |
| StopRecording | Stops the recording of webcam video. |
The Code
The XAML markup for the UserControl is;
<UserControl x:Class="Webcam"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="Auto" Width="Auto" MinHeight="100" MinWidth="100"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d" d:DesignWidth="320" d:DesignHeight="240" Name="Webcam">
<Grid>
<WindowsFormsHost Margin="0,0,0,0" Name="WinFormHost" Background="{x:Null}">
<wf:Panel x:Name="WebcamPanel" Size="320,240" />
</WindowsFormsHost>
</Grid>
</UserControl>
The dimensions of the WinForm Panel
are adjusted when the control is loaded so that the webcam video will occupy the entire area of the Panel
's parent element.
Private Sub Webcam_Loaded(ByVal sender As Object, _
ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
Dim panelWidth As Integer = CInt(Me.ActualWidth)
Dim panelHeight As Integer = CInt(Me.ActualHeight)
WebcamPanel.Width = panelWidth
WebcamPanel.Height = panelHeight
End Sub
As highlighted earlier, Webcam
contains several properties and methods that aid in its operation. The VideoDevice
dependency property is defined as follows;
Public Property VideoDevice() As String
Get
Return CType(GetValue(VideoDeviceProperty), String)
End Get
Set(ByVal value As String)
SetValue(VideoDeviceProperty, value)
End Set
End Property
Public Shared VideoDeviceProperty As DependencyProperty = _
DependencyProperty.Register("VideoDevice", GetType(String), GetType(Webcam), _
New FrameworkPropertyMetadata(New PropertyChangedCallback( _
AddressOf VidDeviceChange)))
Private Shared Sub VidDeviceChange(ByVal source As DependencyObject, ByVal e As DependencyPropertyChangedEventArgs)
Dim deviceName As String = CType(e.NewValue, String)
Dim eDev = EncoderDevices.FindDevices(EncoderDeviceType.Video).Where _
(Function(dv) dv.Name = deviceName)
If (eDev.Count > 0) Then
CType(source, Webcam).vidDevice = eDev.First
CType(source, Webcam).Display()
End If
End Sub
The StartCapture
method displays the webcam video in the WinForm Panel
, if the necessary properties are set;
Public Sub StartCapture()
If (canCapture = False) Then
canCapture = True
Try
Display()
Catch ex As Microsoft.Expression.Encoder.SystemErrorException
canCapture = False
Throw New Microsoft.Expression.Encoder.SystemErrorException
End Try
Else
Exit Sub
End If
End Sub
Private Sub Display()
If (canCapture = True) Then
If (vidDevice IsNot Nothing) Then
StopRecording()
Dispose()
job = New LiveJob
deviceSource = job.AddDeviceSource(vidDevice, audDevice)
deviceSource.PreviewWindow = New PreviewWindow(New HandleRef(WebcamPanel, WebcamPanel.Handle))
job.ActivateSource(deviceSource)
End If
End If
End Sub
The StartRecording
method records video from the webcam to the harddisk;
Public Sub StartRecording()
If (dir <> String.Empty AndAlso job IsNot Nothing) Then
If (Directory.Exists(dir) = False) Then
Throw New DirectoryNotFoundException("The specified directory does not exist")
Exit Sub
End If
If (canCapture = True) Then
StopRecording()
job.PublishFormats.Clear()
Dim timeStamp As String = DateTime.Now.ToString
timeStamp = timeStamp.Replace("/", "-")
timeStamp = timeStamp.Replace(":", ".")
Dim filePath As String = dir & "\WebcamVid " & timeStamp & "." & format
Dim fileArchFormat As New FileArchivePublishFormat(filePath)
job.PublishFormats.Add(fileArchFormat)
job.StartEncoding()
_isRecording = True
End If
End If
End Sub
The VideoFormat
enumeration contains three members;
Public Enum VideoFormat
wmv
mp4
flv
End Enum
You can take a look at the other properties and methods defined in class Webcam
by downloading the src files from the download link at the top of this article.
Conclusion
I hope that you picked up something useful from this article. I'm a novice in audio-video-encoding-decoding matters so if you have any questions regarding such technicalities please try to post them in the associated forums here on CodeProject. Suggestions will be beneficial, as well as answers you receive to any technical queries that may be associated with this article's content. Thanks.