Введение
То, что многие Сильверлайт разработчики давно ждали, произошло. Четвёртый Сильверлайт позволяет получить доступ к веб камере и микрофону. И пусть это не является революцией, в отличие от многих других новых возможностей (конкурирующие технологии поддерживали камеру и микрофон уже давно), но мощь, простота и удобство нового API заслуживают того, чтобы на эту часть функциональности четвёртого Сильверлайта Вы обратили самое пристальное внимание.Работа с веб камерой и микрофоном
Итак, веб камера и микрофон на компьютере пользователя могут быть, а могут и отсутствовать. Также бывают ситуации, когда есть несколько источников видео и звука. Для того, чтобы определить с какми устройствами мы будем работать, а также в случае необходимости запросить у пользователя доступ к этим устройствам (Сильверлайт не позволяет без явного на то разрешения пользователя получить доступ к веб камере или микрофону), сществует статический класс CaptureDeviceConfiguration. Давайте посмотрим как с этим классом работать. Но предварительно создадим новый проект Сильверлайт приложения в Visual Studio 2010 и добавим на страницу MainPage.xaml некоторую XAML разметку:<StackPanel Orientation="Vertical" VerticalAlignment="Center"
HorizontalAlignment="Center">
<Rectangle Width="320" Height="240" x:Name="videoRect"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<ListBox x:Name="VideoSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox x:Name="AudioSources">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding FriendlyName}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button Margin="5" Content="Начать захват" x:Name="startCapture"/>
<Button Margin="5" Content="Остановить захват" x:Name="endCapture"/>
</StackPanel>
</StackPanel>
* This source code was highlighted with Source Code Highlighter.
В данной разметке стоит обратить внимание на прямоугольник (Rectangle) «videoRect», именно в нём и будет отображаться видео с веб камеры.
Ниже находятся два списка (ListBox) «VideoSources» и «AudioSources», в них будут отображаться имена устройств источников видео и звука. Пользователь сможет выбрать нужное устройство, щёлкнув на его имя. Кроме того на странице присутствуют две кнопки, которые мы будем использовать для начала и остановки захвата с обоих устройств.
Работающее приложение будет выглядить следующим образом (на скриншоте я демонстрирую значок «спроси меня про Silverlight» через веб камеру):

Но, перейдём к исходному коду страницы MainPage.xaml на языке C#. И в конструкторе подпишемся на событие загрузки данной страницы:
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
* This source code was highlighted with Source Code Highlighter.
В обработчике события получим доступные устройства и отобразим их в наших списках VideoSources и AudioSources соответственно:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
VideoSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();
AudioSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();
}
* This source code was highlighted with Source Code Highlighter.
Класс CaptureDeviceConfiguration позволяет получить список всех устройств видео и аудио захвата, а также устройства по-умолчанию с помощью методов GetDefaultVideoCaptureDevice и GetDefaultAudioCaptureDevice соответственно. Устройства по-умолчанию устанавливаются автоматически, но пользователь может их настроить с помощью утилиты «Microsoft Silverlight Configuration». Чтобы запустить данную утилиту щёлкните правой кнопкой мыши на любом Сильверлайт приложении и выберите в контекстном меню пункт «Silverlight». Откроется нужное нам окно, в котором в четвёртой версии Сильверлайта появилась новая вкладка «Webcam / Mic».

Можете поменять устройства по-умолчанию или отставить их прежними. А мы пока переходим назад к исходному коду.
Итак, теперь мы добавим в класс MainPage поле типа CaptureSource. Объекты данного класса используются для захвата видео и звука с соответствующих устройств.
private CaptureSource _captureSource;
* This source code was highlighted with Source Code Highlighter.
В методе MainPage_Loaded инициализируем только что созданное поле:
_captureSource = new CaptureSource();
* This source code was highlighted with Source Code Highlighter.
Теперь определим действия, выполняемые при нажатии кнопки начала захвата. Для этого добавим обработчик события «Click» соответствующей кнопки (startCapture) и в обработчике напишем следующий код:
private void startCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.Stop();
_captureSource.VideoCaptureDevice = (VideoCaptureDevice)VideoSources.SelectedItem;
_captureSource.AudioCaptureDevice = (AudioCaptureDevice)AudioSources.SelectedItem;
VideoBrush vidBrush = new VideoBrush();
vidBrush.SetSource(_captureSource);
videoRect.Fill = vidBrush;
if (CaptureDeviceConfiguration.AllowedDeviceAccess ||
CaptureDeviceConfiguration.RequestDeviceAccess())
{
_captureSource.Start();
}
}
}
* This source code was highlighted with Source Code Highlighter.
Вначале мы проверяем, что медиа источник _captureSource не равен null, и останавливаем весь текущий захват для данного источника. После этого мы устанавливаем для _captureSource выбранные пользователем устройства захвата видео и звука, и создаём кисть (vidBrush), которая будет в реальном времени заполнять прямоугольник videoRect видео, получаемым с веб камеры.
Но это ещё не всё. Перед тем, как начать захват, нам надо проверить, что у нас есть нужные права доступа (CaptureDeviceConfiguration.AllowedDeviceAccess) и в случае их отсутствия запросить доступ у пользователя (CaptureDeviceConfiguration.RequestDeviceAccess()).
При запросе разрешений, пользователь увидит похожее диалоговое окно:

