Веб-камера

99

Приложение Silverlight может принимать аудио- и видеоданные от веб-камеры и микрофона. Это позволяет создавать новые типы мощных приложений для Интернета, включая чаты и видеоконференции в реальном времени и многопользовательские компьютерные игры. Однако в Silverlight эта задача довольно трудная. Для создания реалистичного приложения, принимающего звуковые и видеопотоки, записанные пользователем, вам придется написать много страниц кода, выполнять кодирование и декодирование, подключить внешние библиотеки для поддержки необходимых форматов и т.п.

Ниже будет продемонстрирована поддержка веб-камеры на клиентской и серверной сторонах приложения Silverlight. Вы научитесь использовать встроенные средства приема пользовательских данных для решения сравнительно простых задач, таких как добавление "живого" видео на страницу.

Доступ к устройствам записи

Для применения средств поддержки веб-камеры и микрофона вам не придется беспокоиться о конфигурации оборудования или спецификациях устройств. Silverlight автоматически распознает источники аудио- и видеозаписи и сделает их доступными для приложения. Чтобы увидеть, что надстройка Silverlight нашла на вашем компьютере, щелкните правой кнопкой мыши на приложении Silverlight и выберите в открывшемся контекстном меню команду Silverlight. Активизируйте вкладку Веб-камера и микрофон:

Silverlight - распознование микрофона и веб-камеры

Если к компьютеру подключено несколько устройств любого типа, можно выбрать, какое из них будет использоваться надстройкой Silverlight по умолчанию. Обычно Silverlight руководствуется указаниями операционной системы, которая сама назначает устройства, используемые по умолчанию. Эти устройства приведены в раскрывающихся списках при первом открытии окна "Конфигурация Microsoft Silverlight".

Все операции записи начинаются с класса CaptureDeviceConfiguration, расположенного в пространстве имен System.Windows.Media. Этот класс предоставляет набор статических членов, которые можно использовать для управления записью.

Свойство AllowedDeviceAccess возвращает значение true, если пользователь разрешил приложению обращаться к устройствам аудио- и видеозаписи. Сначала это свойство равно false, и приложение должно вызвать метод RequestDeviceAccess(), который предложит пользователю подтвердить необходимые разрешения:

Пользователь должен разрешить доступ приложения к устройствам записи

Если пользователь установит флажок "Запомнить мой ответ" и щелкнет на кнопке Да, приложение будет автоматически получать разрешение при следующем запуске без вызова метода ReguestDeviceAccess().

Обычно в приложении два этапа получения разрешения (проверка, имеет ли приложение разрешение, и вывод окна запроса разрешения) объединены в один блок следующим образом:

if (CaptureDeviceConfiguration.AllowedDeviceAccess ||
        CaptureDeviceConfiguration.RequestDeviceAccess())
{
        // Доступ разрешен
}
else 
{
        // Значение AllowedDeviceAccess равно false (это означает, 
        // что разрешения не было), и метод ReguestDeviceAccess() 
        // вернул false (это означает, что пользователь отклонил 
        // запрос). Доступ невозможен. 
}

Обратите внимание на то, что в данном коде используется блок else, а не просто дизъюнкция. Благодаря этому проверка выполняется оптимальным образом: если свойство AllowedDeviceAccess уже имеет значение true, второе условие не оценивается и метод RequestDeviceAccess() не вызывается.

Когда разрешение получено, можно вызвать метод GetDefaultVideoCaptureDevice() для получения видеоустройства, используемого по умолчанию, или метод GetDafaultAudioDevice() для получения аудиоустройства. Получаемые объекты имеют типы VideoCaptureDevice и AudioCaptureDevice. Каждый из этих объектов предоставляет всего несколько свойств: FriendlyName, SupportedFormats, AudioFrameSize (для аудио) и DesiredFormat.

Silverlight не ограничивает приложение аудио- и видеоисточниками, установленными по умолчанию. Приложение может получить доступ ко всем поддерживаемым устройствам записи с помощью методов GetAvailableVideoCaptureDevices() и GetAvailableAudioCaptureDevices(). Оба этих метода возвращают коллекции.

Однако, обычно о конкретных аудио- и видеоустройствах доступно очень мало информации. К тому же код не может заранее знать о конфигурации оборудования. По этим причинам приложение очень редко выбирает устройство из коллекции на основе некоторой программной логики. Эти методы полезны главным образом для того, чтобы предоставить выбор пользователю. Например, можно связать результаты, возвращаемые методом GetAvailableVideoCaptureDevices(), со списком, отображающим значения FriendlyName каждого устройства, и подключить устройство, выбранное пользователем.

