Главная » Silverlight » Звук, видео и глубокое зумирование

0

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

В этой главе рассматриваются технологии встраивания аудио- и видеосодержи­мого в приложения Silverlight и оптимальные способы кодирования и хостирования видеофайлов. Вы узнаете о том, как с помощью кисти VideoBrush можно создавать впечатляющие эффекты, такие как заполнение текста видеосодержимым и зеркальное отражение видеосодержимого. В конце главы рассматривается глубокое зумирование — интерактивная мультимедийная технология, позволяющая просматривать огромные изображения в реальном времени.

Новые средства. В Silverlight продолжается усовершенствование средств поддержки аудио и видео. Программный интерфейс в Silverlight 3 остался прежним (например, элементы MediaElement и VideoBrush не изменились), однако "под капотом" произошли существенные изменения. В частности, добавлена поддержка видеофайлов Н.264. Кроме того, в Silverlight 3 добавлен низкоуровневый конвейер аудио и видео, позволяющий независимым разработчикам создавать инфраструктуру аудио и пользовательские кодировщики.. Поддерживаемые форматы мультимедийных файлов

Надстройка Silverlight должна обеспечивать совместимость с разными операционны­ми системами и браузерами, поэтому она не может поддерживать все форматы мульти­медийных файлов, доступные для настольных приложений, таких как Windows Media Player. Для разработки аудио- и видеосодержимого Silverlight нужно знать форматы мультимедийных файлов, доступные для надстройки Silverlight.

Надстройка Silverlight поддерживает следующие типы аудиофайлов:

•    формат WMA, версии 7, 8 и 9;

•    формат МРЗ с постоянным или переменным битрейтом от 8 до 320 Кбит/с.

Примечание. В отличие от WPF, надстройка Silverlight не поддерживает аудиоформат WAV. Кроме того, она не может воспроизводить музыкальные файлы MIDI.

Ниже перечислены форматы видео, поддерживаемые надстройкой Silverlight:

•   Windows Media Video 7 (WMV1);

•   Windows Media Video 8 (WMV2);

•   Windows Media Video 9 (WMV3);

•   Windows Media Video Advanced Profile, non-VC-1 (WMVA);

•   Windows Media Video Advanced Profile, VC-1 (WMVC1);

•    H.264 (видео) и AAC (аудио), известные также, как MPEG-4 Part 10 и MPEG-4 AVC.

Формат Windows Media Video в большинстве случаев можно распознать по расши­рению .wmv. Другие видеоформаты, например MPEG и QuickTime, не поддерживаются.

Последние два формата (VC 1 и Н.264) — широко распространенные коммерческие стандарты, используемые в технологиях Blu-ray, HD DVD и Xbox 360. Их рекомендует­ся применять в приложениях Silverlight. Конечно, эти стандарты поддерживают раз­ные битрейты и разрешения, поэтому приложение Silverlight не обязательно должно поддерживать высококачественное DVD-видео только потому, что в нем использует­ся VC 1 или Н.264.

Надстройка Silverlight не поддерживает другие форматы Windows Media (такие, как Windows Media Screen, Windows Media Audio Professional и Windows Media Voice) и ком­бинацию Windows Media Video с аудиосодержимым МРЗ. И наконец, Silverlight не под­держивает видеофайлы с нечетным разрешением, например 127×135.

Примечание. Добавить аудиосодержимое в приложение Silverlight несложно, потому что оно может храниться в любом файле МРЗ. Использовать видеофайлы сложнее. Нужно не только выбрать один из поддерживаемых форматов WMV, но и тщательно сбалансировать качество видеосодержимого и объем загрузки, доступный для пользователей. Далее рассматривается кодирование видео в приложениях Silverlight, однако сначала обсудим базовые аудиосредства.

Элемент MediaElement

Все встроенные в Silverlight средства звука и видео находятся в единственном клас­се MediaElement.

Как и другие элементы, MediaElement размещается непосредственно на пользо­вательском интерфейсе. Если MediaElement используется для воспроизведения зву­ка, этот факт несущественен, потому что тогда элемент невидим. При использовании MediaElement для воспроизведения видео он размещается там, где должно быть вы­ведено окно.

