Medienumwandlung

In diesem Artikel wird beschrieben, wie Sie Medien aus einer universellen Windows-App zu Remotegeräten umwandeln.

Integrierte Medienumwandlung mit MediaPlayerElement

Die einfachste Methode zum Umwandeln von Medien aus einer universellen Windows-App ist die Verwendung der integrierten Umwandlungsfunktion des MediaPlayerElement-Steuerelements.

Um dem Benutzer das Öffnen einer wiederzugebenden Videodatei im MediaPlayerElement-Steuerelement zu ermöglichen, fügen Sie Ihrem Projekt die folgenden Namespaces hinzu.

using Windows.Storage;
using Windows.Storage.Pickers;
using Windows.Storage.Streams;
using Windows.Media.Core;

Fügen Sie in der XAML-Datei der App ein MediaPlayerElement hinzu, und legen Sie AreTransportControlsEnabled auf „true“ fest.

<MediaPlayerElement Name="mediaPlayerElement"  MinHeight="100" MaxWidth="600" HorizontalAlignment="Stretch" AreTransportControlsEnabled="True"/>

Fügen Sie eine Schaltfläche hinzu, über die der Benutzer die Auswahl einer Datei initiieren kann.

<Button x:Name="openButton" Click="openButton_Click" Content="Open"/>

Erstellen Sie im Click-Ereignishandler für die Schaltfläche eine neue Instanz des FileOpenPicker-Objekts, fügen Sie der FileTypeFilter-Sammlung Videodateitypen hinzu, und legen die Ausgangsposition auf die Videobibliothek des Benutzers fest.

Rufen Sie PickSingleFileAsync auf, um das Dialogfeld für die Dateiauswahl zu starten. Diese Methode gibt ein StorageFile-Objekt zurück, das die Videodatei darstellt. Stellen Sie sicher, dass die Datei nicht NULL ist; dies ist der Fall, wenn der Benutzer den Auswahlvorgang abbricht. Rufen Sie die OpenAsync-Methode der Datei auf, um einen IRandomAccessStream für die Datei abzurufen. Abschließend erstellen Sie ein neues MediaSource-Objekt aus der ausgewählten Datei durch Aufrufen von CreateFromStorageFile und weisen es der Source-Eigenschaft des MediaPlayerElement-Objekts zu, um die Videodatei zur Videoquelle für das Steuerelement zu machen.

private async void openButton_Click(object sender, RoutedEventArgs e)
{
    //Create a new picker
    FileOpenPicker filePicker = new FileOpenPicker();

    //Add filetype filters.  In this case wmv and mp4.
    filePicker.FileTypeFilter.Add(".wmv");
    filePicker.FileTypeFilter.Add(".mp4");

    //Set picker start location to the video library
    filePicker.SuggestedStartLocation = PickerLocationId.VideosLibrary;

    //Retrieve file from picker
    StorageFile file = await filePicker.PickSingleFileAsync();

    //If we got a file, load it into the media lement
    if (file != null)
    {
        mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(file);
        mediaPlayerElement.MediaPlayer.Play();
    }
}

Nachdem das Video in das MediaPlayerElement geladen wurde, kann der Benutzer einfach die Umwandlungsschaltfläche in den Transportsteuerelementen wählen, um ein integriertes Dialogfeld zu öffnen, in dem er ein Gerät auswählen kann, für das die geladenen Medien umgewandelt werden.

MediaElement-Umwandlungsschaltfläche

Hinweis

Ab Windows 10, Version 1607, wird die Verwendung der MediaPlayer-Klasse zum Wiedergeben von Medienelementen empfohlen. MediaPlayerElement ist ein einfaches XAML-Steuerelement, das zum Rendern des Inhalts eines MediaPlayer-Objekts auf einer XAML-Seite verwendet wird. Das MediaElement-Steuerelement wird aus Gründen der Abwärtskompatibilität weiterhin unterstützt. Weitere Informationen zur Verwendung von MediaPlayer und MediaPlayerElement zum Wiedergeben von Medieninhalten finden Sie unter Wiedergeben von Audio- und Videoinhalten mit „MediaPlayer“. Informationen zur Verwendung von MediaSource und dazugehörigen APIs für die Arbeit mit Medieninhalten finden Sie unter Medienelemente, Wiedergabelisten und Titel.

