Элемент MediaElement

127

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

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

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

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

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

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

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

Поддерживаемые форматы мультимедийных файлов

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

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

Формат 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 с аудиосодержимым MP3. И наконец, Silverlight не поддерживает видеофайлы с нечетным разрешением, например 127x135.

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

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

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

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

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

<MediaElement x:Name="media" Source="test.mp3" AutoPlay="False"></MediaElement>

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

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

private void cmd_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)
{
       txbErrorText.Text = 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 cmd_Click(object sender, RoutedEventArgs e)
{
      MediaElement media = new MediaElement();
      media.Source = new Uri("test.mp3", UriKind.RelativeOrAbsolute);
      media.MediaEnded += media_MediaEnded;
      LayoutRoot.Children.Add(media);
}
        
private void media_MediaEnded(object sender, RoutedEventArgs e)
{
      LayoutRoot.Children.Remove(sender as MediaElement);
}

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

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

Volume

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

Balance

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

CurrentState

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

Position

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

Ниже показан пример аудиоплеера:

<UserControl x:Class="SilverlightMedia.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SilverlightMedia">
    <Grid x:Name="LayoutRoot" Background="Gray" Margin="10">
        <Grid.Resources>
            <local:DoubleToTimeSpanConverter x:Key="DoubleToTimeSpanConverter"/>
            <Style TargetType="TextBlock">
                <Setter Property="VerticalAlignment" Value="Center"/>
                <Setter Property="FontSize" Value="14"/>
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="Margin" Value="5"/>
            </Style>
            <Style TargetType="CheckBox">
                <Setter Property="Foreground" Value="White"/>
                <Setter Property="Margin" Value="0,3"/>
                <Setter Property="FontSize" Value="12"/>
            </Style>
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBlock Text="Громкость" Grid.Row="1"/>
        <TextBlock Text="Баланс" Grid.Row="2"/>
        <TextBlock Text="Позиция" Grid.Row="3"/>
        
        <MediaElement x:Name="media" AutoPlay="False" Source="test.mp3" MediaOpened="media_MediaOpened" />
        
        <Slider x:Name="sliderVolume" Grid.Row="1" Grid.Column="1" Minimum="0" Maximum="1" SmallChange="0.01" LargeChange="0.1"
                Value="{Binding ElementName=media, Path=Volume, Mode=TwoWay}" />
        <Slider x:Name="sliderBalance" Grid.Row="2" Grid.Column="1" Minimum="-1" Maximum="1" SmallChange="0.02" LargeChange="0.15"
                Value="{Binding ElementName=media, Path=Balance, Mode=TwoWay}" />
        <Slider x:Name="sliderPosition" Grid.Row="3" Grid.Column="1" Minimum="0" SmallChange="1" LargeChange="5"
                Value="{Binding ElementName=media, Path=Position, Mode=TwoWay, Converter={StaticResource DoubleToTimeSpanConverter}}" />
        
        <StackPanel Grid.Row="4" Margin="5">
            <CheckBox x:Name="checkLoop" Content="Повторить по окончанию" Click="checkLoop_Checked" />
            <CheckBox x:Name="checkNoVolume" Content="Отключить звук" Click="checkNoVolume_Checked" />
        </StackPanel>
        
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Grid.Row="5" Grid.ColumnSpan="2">
            <Button x:Name="cmdPlay" Content="Пуск" Click="cmdPlay_Click" Padding="5" Margin="5,5,0,5" />
            <Button x:Name="cmdStop" Content="Стоп" Click="cmdStop_Click" Padding="5" Margin="5,5,0,5" />
            <Button x:Name="cmdPause" Content="Пауза" Click="cmdPause_Click" Padding="5" Margin="5,5,0,5" />
            <Button x:Name="cmdReplay" Content="Повторить" Click="media_MediaEnded" Padding="5" Margin="5,5,0,5" />
        </StackPanel>
    </Grid>
</UserControl>
public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void cmdPlay_Click(object sender, RoutedEventArgs e)
        {
            media.Play();
        }

        private void media_MediaOpened(object sender, RoutedEventArgs e)
        {
            // При запуске приложения код устанавливает максимальное значение ползунка 
            // на основе полного времени воспроизведения, хранящегося в свойстве NaturalDuration
            sliderPosition.Maximum = media.NaturalDuration.TimeSpan.TotalSeconds;
        }

        private void checkLoop_Checked(object sender, RoutedEventArgs e)
        {
            if (this.checkLoop.IsChecked == true)
            {
                // Повторение аудио по окончанию воспроизведения
                media.MediaEnded += media_MediaEnded;
            }
            else
            {
                media.MediaEnded -= media_MediaEnded; 
            }
        }

        private void media_MediaEnded(object sender, RoutedEventArgs e)
        {
            media.Position = TimeSpan.FromSeconds(0);
            media.Play();
        }

        private void checkNoVolume_Checked(object sender, RoutedEventArgs e)
        {
            media.IsMuted = (bool)checkNoVolume.IsChecked;
        }

        private void cmdStop_Click(object sender, RoutedEventArgs e)
        {
            media.Stop();
        }

        private void cmdPause_Click(object sender, RoutedEventArgs e)
        {
            media.Pause();
        }
}

// Вспомогательный конвертер, преобразующий TimeSpan в Double и обратно
// Используется в слайдере позиции
public class DoubleToTimeSpanConverter : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            return ((TimeSpan)value).TotalSeconds;
        }

        public object ConvertBack(object value, Type targetType, object parameter,
            System.Globalization.CultureInfo culture)
        {
            return TimeSpan.FromSeconds((double)value);
        }
}
Аудиоплеер на Silverlight
Пройди тесты
Лучший чат для C# программистов