Для воспроизведения звука необходим дескриптор MediaElement.

<MediaElement Source="test.mp3"x/MediaElement>

После загрузки страницы она загружает файл test.mp3 и автоматически начинает воспроизводить его.

Конечно, приложение Silverlight должно найти файл test .трЗ. В классе MediaElement используется та же система адресов URL, что и в классе Image. Это означает, что меди- афайл можно внедрить в пакет ХАР или развернуть в Интернете. В общем случае луч­ше хранить медиафайлы отдельно, потому что они значительно увеличивают размеры и время загрузки приложения.

Примечание. При первом добавлении медиафайла (например, test.mp3) в проект программа Visual Studio присваивает его свойству Build Action (Операция построения) значение None, а свойству Copy То Output Directory (Копировать в выходную папку) — значение Copy always (Всегда копировать). Чтобы разместить медиафайл в пакете ХАР, присвойте свойству Build Action значение Resource.

Управление воспроизведением

В предыдущем примере приложение начинает воспроизводить аудиофайл немедлен­но после загрузки страницы, содержащей элемент MediaElement. Аудиофайл воспроиз­водится, пока не закончится его время.

Пример довольно ограниченный, потому что обычно необходима возможность управлять воспроизведением. Например, иногда желательно начать воспроизведение в заданный момент времени, повторять воспроизведение и т.д. Управлять воспроизве­дением можно с помощью методов класса MediaElement, вызываемых в определенные моменты времени.

Поведение элемента MediaElement в первый момент времени определяется его свой­ством AutoPlay. Если оно равно False, аудиофайл будет загружен, но запуск воспроиз­ведения будет управляться кодом.

<MediaElement x:Name="media" Source="test.mp3"

AutoPlay="False"x/MediaElement>

В этом случае элементу MediaElement должно быть присвоено имя, чтобы он мог вза­имодействовать с кодом. В общем случае взаимодействие заключается в вызове мето­дов Play (), Pause () и Stop О . Можно также применить свойство Position, для пере­мещения текущей позиции в аудиофайле, или метод SetSource (), для загрузки нового содержимого из потока. Метод SetSource () полезен при асинхронной загрузке медиа- файлов с помощью класса WebClient (см. главу 6).

Ниже приведен обработчик щелчка на кнопке, устанавливающий текущую позицию в начало аудиофайла и запускающий воспроизведение.

private void cmdPlay_Click(object sender, RoutedEventArgs e)

{

media.Position = TimeSpan.Zero; media.Play();

}

Если код обработчика выполняется во время воспроизведения аудиофайла, первая строка устанавливает позицию в начало и воспроизведение продолжается с этой пози­ции, а вторая строка не влияет на приложение, потому что медиафайл уже выполняется.

Примечание. В зависимости от типа медиафайла, иногда желательно проверить свойства CanPause и CanSeek перед попыткой временно остановить воспроизведение или перейти в другую позицию. Некоторые потоковые медиафайлы не поддерживают режим паузы и переход в новую позицию.

Обработка ошибок

Элемент MediaElement не генерирует исключение, когда не может найти или загру­зить медиафайл. Разработчик приложения должен обеспечить реагирование на собы­тие MediaFailed. Для этого нужно добавить имя обработчика в дескриптор элемента.

<MediaElement . . . MediaFailed="media_MediaFailed"> </MediaElement>

В обработчике для получения объекта исключения, содержащего описание про­блемы, можно использовать свойство ExceptionRoutedEventArgs.ErrorException. Например, приведенный ниже код обработчика выводит сообщение об ошибке.

private void media_MediaFailed(object sender,

ExceptionRoutedEventArgs e)

{

lblErrorText.Content = e.ErrorException.Message;

}

Одновременное воспроизведение нескольких источников

Элемент MediaElement может воспроизводить только один медиафайл. Если изме­нить свойство Source или вызвать метод SetSource О , текущее воспроизведение будет немедленно остановлено. Однако это ограничение не касается надстройки Silverlight в целом. Фактически Silverlight может воспроизводить одновременно произвольное количество медиафайлов, нужно лишь ассоциировать каждый со своим элементом MediaElement.

