Главная > Silverlight > Работа с веб камерой и микрофоном в Silverlight 4

Работа с веб камерой и микрофоном в Silverlight 4

Введение

То, что многие Сильверлайт разработчики давно ждали, произошло. Четвёртый Сильверлайт позволяет получить доступ к веб камере и микрофону. И пусть это не является революцией, в отличие от многих других новых возможностей (конкурирующие технологии поддерживали камеру и микрофон уже давно), но мощь, простота и удобство нового 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» через веб камеру):

image

Но, перейдём к исходному коду страницы 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».

image

Можете поменять устройства по-умолчанию или отставить их прежними. А мы пока переходим назад к исходному коду.

Итак, теперь мы добавим в класс 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()).

При запросе разрешений, пользователь увидит похожее диалоговое окно:

image

И если он нажмёт «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.

Теперь приложение можно запустить. А если что-то можно сделать, то давайте сделаем это. Запустите приложение и попробуйте снять несколько моментальных снимков, не зря же мы писали данную функциональность.

image

This website uses IntenseDebate comments, but they are not currently loaded because either your browser doesn't support JavaScript, or they didn't load fast enough.

  1. Пока что нет комментариев.
  1. 13 Январь 2010 в 00:46 | #1
  2. 4 Апрель 2010 в 19:04 | #2
Необходимо войти на сайт, чтобы написать комментарий.