И если он нажмёт «Yes», мы сможем начать захват (_captureSource.Start()). В противном случем остаётся только корить судьбу за недоверчивых пользователей.
Обработчик кнопки остановки захвата значительно проще. Его код достаточно очевиден:
private void endCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.Stop();
}
}
* This source code was highlighted with Source Code Highlighter.
Всё, базовое приложение готово. Запустите его и у Вас появится уникальная возможность посмотреть на мир глазами веб камеры.
Далее приводится полный C# код страницы MainPage:
public partial class MainPage : UserControl
{
private CaptureSource _captureSource;
public MainPage()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
VideoSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices();
AudioSources.ItemsSource = CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices();
_captureSource = new CaptureSource();
}
private void startCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.Stop();
_captureSource.VideoCaptureDevice = (VideoCaptureDevice)VideoSources.SelectedItem;
_captureSource.AudioCaptureDevice = (AudioCaptureDevice)AudioSources.SelectedItem;
VideoBrush vidBrush = new VideoBrush();
vidBrush.SetSource(_captureSource);
videoRect.Fill = vidBrush;
if (CaptureDeviceConfiguration.AllowedDeviceAccess ||
CaptureDeviceConfiguration.RequestDeviceAccess())
{
_captureSource.Start();
}
}
}
private void endCapture_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.Stop();
}
}
}
* This source code was highlighted with Source Code Highlighter.
Снятие моментальных снимков
Приложение работает. Но хочется чего-то ещё. Например, хочется нажать кнопку и сохранить в виде картинки то, что в данный момент показывает камера. Нет ничего проще. В первую очередь нам надо добавить кнопку.<Button Margin="5" Content="Snapshot" x:Name="takeSnapshot" Click="takeSnapshot_Click"/>
* This source code was highlighted with Source Code Highlighter.
Также необходимо создать обработчик события нажатия на данную кнопку. И добавить в XAML разметку код для отображения наших моментальных снимков:
<ScrollViewer Width="400" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Auto"
HorizontalAlignment="Center">
<ItemsControl x:Name="snapshots">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}" Margin="5" Height="50" Stretch="UniformToFill"></Image>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
* This source code was highlighted with Source Code Highlighter.
Мы создаём область прокрутки (ScrollViewer), где будут находиться моментальные снимки. За их отображение отвечает элемент ItemsControl.
Добавим в класс MainPage поле «_images», в котором будут храниться снимки:
private ObservableCollection<WriteableBitmap> _images = new ObservableCollection<WriteableBitmap>();
* This source code was highlighted with Source Code Highlighter.
А в обработчике нажатия на кнопку «takeSnapshot» и напишем следующий код:
private void takeSnapshot_Click(object sender, RoutedEventArgs e)
{
if (_captureSource != null)
{
_captureSource.AsyncCaptureImage((snapImage) =>
{
_images.Add(snapImage);
});
}
}
* This source code was highlighted with Source Code Highlighter.
Здесь мы асинхронно добавляем в коллекцию снимков новый моментальный снимок.
Всё, что теперь нам осталось сделать – это связать коллекцию «_images» с визуальным представлением. Для этого в методе MainPage_Loaded допишем следующий код:
snapshots.ItemsSource = _images;
* This source code was highlighted with Source Code Highlighter.
Теперь приложение можно запустить. А если что-то можно сделать, то давайте сделаем это. Запустите приложение и попробуйте снять несколько моментальных снимков, не зря же мы писали данную функциональность.

Доступен скринкаст на английском на данную тему: смотреть