Выше были упомянуты все методы класса CaptureDeviceConfiguration. Этот класс предоставляет разработчику все инструменты, необходимые для запроса доступа к устройству и получения информации о каждом доступном аудио- и видеоустройстве. Однако для использования устройства необходим также класс CaptureSource, рассматриваемый в следующем разделе.

Базовые средства поддержки веб-камеры

В Silverlight встроены средства решения двух задач, имеющих отношение к веб-камере:

Ниже приводится пример приложения, в котором решаются обе эти задачи.

Для использования любого из этих средств сначала нужно создать объект CaptureSource. Он предоставляет методы Start() и Stop(), которые позволяют управлять включением и отключением записи звука и видео. Кроме того, объект CaptureSource имеет свойство State, которое сообщает о том, что сейчас делает этот объект. Свойство State возвращает перечисление CaptureStates, имеющее значения Started, Stopped и Failed.

Обычно объект CaptureSource определяют как поле, чтобы он был доступен для всех обработчиков событий:

private CaptureSource capture = new CaptureSource();

Ниже представлена разметка окна и обработчики событий клика по кнопкам, в которых определяется работа с веб-камерой:

<Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions></Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="3*"></ColumnDefinition>
            <ColumnDefinition Width="Auto"></ColumnDefinition>
            <ColumnDefinition Width="2*"></ColumnDefinition>
        </Grid.ColumnDefinitions>

        <Rectangle x:Name="rectWebcamDisplay" Margin="10"></Rectangle>
        <StackPanel Grid.Column="1" VerticalAlignment="Center">
            <Button x:Name="cmdStartCapture" Margin="0,3" Padding="5" Content="Пуск" Click="cmdStartCapture_Click"></Button>
            <Button x:Name="cmdSnapshot" Margin="0,3" Padding="5" Content="Снимок -->" Click="cmdSnapshot_Click"></Button>
            <Button x:Name="cmdStopCapture" Margin="0,3" Padding="5" Content="Стоп" Click="cmdStopCapture_Click"></Button>
        </StackPanel>
        <Border Grid.Column="2" Margin="10" BorderBrush="Red" BorderThickness="2">
            <Image x:Name="imgSnapshot" HorizontalAlignment="Center" VerticalAlignment="Center"></Image>
        </Border>

</Grid>
        private void cmdStartCapture_Click(object sender, RoutedEventArgs e)
        {
            if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
            {
                // Рекомендуется сначала вызвать метод Stop(), даже если 
                // запись не выполняется, потому что попытка вызвать метод 
                // Start() во время записи приведет к появлению исключения
                capture.Stop();

                // Определение веб-камеры, установленной по умолчанию              
                capture.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
                if (capture.VideoCaptureDevice == null)
                {
                    MessageBox.Show("Нет устройства видеозаписи!");
                }
                else
                {
                    // Запуск записи
                    capture.Start();

                    // Присвоение видеопотока кисти VideoBrush
                    VideoBrush videoBrush = new VideoBrush();
                    videoBrush.Stretch = Stretch.Uniform;
                    videoBrush.SetSource(capture);

                    // Применение кисти VideoBrush для заливки прямоугольника
                    rectWebcamDisplay.Fill = videoBrush;
                }
            }
        }

        private void cmdStopCapture_Click(object sender, RoutedEventArgs e)
        {
            // Остановить запись
            capture.Stop();
        }

        private void cmdSnapshot_Click(object sender, RoutedEventArgs e)
        {
            // Создание скриншота из видео
            if (capture.State == CaptureState.Started)
            {
                capture.CaptureImageCompleted += capture_CaptureImageCompleted;
                capture.CaptureImageAsync();
            }
        }

        private void capture_CaptureImageCompleted(object sender, CaptureImageCompletedEventArgs e)
        {
            // Отображение скриншота в элементе Image
            imgSnapshot.Source = e.Result;
        }
Базовое приложение с веб-камерой

В данном коде нетрудно заметить намек на дополнительные возможности. Например, имея растровую карту одного кадра, можно сохранить ее (возможно, в изолированном хранилище или базе данных), применить к ней эффекты раскрашивания пикселей, выгрузить ее в веб-службу и т.п.

Однако, прежде чем сохранять или передавать куда-либо записанные кадры, серьезно подумайте об их объеме, потому что "сырые" растровые карты имеют ужасающе огромные размеры. Использовать их в таком виде — явное расточительство ресурсов, да и заставлять пользователя долго ждать окончания загрузки очень не рекомендуется. Приложение должно преобразовать растровую карту WriteableBitmap в какой-нибудь другой формат (лучше всего в PNG или JPG), прежде чем сохранить или передать ее.

К сожалению, нужные для этого средства преобразования не встроены в Silverlight. Их можно найти в дополнительных библиотеках, таких как fjcore или .NET Image Tools.

Пройди тесты
Лучший чат для C# программистов