Medienumwandlung mit CastingDevicePicker

Eine zweite Methode zum Umwandeln von Medien für ein Gerät ist die Verwendung der CastingDevicePicker-Klasse. Zum Verwenden dieser Klasse schließen Sie den Windows.Media.Casting-Namespace in Ihr Projekt ein.

using Windows.Media.Casting;

Deklarieren Sie eine Membervariable für das CastingDevicePicker-Objekt.

CastingDevicePicker castingPicker;

Wenn die Seite initialisiert wird, erstellen Sie eine neue Instanz der Umwandlungsauswahl, und legen Sie die Filter-Eigenschaft auf SupportsVideo fest, um anzugeben, dass die von der Auswahl aufgeführten Umwandlungsgeräte Video unterstützen müssen. Registrieren Sie einen Handler für das CastingDeviceSelected-Ereignis, das ausgelöst wird, wenn der Benutzer ein Gerät für die Umwandlung auswählt.

//Initialize our picker object
castingPicker = new CastingDevicePicker();

//Set the picker to filter to video capable casting devices
castingPicker.Filter.SupportsVideo = true;

//Hook up device selected event
castingPicker.CastingDeviceSelected += CastingPicker_CastingDeviceSelected;

Fügen Sie in der XAML-Datei eine Schaltfläche hinzu, über die der Benutzer die Auswahl starten kann.

<Button x:Name="castPickerButton" Content="Cast Button" Click="castPickerButton_Click"/>

Rufen Sie im Click-Ereignishandler für die Schaltfläche TransformToVisual auf, um die Transformation eines UI-Elements relativ zu einem anderen Element abzurufen. In diesem Beispiel ist die Transformation die Position der Umwandlungsauswahl-Schaltfläche relativ zum visuellen Stamm des Anwendungsfensters. Rufen Sie die Show-Methode des CastingDevicePicker-Objekts auf, um das Dialogfeld der Umwandlungsauswahl zu öffnen. Geben Sie die Position und die Abmessungen der Umwandlungsauswahl-Schaltfläche an, sodass das Dialogfeld als Flyout der vom Benutzer gewählten Schaltfläche angezeigt werden kann.

private void castPickerButton_Click(object sender, RoutedEventArgs e)
{
    //Retrieve the location of the casting button
    GeneralTransform transform = castPickerButton.TransformToVisual(Window.Current.Content as UIElement);
    Point pt = transform.TransformPoint(new Point(0, 0));

    //Show the picker above our casting button
    castingPicker.Show(new Rect(pt.X, pt.Y, castPickerButton.ActualWidth, castPickerButton.ActualHeight),
        Windows.UI.Popups.Placement.Above);
}

Rufen Sie im CastingDeviceSelected-Ereignishandler die CreateCastingConnection-Methode der SelectedCastingDevice-Eigenschaft der Ereignisargumente auf, die das vom Benutzer ausgewählte Umwandlungsgerät darstellt. Registrieren Sie Handler für die Ereignisse ErrorOccurred und StateChanged. Rufen Sie abschließend RequestStartCastingAsync auf, um die Umwandlung zu starten, indem das Ergebnis für die GetAsCastingSource-Methode des MediaPlayer-Objekts des MediaPlayerElement-Steuerelements übergeben wird, um anzugeben, dass die Medien, die umgewandelt werden sollen, der Inhalt des MediaPlayer sind, der dem MediaPlayerElement zugeordnet ist.

Hinweis

Die Umwandlungsverbindung muss im UI-Thread initiiert werden. Da CastingDeviceSelected nicht für den UI-Thread aufgerufen wird, müssen Sie diese Aufrufe innerhalb eines Aufrufs von CoreDispatcher.RunAsync platzieren, sodass diese für den UI-Thread aufgerufen werden.

private async void CastingPicker_CastingDeviceSelected(CastingDevicePicker sender, CastingDeviceSelectedEventArgs args)
{
    //Casting must occur from the UI thread.  This dispatches the casting calls to the UI thread.
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
    {
        //Create a casting conneciton from our selected casting device
        CastingConnection connection = args.SelectedCastingDevice.CreateCastingConnection();

        //Hook up the casting events
        connection.ErrorOccurred += Connection_ErrorOccurred;
        connection.StateChanged += Connection_StateChanged;

        //Cast the content loaded in the media element to the selected casting device
        await connection.RequestStartCastingAsync(mediaPlayerElement.MediaPlayer.GetAsCastingSource());
    });
}

