Xamarin Community Toolkit MediaElement

Скачайте пример. Скачивание примера

MediaElement — это представление для воспроизведения видео и звука. Мультимедиа, поддерживаемые базовой платформой, можно воспроизводить из следующих источников:

  • Веб-сайт с использованием URI (HTTP или HTTPS).
  • Ресурс, внедренный в приложение платформы с использованием ms-appx:/// схемы URI.
  • Файлы, поступающие из локальных и временных папок данных приложения, используя схему ms-appdata:/// URI.
  • Библиотека устройства.

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

Снимок экрана: mediaElement, воспроизводимый видео в iOS и Android.

Примечание

MediaElementдоступен в iOS, Android, универсальная платформа Windows (UWP), macOS, Windows Presentation Foundation и Tizen.

MediaElement определяет следующие свойства:

  • Aspectс типом Aspectопределяет, как будет масштабироваться носитель в соответствии с областью отображения. Значение по умолчанию этого свойства равно AspectFit.
  • AutoPlayс типом boolуказывает, начнется ли воспроизведение мультимедиа автоматически при Source установке свойства . Значение по умолчанию этого свойства равно true.
  • BufferingProgressс типом doubleуказывает текущий ход выполнения буферизации. Значение этого свойства по умолчанию — 0,0.
  • CanSeekс типом boolуказывает, можно ли изменить положение носителя, задав значение Position свойства . Это свойство доступно только для чтения.
  • CurrentStateс типом MediaElementStateуказывает текущее состояние элемента управления. Это свойство доступно только для чтения, значение по умолчанию — MediaElementState.Closed.
  • Durationс типом TimeSpan?указывает продолжительность открытого в данный момент носителя. Это свойство, доступное только для чтения, значением по умолчанию является null.
  • IsLoopingс типом boolописывает, должен ли загруженный в данный момент источник мультимедиа возобновлять воспроизведение с начала после достижения его окончания. Значение по умолчанию этого свойства равно false.
  • KeepScreenOnс типом boolопределяет, должен ли экран устройства оставаться включен во время воспроизведения мультимедиа. Значение по умолчанию этого свойства равно false.
  • Positionс типом TimeSpanописывает текущий ход выполнения во время воспроизведения мультимедиа. Это свойство использует привязку TwoWay и имеет значение по умолчанию .TimeSpan.Zero
  • ShowsPlaybackControlsс типом boolопределяет, отображаются ли элементы управления воспроизведением платформ. Значение по умолчанию этого свойства равно false. Обратите внимание, что в iOS элементы управления отображаются только в течение короткого периода после взаимодействия с экраном. Элементы управления не могут быть видимыми в любое время. В WPF системные элементы управления не поддерживаются, поэтому это свойство не оказывает никакого влияния.
  • Speedс типом doubleопределяет скорость воспроизведения мультимедиа. Значение этого свойства по умолчанию равно 1.
  • Sourceс типом MediaSourceуказывает источник носителя, загруженного в элемент управления .
  • VideoHeightс типом intуказывает высоту элемента управления. Это свойство доступно только для чтения.
  • VideoWidthс типом intуказывает ширину элемента управления . Это свойство доступно только для чтения.
  • Volumeс типом doubleопределяет объем носителя, который представлен в линейной шкале от 0 до 1. Это свойство использует привязку TwoWay и имеет значение по умолчанию 1.

Эти свойства, за исключением CanSeek свойства , поддерживаются объектами BindableProperty , что означает, что они могут быть целевыми объектами привязок данных и стили.

Класс MediaElement также определяет четыре события:

  • MediaOpened активируется при проверке и открытии потока мультимедиа.
  • MediaEnded срабатывает, MediaElement когда завершает воспроизведение носителя.
  • MediaFailed срабатывает при возникновении ошибки, связанной с источником мультимедиа.
  • SeekCompleted активируется, когда точка поиска запрошенной операции поиска готова к воспроизведению.

Кроме того, MediaElement включает Playметоды , Pauseи Stop .

Сведения о поддерживаемых форматах мультимедиа в Android см. в статье Поддерживаемые форматы мультимедиа в developer.android.com. Сведения о поддерживаемых форматах мультимедиа в универсальная платформа Windows (UWP) см. в разделе Поддерживаемые кодеки.

Воспроизведение удаленного носителя

Может MediaElement воспроизводить удаленные файлы мультимедиа с помощью схем URI HTTP и HTTPS. Для этого для свойства задается Source URI файла мультимедиа:

<MediaElement Source="https://sec.ch9.ms/ch9/5d93/a1eab4bf-3288-4faf-81c4-294402a85d93/XamarinShow_mid.mp4"
              ShowsPlaybackControls="True" />

По умолчанию носитель, определенный свойством , Source воспроизводится сразу после открытия носителя. Чтобы отключить автоматическое AutoPlay воспроизведение мультимедиа, задайте для свойства значение false.

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

Воспроизведение локальных носителей

Локальный носитель можно воспроизводить из следующих источников:

  • Ресурс, внедренный в приложение платформы с использованием ms-appx:/// схемы URI.
  • Файлы, поступающие из локальных и временных папок данных приложения, используя схему ms-appdata:/// URI.
  • Библиотека устройства.

Дополнительные сведения об этих схемах URI см. в разделе Схемы URI.

Воспроизведение мультимедиа, внедренного в пакет приложения

Объект MediaElement может воспроизводить файлы мультимедиа, внедренные в пакет приложения, с помощью ms-appx:/// схемы URI. Файлы мультимедиа внедряются в пакет приложения, помещая их в проект платформы.

Хранение файла мультимедиа в проекте платформы отличается для каждой платформы:

  • В iOS файлы мультимедиа должны храниться в папке Resources или в подпапке папки Resources . Файл мультимедиа должен иметь значение Build ActionBundleResource.
  • В Android файлы мультимедиа должны храниться во вложенной папке Resources с именем raw. В папке raw не может быть вложенных папок. Файл мультимедиа должен иметь значение Build ActionAndroidResource.
  • В UWP файлы мультимедиа можно хранить в любой папке проекта. Файл мультимедиа должен иметь значение BuildActionContent.

Затем файлы мультимедиа, соответствующие этим критериям, можно воспроизвести с помощью ms-appx:/// схемы URI:

<MediaElement Source="ms-appx:///XamarinForms101UsingEmbeddedImages.mp4"
              ShowsPlaybackControls="True" />

При использовании привязки данных для применения следующей схемы URI можно использовать преобразователь значений:

public class VideoSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return null;

        if (string.IsNullOrWhiteSpace(value.ToString()))
            return null;

        if (Device.RuntimePlatform == Device.UWP)
            return new Uri($"ms-appx:///Assets/{value}");
        else
            return new Uri($"ms-appx:///{value}");
    }
    // ...
}

Затем экземпляр VideoSourceConverter можно использовать для применения ms-appx:/// схемы URI к внедренным файлам мультимедиа:

<MediaElement Source="{Binding MediaSource, Converter={StaticResource VideoSourceConverter}}"
              ShowsPlaybackControls="True" />

Дополнительные сведения о схеме URI ms-appx см. в разделах ms-appx и ms-appx-web.

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

Объект MediaElement может воспроизводить файлы мультимедиа, которые копируются в локальные или временные папки данных приложения, используя схему ms-appdata:/// URI.

В следующем примере показано Source свойство, заданное для файла мультимедиа, хранящегося в локальной папке данных приложения:

<MediaElement Source="ms-appdata:///local/XamarinVideo.mp4"
              ShowsPlaybackControls="True" />

В следующем примере показано Source свойство файла мультимедиа, хранящегося во временной папке данных приложения:

<MediaElement Source="ms-appdata:///temp/XamarinVideo.mp4"
              ShowsPlaybackControls="True" />

Важно!

Помимо воспроизведения файлов мультимедиа, хранящихся в локальных или временных папках данных приложения, UWP также может воспроизводить файлы мультимедиа, расположенные в перемещаемой папке приложения. Это можно сделать, установив в файле мультимедиа префикс .ms-appdata:///roaming/

При использовании привязки данных для применения следующей схемы URI можно использовать преобразователь значений:

public class VideoSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return null;

        if (string.IsNullOrWhiteSpace(value.ToString()))
            return null;

        return new Uri($"ms-appdata:///{value}");
    }
    // ...
}

Затем экземпляр VideoSourceConverter можно использовать для применения ms-appdata:/// схемы URI к файлу мультимедиа в локальной или временной папке данных приложения:

<MediaElement Source="{Binding MediaSource, Converter={StaticResource VideoSourceConverter}}"
              ShowsPlaybackControls="True" />

Дополнительные сведения о схеме URI ms-appdata см. в разделе ms-appdata.

Копирование файла мультимедиа в локальную или временную папку данных приложения

Для воспроизведения файла мультимедиа, хранящегося в локальной или временной папке данных приложения, требуется, чтобы файл мультимедиа был скопирован приложением. Это можно сделать, например, скопировав файл мультимедиа из пакета приложения:

// This method copies the video from the app package to the app data
// directory for your app. To copy the video to the temp directory
// for your app, comment out the first line of code, and uncomment
// the second line of code.
public static async Task CopyVideoIfNotExists(string filename)
{
    string folder = FileSystem.AppDataDirectory;
    //string folder = Path.GetTempPath();
    string videoFile = Path.Combine(folder, "XamarinVideo.mp4");

    if (!File.Exists(videoFile))
    {
        using (Stream inputStream = await FileSystem.OpenAppPackageFileAsync(filename))
        {
            using (FileStream outputStream = File.Create(videoFile))
            {
                await inputStream.CopyToAsync(outputStream);
            }
        }
    }
}

Примечание

В приведенном выше примере кода используется класс , включенный FileSystem в Xamarin.Essentials. Дополнительные сведения см. в разделе Xamarin.Essentials: вспомогательные функции файловой системы.

Воспроизведение мультимедиа из библиотеки устройств

Большинство современных мобильных устройств и настольных компьютеров имеют возможность записывать видео и звук с помощью камеры и микрофона устройства. Созданный носитель затем сохраняется на устройстве в виде файлов. Эти файлы можно извлечь из библиотеки и воспроизвести с MediaElementпомощью .

Каждая из платформ включает в себя средство, позволяющее пользователю выбирать мультимедиа из библиотеки устройства. В Xamarin.Forms проекты платформы могут вызывать эту функцию, и она может вызываться классом DependencyService .

Служба зависимостей выбора видео, используемая в примере приложения, очень похожа на службу, определенную в разделе Выбор фотографии из библиотеки рисунков, за исключением того, что средство выбора возвращает имя файла, а не Stream объект. Проект общего кода определяет интерфейс с именем IVideoPicker, который определяет один метод с именем GetVideoFileAsync. Затем каждая платформа реализует этот интерфейс в VideoPicker классе .

В следующем примере кода показано, как получить файл мультимедиа из библиотеки устройств:

string filename = await DependencyService.Get<IVideoPicker>().GetVideoFileAsync();
if (!string.IsNullOrWhiteSpace(filename))
{
    mediaElement.Source = new FileMediaSource
    {
        File = filename
    };
}

Служба зависимостей выбора видео вызывается путем вызова DependencyService.Get метода для получения реализации IVideoPicker интерфейса в проекте платформы. Затем GetVideoFileAsync метод вызывается для этого экземпляра, и возвращенное имя файла используется для создания FileMediaSource объекта и задания ему Source свойства MediaElementобъекта .

Изменение пропорций видео

Свойство Aspect определяет, как будет масштабироваться видеофайл в соответствии с областью отображения. По умолчанию этому свойству AspectFit присваивается элемент перечисления, но ему может быть присвоен любой из Aspect членов перечисления:

  • AspectFit указывает, что видео будет в почтовом ящике, если это необходимо, для размещения в области отображения с сохранением пропорций.
  • AspectFill указывает, что видео будет обрезано таким образом, чтобы оно заполняло область отображения с сохранением пропорций.
  • Fill указывает, что видео будет растянуто для заполнения области отображения.

Привязка к свойству Position

Уведомление об изменении свойства для привязываемого Position свойства срабатывает с интервалом 200 мс во время воспроизведения. Таким образом, свойство может быть привязано к элементу Slider управления (или аналогичному) для отображения хода выполнения через носитель. CommunityToolkit также предоставляет объект , TimeSpanToDoubleConverter который преобразует в TimeSpan значение с плавающей запятой, представляющее общее количество затраченных секунд. Таким образом, для ползунка MaximumDuration можно задать значение носителя, а для Value — для точного Position хода выполнения:

<?xml version="1.0" encoding="UTF-8"?>
<pages:BasePage xmlns="http://xamarin.com/schemas/2014/forms"
                xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
                xmlns:pages="clr-namespace:Xamarin.CommunityToolkit.Sample.Pages"
                x:Class="Xamarin.CommunityToolkit.Sample.Pages.Views.MediaElementPage">
    <pages:BasePage.Resources>
        <xct:TimeSpanToDoubleConverter x:Key="TimeSpanConverter"/>
    </pages:BasePage.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <xct:MediaElement
            x:Name="mediaElement"
            Source="https://sec.ch9.ms/ch9/5d93/a1eab4bf-3288-4faf-81c4-294402a85d93/XamarinShow_mid.mp4"
            ShowsPlaybackControls="True"
            HorizontalOptions="Fill"
            SeekCompleted="OnSeekCompleted" />
        <Slider Grid.Row="1" BindingContext="{x:Reference mediaElement}" Value="{Binding Position, Converter={StaticResource TimeSpanConverter}}" Maximum="{Binding Duration, Converter={StaticResource TimeSpanConverter}}">
            <Slider.Triggers>
                <DataTrigger TargetType="Slider"
                     Binding="{Binding CurrentState}"
                     Value="{x:Static MediaElementState.Buffering}">
                    <Setter Property="IsEnabled" Value="False" />
                </DataTrigger>
            </Slider.Triggers>
        </Slider>
        <Button Grid.Row="2" Text="Reset Source (Set Null)" Clicked="OnResetClicked" />
    </Grid>
</pages:BasePage>

В этом примере Maximum свойство объекта привязано Slider к свойству DurationMediaElement объекта , а Value свойство Slider объекта — к свойству PositionMediaElementобъекта . Таким образом, перетаскивание Slider результатов в положение воспроизведения мультимедиа изменится:

Снимок экрана: элемент MediaElement с позицией в iOS и Android.

Кроме того, DataTrigger объект используется для отключения Slider при буферизации носителя. Дополнительные сведения о триггерах данных см. в разделе Триггеры Xamarin.Forms.

Примечание

В Android Slider только имеет 1000 дискретных шагов, независимо от Minimum параметров и Maximum . Если длина носителя превышает 1000 секунд, то два разных Position значения будут соответствовать одному и тому же Value значению Slider. Именно поэтому приведенный выше код проверяет, что новая позиция и существующая позиция превышают сотую часть общей длительности.

Общие сведения о типах MediaSource

Может MediaElement воспроизводить мультимедиа, задав для его Source свойства удаленный или локальный файл мультимедиа. Свойство Source имеет тип MediaSource, и этот класс определяет два статических метода:

  • FromFile, возвращает MediaSource экземпляр из аргумента string .
  • FromUri, возвращает MediaSource экземпляр из аргумента Uri .

Кроме того, класс MediaSource также имеет неявные операторы, которые возвращают MediaSource экземпляры из string аргументов и Uri .

Примечание

Если свойство задано Source в XAML, вызывается преобразователь типов для возврата экземпляра MediaSourcestring из или Uri.

Класс MediaSource также имеет два производных класса:

  • UriMediaSource, который используется для указания удаленного файла мультимедиа из универсального кода ресурса (URI). Этот класс имеет Uri свойство , для которого можно задать значение Uri.
  • FileMediaSource, который используется для указания локального файла мультимедиа из string. Этот класс имеет File свойство , для которого можно задать значение string. Кроме того, этот класс имеет неявные операторы для преобразования в stringFileMediaSource объект и FileMediaSource объекта в string.

Примечание

FileMediaSource При создании объекта в XAML вызывается преобразователь типов для возврата экземпляра FileMediaSource из string.

Определение состояния MediaElement

Класс MediaElement определяет привязываемое свойство только для чтения с именем CurrentState, типа MediaElementState. Это свойство указывает текущее состояние элемента управления, например, воспроизводимый или приостановленный носитель, или он еще не готов к воспроизведению мультимедиа.

Перечисление MediaElementState определяет следующие члены:

  • Closed указывает, что MediaElement не содержит носителей.
  • Opening указывает, что MediaElement выполняет проверку и пытается загрузить указанный источник.
  • Buffering указывает, что MediaElement загружает мультимедиа для воспроизведения. Его Position свойство не перемещает во время этого состояния. Если воспроизводилось MediaElement видео, он продолжает отображать последний отображаемый кадр.
  • Playing указывает, что MediaElement воспроизводит источник мультимедиа.
  • Paused указывает, что MediaElement объект не перемещает свое Position свойство . Если воспроизводит MediaElement видео, он продолжает отображать текущий кадр.
  • Stopped указывает, что MediaElement содержит мультимедиа, но не воспроизводится или приостанавливается. Его Position свойство равно 0 и не перемещается вперед. Если загруженным носителем является видео, отображается MediaElement первый кадр.

Обычно не требуется проверять CurrentState свойство при использовании элементов управления транспортировкой MediaElement . Однако это свойство становится важным при реализации собственных элементов управления транспортировкой.

Реализация пользовательских элементов управления транспортировкой

Элементы управления транспортировкой проигрывателя мультимедиа включают кнопки, которые выполняют функции Воспроизведения, Приостановка и Остановка. Эти кнопки обычно определяются по знакомым значкам, а не тексту. Как правило, функции Воспроизведение и Пауза объединены в одну кнопку.

По умолчанию элементы управления воспроизведением MediaElement отключены. Это позволяет управлять программными MediaElement средствами или путем предоставления собственных элементов управления транспортировкой. Для поддержки этого MediaElement включает Playметоды , и .StopPause

В следующем примере XAML показана страница, содержащая и пользовательские элементы управления транспортировкой MediaElement :

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MediaElementDemos.CustomTransportPage"
             Title="Custom transport">
    <Grid>
        ...
        <MediaElement x:Name="mediaElement"
                      AutoPlay="False"
                      ... />
        <StackLayout BindingContext="{x:Reference mediaElement}"
                     ...>
            <Button Text="&#x25B6;&#xFE0F; Play"
                    HorizontalOptions="CenterAndExpand"
                    Clicked="OnPlayPauseButtonClicked">
                <Button.Triggers>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding CurrentState}"
                                 Value="{x:Static MediaElementState.Playing}">
                        <Setter Property="Text"
                                Value="&#x23F8; Pause" />
                    </DataTrigger>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding CurrentState}"
                                 Value="{x:Static MediaElementState.Buffering}">
                        <Setter Property="IsEnabled"
                                Value="False" />
                    </DataTrigger>
                </Button.Triggers>
            </Button>
            <Button Text="&#x23F9; Stop"
                    HorizontalOptions="CenterAndExpand"
                    Clicked="OnStopButtonClicked">
                <Button.Triggers>
                    <DataTrigger TargetType="Button"
                                 Binding="{Binding CurrentState}"
                                 Value="{x:Static MediaElementState.Stopped}">
                        <Setter Property="IsEnabled"
                                Value="False" />
                    </DataTrigger>
                </Button.Triggers>
            </Button>
        </StackLayout>
    </Grid>
</ContentPage>

В этом примере пользовательские элементы управления транспортировкой определяются как Button объекты . Однако существует только два Button объекта: первый Button представляет воспроизведение и паузу, а второй Buttonstop. DataTrigger Объекты используются для включения и отключения кнопок, а также для переключения первой кнопки между воспроизведением и паузой. Дополнительные сведения о триггерах данных см. в разделе Триггеры Xamarin.Forms.

Файл кода программной части содержит обработчики для Clicked событий:

void OnPlayPauseButtonClicked(object sender, EventArgs args)
{
    if (mediaElement.CurrentState == MediaElementState.Stopped ||
        mediaElement.CurrentState == MediaElementState.Paused)
    {
        mediaElement.Play();
    }
    else if (mediaElement.CurrentState == MediaElementState.Playing)
    {
        mediaElement.Pause();
    }
}

void OnStopButtonClicked(object sender, EventArgs args)
{
    mediaElement.Stop();
}

После включения можно нажать кнопку Воспроизвести , чтобы начать воспроизведение:

Снимок экрана: Элемент MediaElement с пользовательскими элементами управления транспортировкой в iOS и Android.

Нажатие кнопки Пауза приводит к приостановке воспроизведения:

Снимок экрана: элемент MediaElement с приостановленным воспроизведением в iOS и Android.

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

Реализация пользовательского элемента управления громкости

Элементы управления воспроизведением мультимедиа, реализованные каждой платформой, включают в себя полосу громкости. Эта панель похожа на ползунок и показывает объем носителя. Кроме того, можно управлять полосой тома для увеличения или уменьшения громкости.

Пользовательскую панель тома можно реализовать с помощью Slider, как показано в следующем примере:

<StackLayout>
    <MediaElement AutoPlay="False"
                  Source="{StaticResource AdvancedAsync}" />
    <Slider Maximum="1.0"
            Minimum="0.0"
            Value="{Binding Volume}"
            Rotation="270"
            WidthRequest="100" />
</StackLayout>

В этом примере Slider данные привязывают свое Value свойство к свойству VolumeMediaElementобъекта . Это возможно, так как Volume свойство использует привязку TwoWay . Таким образом, изменение Value свойства приведет к изменению Volume свойства.

Примечание

Свойство Volume имеет обратный вызов проверки, который гарантирует, что его значение больше или равно 0,0 и меньше или равно 1,0.

Дополнительные сведения об использовании Slider см. в разделе Ползунок Xamarin.Forms.