Существует два способа воспроизведения нескольких звуков. Первый состоит в соз­дании всех необходимых объектов MediaElement во время разработки. Этот способ по­лезен, когда планируется повторное использование нескольких объектов MediaElement.

Например, можно определить два объекта MediaElement и переключаться между ними каждый раз, когда нужно воспроизводить новый звук. Отслеживать объект, ис­пользовавшийся последним, можно с помощью булевой переменной, определенной в классе страницы. Чтобы облегчить использование этого способа, сохраните имена аудиофайлов в свойствах Tag соответствующих элементов. Тогда код обработки собы­тия сможет прочитать имя файла в свойстве Tag, найти нужный объект MediaElement, установить его свойство Source и вызвать метод Play (). Когда используется два объек­та MediaElement, воспроизводить одновременно можно будет только два звука. Это до­пустимый компромисс, если ожидается, что пользователь не захочет слышать третий звук (обычно двух звуков достаточно для создания невообразимой какофонии).

Второй способ воспроизведения нескольких звуков состоит в динамическом создании каждого объекта MediaElement по мере необходимости. Трудоемкость разработки немно­го увеличивается, однако разница небольшая (если одновременно воспроизводится не более нескольких аудиофайлов). При создании объекта MediaElement в коде, необходимо добавить его в контейнер, определенный в приложении. Если свойство AutoPlay не уста­новить (т.е. оставить значение true, присвоенное по умолчанию), воспроизведение начнет­ся немедленно после добавления. Если же присвоить свойству AutoPlay значение false, для запуска воспроизведения нужно вызвать метод Play (). По окончании воспроизведе­ния рекомендуется удалить объект MediaElement в обработчике события MediaEnded.

Ниже приведен код кнопки, запускающей воспроизведение одного и того же аудио­файла при каждом щелчке на кнопке.

private void cmdPlay_Click(object sender, RoutedEventArgs e)

{

MediaElement media = new MediaElement();

media.Source = new Uri("test.mp3", UriKind.Relative);

media.MediaEnded += new RoutedEventHandler(media_MediaEnded);

LayoutRoot.Children.Add(media);

}

private void media_MediaEnded(object sender, RoutedEventArgs e)

{

LayoutRoot.Children.Remove((MediaElement)

sender);

}

Чтобы облегчить отслеживание нескольких динамически генерируемых объектов Media- Element, добавьте их все в один контейнер, специально предназначенный для них (напри­мер, невидимый контейнер StackPanel). Это по­зволит быстро проверить все воспроизводимые медиафайлы и остановить их воспроизведение. На рис. 11.1 показан пример одновременного воспроизведения многих аудиофайлов. Выводимый на экран счетчик изменяется при каждом добавлении объекта MediaElement в невидимый контейнер StackPanel или удалении из него.

Изменение громкости, баланса и позиции

Элемент MediaElement предоставляет ряд свойств, позволяющих программно управ­лять воспроизведением. Наиболее полезны следующие свойства.

•       Volume. Громкость воспроизведения. Допустимы значения от 0 (полная тишина) до 1 (максимальная громкость). По умолчанию установлено значение 0.5. Что­бы временно отключить звук, не переходя в режим паузы и не изменяя значение Volume, присвойте свойству IsMuted значение true.

•       Balance. Баланс левого и правого каналов. Допустимы значения от -1 (работает только левый динамик) до 1 (работает только правый динамик).

•       CurrentState. Текущее состояние проигрывателя. Допустимы значения Playing (аудиофайл воспроизводится), Paused (режим паузы), Stopped (воспроизведение остановлено), Opening (аудиофайл загружается), Buffering (содержимое записы­вается в буфер), AcquiringLicense (выполняется запрос на лицензию содержимо­го DRM) и Closed (аудиофайла нет).

•       Position. Текущая позиция в аудиофайле. Это свойство содержит значение типа TimeSpan. С его помощью можно начать воспроизведение с любой позиции в аудиофайле.

Рис. 11.2. Управление воспроизведением

В верхней части окна размещены три кнопки, при щелчке на которых вызываются методы Play (), Stop () и Pause () элемента MediaElement.

Ниже расположены два ползунка, регулирующие громкость и баланс. Каждому пол­зунку присвоен определенный диапазон: от 0 до 1 и от -1 до 1.

