Pull to refresh

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

Reading time9 min
Views4.7K

Введение

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

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

Articles