Screenshot_1.png

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;

  1. Display webcam video with little coding effort,
  2. Allow saving of webcam video to harddisk, with little coding effort,
  3. 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 code for the downloadable sample application, shows the use of the Webcam control. The sample application contains; a ContentControl that will host the Webcam control, two ComboBoxes for displaying the names of audio and video devices connected to the machine, and four buttons.

VB.NET

Imports Microsoft.Expression.Encoder.Devices
Imports WebcamControl

Class MainWindow
    Private 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

        ' Set some properties of the Webcam control.
        webCamCtrl.VideoDirectory = path
        webCamCtrl.VidFormat = VideoFormat.wmv

        ' Set the Webcam control as the ContentControl's content.
        ContentControl1.Content = webCamCtrl

        VidDvcsComboBox.SelectedIndex = 0
        AudDvcsComboBox.SelectedIndex = 0
    End Sub

    ' Find available a/v devices.
    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

        ' Display webcam images on control.
        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

        ' Stop the display of webcam video.
        webCamCtrl.StopCapture()
    End Sub

    Private Sub RecordButton_Click(ByVal sender As System.Object, _
                                   ByVal e As System.Windows.RoutedEventArgs) Handles RecordButton.Click

        ' Start recording of webcam video to harddisk.
        webCamCtrl.StartRecording()
    End Sub

    Private Sub StopRecordButton_Click(ByVal sender As Object, _
                                       ByVal e As System.Windows.RoutedEventArgs) Handles StopRecordButton.Click

        ' Stop recording of webcam video to harddisk.
        webCamCtrl.StopRecording()
    End Sub

    Private Sub VidDvcsComboBox_SelectionChanged(ByVal sender As Object, _
                                                 ByVal e As System.Windows.Controls.SelectionChangedEventArgs) _
                                             Handles VidDvcsComboBox.SelectionChanged

        ' Set which video device to use.
        webCamCtrl.VideoDevice = VidDvcsComboBox.SelectedValue
    End Sub
   
    Private Sub AudDvcsComboBox_SelectionChanged(ByVal sender As Object, _
                                                 ByVal e As System.Windows.Controls.SelectionChangedEventArgs) _
                                             Handles AudDvcsComboBox.SelectionChanged

        ' Set which audio device to use.
        webCamCtrl.AudioDevice = AudDvcsComboBox.SelectedValue
    End Sub
End Class

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.

    Private Sub MainWindow_Initialized(ByVal sender As Object, _
                                       ByVal e As System.EventArgs) Handles Me.Initialized
        Dim bndg_1 As New Binding("SelectedValue")
        bndg_1.Source = VidDvcsComboBox
        webCamCtrl.SetBinding(Webcam.VideoDeviceProperty, bndg_1)

        Dim bndg_2 As New Binding("SelectedValue")
        bndg_2.Source = AudDvcsComboBox
        webCamCtrl.SetBinding(Webcam.AudioDeviceProperty, bndg_2)
    End Sub

C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Expression.Encoder.Devices;
using WebcamControl;
using System.IO;

namespace WPF_Webcam
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private Webcam webCamCtrl;

        public MainWindow()
        {
            InitializeComponent();

            webCamCtrl = new Webcam();           

            // Bind the Video and Audio device properties of the
            // Webcam control to the SelectedValue property of 
            // the necessary ComboBox.
            Binding bndg_1 = new Binding("SelectedValue");
            bndg_1.Source = VidDvcsComboBox;
            webCamCtrl.SetBinding(Webcam.VideoDeviceProperty, bndg_1);

            Binding bndg_2 = new Binding("SelectedValue");
            bndg_2.Source = AudDvcsComboBox;
            webCamCtrl.SetBinding(Webcam.AudioDeviceProperty, bndg_2);

            // Create directory for saving video files.
            string vidPath = @"C:\VideoClips";

            if (Directory.Exists(vidPath) == false)
            {
                Directory.CreateDirectory(vidPath);
            }

            // Set some properties of the Webcam control
            webCamCtrl.VideoDirectory = vidPath;
            webCamCtrl.VidFormat = VideoFormat.wmv;

            // Set the Webcam control as the ContentControl's content.
            ContentControl1.Content = webCamCtrl;

            // Find a/v devices connected to the machine.
            FindDevices();

            VidDvcsComboBox.SelectedIndex = 0;
            AudDvcsComboBox.SelectedIndex = 0;
        }

        private void FindDevices()
        {
            var vidDevices = EncoderDevices.FindDevices(EncoderDeviceType.Video);
            var audDevices = EncoderDevices.FindDevices(EncoderDeviceType.Audio);

            foreach (EncoderDevice dvc in vidDevices)
            {
                VidDvcsComboBox.Items.Add(dvc.Name);
            }

            foreach (EncoderDevice dvc in audDevices)
            {
                AudDvcsComboBox.Items.Add(dvc.Name);
            }

        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Display webcam video on control.
                webCamCtrl.StartCapture();
            }
            catch (Microsoft.Expression.Encoder.SystemErrorException ex)
            {
                MessageBox.Show("Device is in use by another application");
            }
        }

        private void EndButton_Click(object sender, RoutedEventArgs e)
        {
            // Stop the display of webcam video.
            webCamCtrl.StopCapture();
        }

        private void RecordButton_Click(object sender, RoutedEventArgs e)
        {
            // Start recording of webcam video to harddisk.
            webCamCtrl.StartRecording();
        }

        private void StopRecordButton_Click(object sender, RoutedEventArgs e)
        {
            // Stop recording of webcam video to harddisk.
            webCamCtrl.StopRecording();
        }        
       
    }
}

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.

Webcam

The following are the members of interest in class Webcam;

Properties

  Name Description Type
PropertyIcon.png VideoDirectory Gets or Sets the folder where the recorded webcam video will be saved. This is a dependency property. String
PropertyIcon.png 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
PropertyIcon.png VideoDevice Gets or Sets the name of the video device to be used. This is a dependency property. String
PropertyIcon.png AudioDevice Gets or Sets the name of the audio device to be used. This is a dependency property. String
PropertyIcon.png IsRecording Gets a value indicating whether video recording is taking place. This is a read-only property. Boolean

Methods

  Name Description
MethodIcon.png StartCapture Displays webcam video on control. (Throws a Microsoft.Expression.Encoder.SystemErrorException if a specified device is already in use by another application)
MethodIcon.png StopCapture Stops the capturing/display of webcam video. (Stops any current recording of webcam video)
MethodIcon.png 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)
MethodIcon.png 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
        ' Set dimensions of WinForm Panel to current dimensions
        ' of the UserControl.
        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;

    ''' <summary>
    ''' Gets or Sets the name of the video device to be used.
    ''' </summary>    
    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

            Try
                CType(source, Webcam).Display()
            Catch ex As Microsoft.Expression.Encoder.SystemErrorException
                Exit Sub
            End Try
        End If
    End Sub

The StartCapture method displays the webcam video in the WinForm Panel, if the necessary properties are set;

    ''' <summary>
    ''' Display webcam video on control.
    ''' </summary>
    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
    
    ' Display video from webcam.
    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;

    ''' <summary>
    ''' Starts the recording of webcam video to a video file.
    ''' </summary>
    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 is true then it means the control is capturing video 
            ' from the webcam.
            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.

推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架
新浪微博粉丝精灵,刷粉丝、刷评论、刷转发、企业商家微博营销必备工具"