<Slider Grid.Column="l" x:Name="sliderVolume" Minimum="0" Maximum="l" Value="0.5" ValueChanged="sliderVolume_ValueChanged" ></Slider>

<Slider Grid.Row="l" Grid.Column="l" x:Name="sliderBalance" Minimum="-1" Maximum="l"

ValueChanged="sliderBalance_ValueChanged"x/Slider>

Когда пользователь перетаскивает ползунок, изменяемое значение применяется в объекте MediaElement.

private void sliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

{

media.Volume = sliderVolume.Value;

)

private void sliderBalance_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

{

media.Balance = sliderBalance.Value;

}

Третий ползунок позволяет быстро перейти в новую позицию. Он фактически состо­ит из двух отдельных ползунков, наложенных один поверх другого. Пользователь пере­таскивает верхний ползунок (он определен первым), задавая таким образом желаемую позицию.

<Slider Minimum="0" Grid.Column="l" Grid.Row="2" x:Name="sliderPosition"

ValueChanged="sliderPosition_ValueChanged" ></Slider>

Нижний ползунок игнорирует операции мыши (потому что его свойству IsHitTest- Visible присвоено значение False). Этот ползунок полупрозрачен, вследствие того что его свойство Opacity имеет значение 0.5. В результате нижний ползунок прорисовы­вается менее отчетливо, чем верхний (см. рис. 11.2). Разметка нижнего ползунка имеет следующий вид.

<Slider Minimum="0" Grid.Column="l" Grid.Row="2" x:Name="sliderPositionBackground" IsHitTestVisible="False" 0pacity="0.5"></Slider>

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

При запуске приложения код устанавливает максимальное значение ползунка на основе полного времени воспроизведения, хранящегося в свойстве NaturalDuration.

private void media_MediaOpened(object sender, RoutedEventArgs e)

{

sliderPosition.Maximum =

media.NaturalDuration.TimeSpan.TotalSeconds;

}

При перетаскивании ползунка код запускает воспроизведение с новой позиции.

private void sliderPosition_ValueChanged(object sender, RoutedEventArgs e)

{

/ / Переключение в режим паузы необходимо для устранения II шумовых эффектов, возникающих при изменении значений media.Pause (); media.Position = TimeSpan.FromSeconds(sliderPosition.Value); media.Play();

)

К сожалению, элемент MediaElement не генерирует никаких событий, извещающих о текущем воспроизведении. Поэтому для перемещения ползунка sliderPositionBack­ground и обновления текстового блока, выводящего текущее время воспроизведения, необходим таймер.

Идеально подходит таймер DispatcherTimer. Его можно создать при загрузке стра­ницы, задав короткие интервалы длительностью, например, 0,1 секунды. Запускать и останавливать таймер нужно вместе с воспроизведением.

private DispatcherTimer timer = new DispatcherTimer ();

public MediaPlayer() {

InitializeComponent();

timer.Interval = TimeSpan.FromSeconds(0.1); timer.Tick += timer_Tick;

}

private void cmdPlay_Click(object sender, RoutedEventArgs e) {

media.Play () ; timer.Start();

}

При возникновении события DispatcherTimer .Tick можно обновить пользователь­ский интерфейс, отобразив текущую позицию в текстовом блоке и переместив полупро­зрачный фоновый ползунок.

private void timer_Tick(object sender, EventArgs e) {

lblStatus.Text =

media.Position.ToString().TrimEnd(new char[](‘01}); sliderPositionBackground.Value = media.Position.TotalSeconds;

}

Два флажка — последние компоненты страницы и самые простые. Флажок Отключить звук (см. рис. 11.2) устанавливает свойство isMuted элемента MediaElement.

private void chkMute_Click(object sender, RoutedEventArgs e)

