So, by now you should have heard that Silverlight 4 Beta was released at PDC 2009. One of the most interesting and fun features included in the release is the ability for you to access a users webcam and microphone. Even a fellow ElegantCoder wrote a short post on it. But I wanted to go into a little more detail. So I am going to show you have to access a list of webcams and microphones, capture video, and then take pictures and show them to the user. But, before I can show you how to use them, you have to have the Silverlight 4 Beta framework installed.
Start here:
- Visual Studio 2010 Beta 2 or Visual Web Developer Express 2010 Beta 2 (pick one)
- Silverlight Tools for Visual Studio 2010
- Silverlight 4 SDK CHM (offline documentation) ? online documentation here
- Updated Silverlight Toolkit for Silverlight 4
You can either download the source and start playing around immediately, or you can read through the post and then download the source.
First off lets start out with our view box (this spot is where our video will be shown). First create a rectangle and give it a meaningful name. I called mine ViewBox. Make it the size of the video you want to show, as you can see mine is 640×480.
<Rectangle x:Name="ViewBox" Width="640" Height="480" Fill="White"/>
Now lets create some combo boxes to show the available webcams and microphones on the users machine. I created a item template and used the FriendlyName as the binding text. The FriendlyName is the name/description of the device.
<TextBlock Margin="5" HorizontalAlignment="Center" Text="WebCam" Grid.Column="0" Grid.Row="0" />
<ComboBox x:Name="WebCamList" Grid.Row="1" Grid.Column="0">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<TextBlock Margin="5" HorizontalAlignment="Center" Text="Microphone" Grid.Column="1" Grid.Row="0" />
<ComboBox x:Name="MicrophoneList" Grid.Row="1" Grid.Column="1">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Now lets create some buttons to start capturing our video, stop capturing the video, and one to take some pictures.
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Margin="5" x:Name="btnStartCapture" Content="Start Capture" Click="btnStartCapture_Click" />
<Button Margin="5" x:Name="btnStopCapture" Content="Stop Capture" Click="btnStopCapture_Click" />
<Button Margin="5" x:Name="btnTakePicture" Content="Take Picture" Click="btnTakePicture_Click" />
</StackPanel>
Next, lets create a scroll viewer to hold a collection of pictures we take.
<ScrollViewer Width="800" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto">
<ItemsControl x:Name="Pictures">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Margin="5" Stretch="UniformToFill" Height="240" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
Now that we have our UI finished up we need to start adding some code. The first thing we need to do is create some private members. Once will be our capture source and the other will be a collection to hold our pictures. I am using an ObservableCollection so I don?t have to worry about manually update the UI when items are added to it.
CaptureSource _captureSource;
ObservableCollection<WriteableBitmap> _pictures = new ObservableCollection<WriteableBitmap>();
Now that we have our private members, lets hook into the form?s loaded event and add some code. The first thing we need to do is create a new instance of our capture source. Next, we get a list of all our available webcams and microphones and add them to our combo boxes accordingly. Last we set the Pictures ScrollViewer items source to our private member _pictures. You should have something like the following.
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
// creating a new capture source
_captureSource = new CaptureSource();
// get list of the web cams
WebCamList.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();
WebCamList.SelectedIndex = 0;
// get list of microphones
MicrophoneList.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();
MicrophoneList.SelectedIndex = 0;
Pictures.ItemsSource = _pictures;
}
Now, lets handle the click event for our start capturing button. First thing we hav to do is stop and device that may be capturing. Now, we need to set our capture source?s video and audio capture instances from the available options in our combo boxes. We need to create a VisualBrush, this is what will be the video. We create a new instance of the VisualBrush and set the source to our captureSource. Next, we set the Fill of our rectangle to the VisualBrush. now, the magic does happen until the next part. You need to request permission from the user to use their webcam. Once you have it you just start capturing.
private void btnStartCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
// stop whatever device may be capturing
_captureSource.Stop();
_captureSource.VideoCaptureDevice = (VideoCaptureDevice)WebCamList.SelectedItem;
_captureSource.AudioCaptureDevice = (AudioCaptureDevice)MicrophoneList.SelectedItem;
VideoBrush vidBrush = new VideoBrush();
vidBrush.SetSource(_captureSource);
ViewBox.Fill = vidBrush;
// request access to webcam and audio devices
if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
{
_captureSource.Start();
}
}
}
Now, lets handle the stop capture buttons click event. This basically halts all video capturing and is very easy to implement.
private void btnStopCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.Stop();
}
}
The last thing we need to do is enable taking pictures. So, handle the click event for the take picture button. Luckily for us, the capture source has built in support for capturing images asynchronously.
private void btnTakePicture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.AsyncCaptureImage((image) =>
{
_pictures.Add(image);
});
}
}
That?s it. You have now created your first Silverlight application that can communicate with a users webcam and microphone. Think of all the possibilities. Download the code, play with it and have fun.
Wow. Now that was quick!