Aktualisieren Sie die Benutzeroberfläche in den Ereignishandlern ErrorOccurred und StateChanged, um den Benutzer über den aktuellen Status der Umwandlung zu informieren. Diese Ereignisse werden im folgenden Abschnitt zum Erstellen einer benutzerdefinierten Umwandlungsgeräteauswahl ausführlich erläutert.

private async void Connection_StateChanged(CastingConnection sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        ShowMessageToUser("Casting Connection State Changed: " + sender.State);
    });
}

private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        ShowMessageToUser("Casting Connection State Changed: " + sender.State);
    });
}

Medienumwandlung mit einer benutzerdefinierten Geräteauswahl

Im folgenden Abschnitt wird beschrieben, wie Sie ein eigenes Benutzeroberflächenelement zur Umwandlungsgeräteauswahl erstellen, indem Sie die Umwandlungsgeräte aufzählen und die Verbindung im Code initiieren.

Um die verfügbaren Umwandlungsgeräte aufzuzählen, schließen Sie den Windows.Devices.Enumeration-Namespace in Ihr Projekt ein.

using Windows.Devices.Enumeration;

Fügen Sie der XAML-Seite die folgenden Steuerelemente hinzu, um die einfache Benutzeroberfläche für dieses Beispiel zu implementieren:

  • Eine Schaltfläche zum Starten des Geräteüberwachungselements, das nach verfügbaren Umwandlungsgeräten sucht.
  • Ein ProgressRing-Steuerelement, das den Benutzer über die laufende Umwandlungsenumeration informiert.
  • Ein ListBox zum Auflisten der erkannten Umwandlungsgeräte. Definieren Sie eine ItemTemplate für das Steuerelement, sodass die Umwandlungsgeräteobjekte direkt dem Steuerelement zugewiesen werden können und die FriendlyName-Eigenschaft trotzdem weiterhin angezeigt wird.
  • Eine Schaltfläche, über die der Benutzer das Umwandlungsgerät trennen kann.
<Button x:Name="startWatcherButton" Content="Watcher Button" Click="startWatcherButton_Click"/>
<ProgressRing x:Name="watcherProgressRing" IsActive="False"/>
<ListBox x:Name="castingDevicesListBox" MaxWidth="300" HorizontalAlignment="Left" SelectionChanged="castingDevicesListBox_SelectionChanged">
    <!--Listbox content is bound to the FriendlyName field of our casting devices-->
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=FriendlyName}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
<Button x:Name="disconnectButton" Content="Disconnect" Click="disconnectButton_Click" Visibility="Collapsed"/>

Deklarieren Sie im CodeBehind Membervariablen für DeviceWatcher und CastingConnection.

DeviceWatcher deviceWatcher;
CastingConnection castingConnection;

Aktualisieren Sie im Click-Handler für die startWatcherButton zuerst die Benutzeroberfläche, indem Sie die Schaltfläche deaktivieren und das Statussignal aktivieren, während die Geräteenumeration ausgeführt wird. Löschen Sie den Inhalt des Listenfelds mit Umwandlungsgeräten.

Erstellen Sie als Nächstes ein Geräteüberwachungselement durch Aufruf von DeviceInformation.CreateWatcher. Diese Methode kann verwendet werden, um viele verschiedene Arten von Geräten zu überwachen. Geben Sie mithilfe der von CastingDevice.GetDeviceSelector zurückgegebenen Geräteauswahlzeichenfolge an, dass Sie Geräte überwachen möchten, die die Videoumwandlung unterstützen.

Registrieren Sie abschließend Ereignishandler für die Ereignisse Added, Removed, EnumerationCompleted und Stopped.

private void startWatcherButton_Click(object sender, RoutedEventArgs e)
{
    startWatcherButton.IsEnabled = false;
    watcherProgressRing.IsActive = true;

    castingDevicesListBox.Items.Clear();

    //Create our watcher and have it find casting devices capable of video casting
    deviceWatcher = DeviceInformation.CreateWatcher(CastingDevice.GetDeviceSelector(CastingPlaybackTypes.Video));

    //Register for watcher events
    deviceWatcher.Added += DeviceWatcher_Added;
    deviceWatcher.Removed += DeviceWatcher_Removed;
    deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
    deviceWatcher.Stopped += DeviceWatcher_Stopped;

    //Start the watcher
    deviceWatcher.Start();
}

Das Added-Ereignis wird ausgelöst, wenn ein neues Gerät vom Überwachungselement erkannt wird. Erstellen Sie im Handler für dieses Ereignis ein neues CastingDevice-Objekt, indem Sie CastingDevice.FromIdAsync aufrufen und die ID des erkannten Umwandlungsgeräts übergeben, die in dem an den Handler übergebenen DeviceInformation-Objekt enthalten ist.

Fügen Sie das CastingDevice zum ListBox für Umwandlungsgeräte hinzu, damit der Benutzer es auswählen kann. Aufgrund der in XAML definierten ItemTemplate wird die FriendlyName-Eigenschaft als Elementtext im Listenfeld verwendet. Da dieser Ereignishandler nicht für den UI-Thread aufgerufen wird, müssen Sie die Benutzeroberfläche innerhalb eines Aufrufs von CoreDispatcher.RunAsync aktualisieren.

private async void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () =>
    {
        //Add each discovered device to our listbox
        CastingDevice addedDevice = await CastingDevice.FromIdAsync(args.Id);
        castingDevicesListBox.Items.Add(addedDevice);
    });
}

Das Removed-Ereignis wird ausgelöst, wenn das Überwachungselement erkennt, dass ein Umwandlungsgerät nicht mehr vorhanden ist. Vergleichen Sie die ID-Eigenschaft des Added-Objekts, die an den Handler übergeben wird, mit der ID jedes Added-Objekts in der Items-Sammlung des Listenfelds. Wenn die ID übereinstimmt, entfernen Sie das Objekt aus der Sammlung. Zur Erinnerung: Da die Benutzeroberfläche aktualisiert wird, muss dieser Aufruf innerhalb eines RunAsync-Aufrufs erfolgen.

private async void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        foreach (CastingDevice currentDevice in castingDevicesListBox.Items)
        {
            if (currentDevice.Id == args.Id)
            {
                castingDevicesListBox.Items.Remove(currentDevice);
            }
        }
    });
}

Das EnumerationCompleted-Ereignis wird ausgelöst, wenn das Überwachungselement die Erkennung von Geräten abgeschlossen hat. Aktualisieren Sie im Handler für dieses Ereignis die Benutzeroberfläche, um den Benutzer darüber zu informieren, dass die Enumeration abgeschlossen ist, und beenden Sie das Geräteüberwachungselement durch Aufruf von Stop.

private async void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //If enumeration completes, update UI and transition watcher to the stopped state
        ShowMessageToUser("Watcher completed enumeration of devices");
        deviceWatcher.Stop();
    });
}

Das Stopped-Ereignis wird ausgelöst, wenn das Beenden des Geräteüberwachungselements abgeschlossen ist. Beenden Sie im Handler für dieses Ereignis das ProgressRing-Steuerelement, und aktivieren Sie die startWatcherButton wieder, damit der Benutzer den Vorgang der Geräteenumeration neu starten kann.

private async void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Update UX when the watcher stops
        startWatcherButton.IsEnabled = true;
        watcherProgressRing.IsActive = false;
    });
}

Wenn der Benutzer eines der Umwandlungsgeräte im Listenfeld auswählt, wird das SelectionChanged-Ereignis ausgelöst. Innerhalb dieses Handlers werden die Umwandlungsverbindung erstellt und die Umwandlung gestartet.

Stellen Sie zunächst sicher, dass das Geräteüberwachungselement beendet wurde, sodass kein Konflikt zwischen Geräteenumeration und Medienumwandlung auftritt. Erstellen Sie eine Umwandlungsverbindung, indem Sie CreateCastingConnection für das vom Benutzer ausgewählte CastingDevice-Objekt aufrufen. Fügen Sie Ereignishandler für die Ereignisse StateChanged und ErrorOccurred hinzu.

Starten Sie die Medienumwandlung durch Aufrufen von RequestStartCastingAsync, und übergeben Sie dabei die Umwandlungsquelle, die durch den Aufruf der MediaPlayer-Methode GetAsCastingSource zurückgegeben wurde. Machen Sie zum Schluss die Schaltfläche zum Trennen sichtbar, damit der Benutzer die Medienumwandlung beenden kann.

private async void castingDevicesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (castingDevicesListBox.SelectedItem != null)
    {
        //When a device is selected, first thing we do is stop the watcher so it's search doesn't conflict with streaming
        if (deviceWatcher.Status != DeviceWatcherStatus.Stopped)
        {
            deviceWatcher.Stop();
        }

        //Create a new casting connection to the device that's been selected
        castingConnection = ((CastingDevice)castingDevicesListBox.SelectedItem).CreateCastingConnection();

        //Register for events
        castingConnection.ErrorOccurred += Connection_ErrorOccurred;
        castingConnection.StateChanged += Connection_StateChanged;

        //Cast the loaded video to the selected casting device.
        await castingConnection.RequestStartCastingAsync(mediaPlayerElement.MediaPlayer.GetAsCastingSource());
        disconnectButton.Visibility = Visibility.Visible;
    }
}

Im Ereignishandler für geänderten Zustand hängt die ausgeführte Aktion vom neuen Zustand der Umwandlungsverbindung ab:

  • Beim Zustand Connected oder Rendering stellen Sie sicher, dass das ProgressRing-Steuerelement inaktiv ist und die Schaltfläche zum Trennen angezeigt wird.
  • Beim Zustand Disconnected heben Sie die Auswahl des aktuellen Umwandlungsgerät im Listenfeld auf, deaktivieren Sie das ProgressRing-Steuerelement, und blenden Sie die Schaltfläche zum Trennen aus.
  • Beim Zustand Connecting aktivieren Sie das ProgressRing-Steuerelement, und blenden Sie die Schaltfläche zum Trennen aus.
  • Beim Zustand Disconnecting aktivieren Sie das ProgressRing-Steuerelement, und blenden Sie die Schaltfläche zum Trennen aus.
private async void Connection_StateChanged(CastingConnection sender, object args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Update the UX based on the casting state
        if (sender.State == CastingConnectionState.Connected || sender.State == CastingConnectionState.Rendering)
        {
            disconnectButton.Visibility = Visibility.Visible;
            watcherProgressRing.IsActive = false;
        }
        else if (sender.State == CastingConnectionState.Disconnected)
        {
            disconnectButton.Visibility = Visibility.Collapsed;
            castingDevicesListBox.SelectedItem = null;
            watcherProgressRing.IsActive = false;
        }
        else if (sender.State == CastingConnectionState.Connecting)
        {
            disconnectButton.Visibility = Visibility.Collapsed;
            ShowMessageToUser("Connecting");
            watcherProgressRing.IsActive = true;
        }
        else
        {
            //Disconnecting is the remaining state
            disconnectButton.Visibility = Visibility.Collapsed;
            watcherProgressRing.IsActive = true;
        }
    });
}

Aktualisieren Sie im Handler für das ErrorOccurred-Ereignis die Benutzeroberfläche, um den Benutzer darüber zu informieren, dass ein Umwandlungsfehler aufgetreten ist, und heben Sie die Auswahl des aktuellen CastingDevice-Objekts im Listenfeld auf.

private async void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        //Clear the selection in the listbox on an error
        ShowMessageToUser("Casting Error: " + args.Message);
        castingDevicesListBox.SelectedItem = null;
    });
}

Implementieren Sie zum Schluss den Handler für die Schaltfläche zum Trennen. Beenden Sie die Medienumwandlung, und trennen Sie die Verbindung mit dem Umwandlungsgerät, indem Sie die DisconnectAsync-Methode des CastingConnection-Objekts aufrufen. Dieser Aufruf muss durch Aufrufen von CoreDispatcher.RunAsync an den UI-Thread weitergeleitet werden.

private async void disconnectButton_Click(object sender, RoutedEventArgs e)
{
    if (castingConnection != null)
    {
        //When disconnect is clicked, the casting conneciton is disconnected.  The video should return locally to the media element.
        await castingConnection.DisconnectAsync();
    }
}