{

media.IsMuted = (bool)chkMute.IsChecked;

В элемент MediaElement не встроена поддержка циклического воспроизведения. Поэтому, когда флажок Повторять установлен, код страницы повторно запускает вос­произведение с начала при возникновении события MediaEnded.

private void media_MediaEnded(object sender,

RoutedEventArgs e)

{

if ((bool)chkLoop.IsChecked) {

media.Position = TimeSpan.Zero;

media.Play () ; }

else {

timer .Stop ();

}

}

Пример довольно простой, однако на его основе несложно создать более сложный проигрыватель. Для этого добавьте анимацию, прозрачность и другие эстетически при­влекательные эффекты.

Низкоуровневый конвейер звука и видео

Поддержка конвейера (pipeline) позволяет приложениям Silverlight 3 декодировать фрагменты звука и видео и на­правлять их в поток MediaElement для воспроизведения. Конечно, этот процесс довольно сложный и трудоемкий. К тому же, могут возникать серьезные проблемы с задержками. В данной книге использование конвейеров не рас­сматривается.

Большинство разработчиков приложений не имеют дела непосредственно с конвейерами звука и видео, однако вам могут быть полезными другие компоненты, основанные на конвейерах. Например, независимые поставщики при­меняют конвейеры в библиотеках, предназначенных для воспроизведения новых мультимедийных форматов, реали­зации "стильных" приложений с виртуальными синтезаторами и бесшовного циклического воспроизведения звука. Например, ознакомьтесь с компонентом MediaStreamSource (www.code .msdn .microsoft. com/wavmss), позволяющим воспроизводить в Silverlight аудиофайлы WAV в формате PCM.

Воспроизведение видеофайлов

Все, что написано выше о классе MediaElement, применимо не только к аудио-, но и к видеофайлам.

Ключевое отличие видео от звука состоит лишь в необходимости визуализации содержи­мого и добавлении свойств, связанных с размещением элемента MediaElement. Исходные размеры рамки определяются свойствами NaturalVideoHeight и NaturalVideoWidth эле­мента MediaElement. С помощью свойства Stretch рамку можно масштабировать или растягивать. Доступны значения None (вывод рамки с исходными размерами; рекомен­дуется для обеспечения максимальной производительности). Uniform (рамка растягива­ется, насколько позволяют размеры контейнера; пропорции сохраняются; это значение установлено по умолчанию). Fill (рамка растягивается до размеров контейнера; пропор­ции не сохраняются) и UniformToFill (рамка растягивается, насколько позволяет боль­ший размер контейнера; заполняется все пространство контейнера; пропорции сохраня­ются; не поместившаяся часть видеосодержимого отсекается).

Совет. Рекомендуется задать размеры элемента MediaElement такими же, как исходные размеры, определенные в видеофайле. Например, если создать элемент MediaElement, присвоить его свойству Stretch значение Uniform и поместить его в строку Grid, свойство Height которой имеет значение Auto, то строка Grid примет исходные размеры видеофайла. Масштабирование не понадобится.

Списки воспроизведения на стороне клиента

Платформа Silverlight поддерживает метафайлы Windows Media, представляющие собой списки воспроизведения (playlists). Список воспроизведения содержит указате­ли на медиафайлы. Метафайл Windows Media обычно имеет расширение .wax, .wvx, .wmx, .wpl или .asx. Некоторые средства метафайлов не поддерживаются и могут вы­звать ошибку, например ошибку команды сценария. Полный список неподдерживаемых средств метафайлов Windows Media можно найти в документации Silverlight.

Ниже приведен список воспроизведения (метафайл), ссылающийся на два видео­файла.

<asx version="3.0"> <title>CnncoK BocnpoH3BefleHHH</title> <entry>

<title>Bnfleo$aiin l</title> <ref href="Videol.wmv" /> </entry> <entry> <title>BHfleo$afm 2</title> <ref href="Video2.wmv" /> </entry>

</asx>

Если в свойство Source элемента MediaElement вставить ссылку на приведенный выше метафайл, элемент немедленно начнет воспроизведение файла Videol .wmv (ко­нечно, если он существует), а затем файла Video2 . wmv. В данном случае оба файла рас­положены в одном и том же месте на сервере. Список воспроизведения находится в той же папке, однако вы должны задать в атрибуте href другие папки и серверы.

Обычно файлы .asx используются с потоковыми файлами .asf. В этом случае файл .asx содержит ссылку на файл .asf.

Источник: Мак-Дональд, Мэтью. Silverlight 3 с примерами на С# для профессионалов. : Пер. с англ. —- М. : ООО «И.Д. Вильяме», 2010. — 656 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии