Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Artikel erfahren Sie, wie Sie Medien von einer WinUI-App auf Remotegeräte umwandeln.
Integrierte Medienübertragung über MediaPlayerElement
Die einfachste Möglichkeit zum Umwandeln von Medien aus einer WinUI-App besteht darin, die integrierte Umwandlungsfunktion des MediaPlayerElement-Steuerelements zu verwenden.
Fügen Sie in der XAML-Datei Ihrer 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, mit der der Benutzer die Auswahl einer Datei initiieren kann.
<Button x:Name="bOpenButton" Click="bOpenButton_Click" Content="Open"/>
Erstellen Sie im Click-Ereignishandler für den Button eine neue Instanz des FileOpenPicker, fügen Sie der FileTypeFilter-Collection Videodateitypen hinzu und legen Sie den Startspeicherort auf die Videobibliothek des Benutzers fest.
Rufen Sie PickSingleFileAsync auf, um das Dialogfeld "Dateiauswahl" zu starten. Wenn diese Methode zurückgegeben wird, ist das Ergebnis ein StorageFile-Objekt , das die Videodatei darstellt. Stellen Sie sicher, dass die Datei nicht NULL ist, was der Fall ist, wenn der Benutzer den Auswahlvorgang abbricht. Rufen Sie die OpenAsync-Methode der Datei auf, um einen IRandomAccessStream für die Datei abzurufen. Erstellen Sie schließlich ein neues MediaSource-Objekt aus der ausgewählten Datei, indem Sie CreateFromStorageFile aufrufen und es der Source-Eigenschaft des MediaPlayerElement-Objekts zuweisen, um die Videodatei zur Videoquelle für das Steuerelement zu machen.
private async void bOpenButton_Click(object sender, RoutedEventArgs e)
{
//Create a new picker
var filePicker = new Microsoft.Windows.Storage.Pickers.FileOpenPicker(this.AppWindow.Id)
{
SuggestedStartLocation = PickerLocationId.VideosLibrary,
FileTypeFilter = { ".wmv", ".mp4", ".mkv" },
};
//Retrieve file from picker
var result = await filePicker.PickSingleFileAsync();
if (result is not null)
{
var storageFile = await Windows.Storage.StorageFile.GetFileFromPathAsync(result.Path);
mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(storageFile);
mediaPlayerElement.MediaPlayer.Play();
}
}
Sobald das Video im MediaPlayerElement geladen wurde, kann der Benutzer einfach die Umwandlungsschaltfläche auf den Transportsteuerelementen drücken, um ein integriertes Dialogfeld zu starten, das es ihnen ermöglicht, ein Gerät auszuwählen, in das die geladenen Medien casten.
Medienübertragung mit CastingDevicePicker
Eine zweite Möglichkeit zum Umwandeln von Medien in ein Gerät ist die Verwendung von CastingDevicePicker. Deklarieren Sie zunächst eine Membervariable für das Windows.Media.Casting.CastingDevicePicker-Objekt .
CastingDevicePicker castingPicker;
Erstellen Sie beim Initialisieren des Fensters eine neue Instanz der Casting-Auswahl und legen Sie die Eigenschaft "Filter" auf SupportsVideo fest, um anzugeben, dass die von der Auswahl aufgelisteten Casting-Geräte Video unterstützen sollen. 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 Ihrer XAML-Datei eine Schaltfläche hinzu, mit der der Benutzer die Auswahl starten kann.
<Button x:Name="bCastPickerButton" Content="Cast Button" Click="bCastPickerButton_Click"/>
Im Click-Ereignishandler der Schaltfläche rufen Sie TransformToVisual auf, um die Transformation eines UI-Elements relativ zu einem anderen Element zu erhalten. In diesem Beispiel ist der Transform die Position der Cast-Picker-Schaltfläche relativ zur visuellen Wurzel des Anwendungsfensters. Rufen Sie die Show-Methode des CastingDevicePicker-Objekts auf, um das Dialogfeld für den Casting-Picker zu starten. Geben Sie die Position und Abmessungen der Schaltfläche für die Cast-Auswahl an, damit das Dialogfeld von der Schaltfläche, die der Benutzer gedrückt hat, ausgehen kann.
private void bCastPickerButton_Click(object sender, RoutedEventArgs e)
{
//Retrieve the location of the casting button
GeneralTransform transform = bCastPickerButton.TransformToVisual(this.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, bCastPickerButton.ActualWidth, bCastPickerButton.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 Casting-Gerät darstellt. Registrieren Sie Handler für die Ereignisse ErrorOccurred und StateChanged . Rufen Sie schließlich RequestStartCastingAsync auf, um mit der Umwandlung zu beginnen, und übergeben Sie das Ergebnis an die GetAsCastingSource-Methode des MediaPlayer-Objekts des MediaPlayer-Steuerelements, um anzugeben, dass das zu umwandelnde Medium der Inhalt des MediaPlayers ist, der dem MediaPlayerElement zugeordnet ist.
Hinweis
Die Casting-Verbindung muss im UI-Thread initiiert werden. Da castingDeviceSelected nicht im UI-Thread aufgerufen wird, müssen Sie diese Aufrufe in einem Aufruf von DispatcherQueue.TryEnqueue platzieren, wodurch sie im UI-Thread aufgerufen werden.
private void CastingPicker_CastingDeviceSelected(CastingDevicePicker sender, CastingDeviceSelectedEventArgs args)
{
//Casting must occur from the UI thread. This dispatches the casting calls to the UI thread.
DispatcherQueue.TryEnqueue( 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());
});
}
In den Ereignishandlern ErrorOccurred und StateChanged sollten Sie Ihre Benutzeroberfläche (UI) aktualisieren, um den Benutzer über den aktuellen Casting-Status zu informieren. Diese Ereignisse werden im folgenden Abschnitt zum Erstellen einer benutzerdefinierten Umwandlungsgeräteauswahl ausführlich erläutert.
private void Connection_StateChanged(CastingConnection sender, object args)
{
DispatcherQueue.TryEnqueue( () =>
{
ShowMessageToUser("Casting Connection State Changed: " + sender.State);
});
}
private void Connection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
DispatcherQueue.TryEnqueue(() =>
{
ShowMessageToUser("Casting Connection State Changed: " + sender.State);
});
}
Medienumwandlung mit einer benutzerdefinierten Geräteauswahl
Im folgenden Abschnitt wird beschrieben, wie Sie eine eigene Benutzeroberfläche für die Umwandlungsgeräteauswahl erstellen, indem Sie die Umwandlungsgeräte aufzählen und die Verbindung aus Ihrem Code initiieren.
Fügen Sie der XAML-Seite die folgenden Steuerelemente hinzu, um die rudimentäre Benutzeroberfläche für dieses Beispiel zu implementieren:
- Eine Schaltfläche zum Starten des Gerätebeobachters, der nach verfügbaren Casting-Geräten sucht.
- Ein ProgressRing-Steuerelement, um dem Benutzer eine Rückmeldung zu geben, dass die Aufzählung der Casting-Elemente noch im Gange ist.
- Ein ListBox-Objekt zum Auflisten der ermittelten Umwandlungsgeräte. Definieren Sie eine ItemTemplate für das Steuerelement, damit wir die Umwandlungsgeräteobjekte direkt dem Steuerelement zuweisen und die FriendlyName-Eigenschaft weiterhin anzeigen können.
- Eine Schaltfläche, mit der der Benutzer das Umwandlungsgerät trennen kann.
<Button x:Name="bStartWatcherButton" Content="Watcher Button" Click="bStartWatcherButton_Click"/>
<ProgressRing x:Name="prWatcherProgressRing" IsActive="False"/>
<ListBox x:Name="lbCastingDevicesListBox" MaxWidth="300" HorizontalAlignment="Left" SelectionChanged="lbCastingDevicesListBox_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="bDisconnectButton" Content="Disconnect" Click="bDisconnectButton_Click" Visibility="Collapsed"/>
Deklarieren Sie in Ihrer Code-Behind-Datei Mitgliedervariablen für DeviceWatcher und CastingConnection.
DeviceWatcher deviceWatcher;
CastingConnection castingConnection;
Aktualisieren Sie im Click-Handler für den startWatcherButton zunächst die Benutzeroberfläche, indem Sie die Schaltfläche deaktivieren und den Fortschrittsring aktivieren, während die Geräteaufzählung läuft. Deaktivieren Sie das Listenfeld von Umwandlungsgeräten.
Erstellen Sie als Nächstes eine Geräteüberwachung, indem Sie DeviceInformation.CreateWatcher aufrufen. Diese Methode kann verwendet werden, um auf viele verschiedene Gerätetypen zu achten. Geben Sie an, dass Sie nach Geräten suchen möchten, die die Videoübertragung unterstützen, indem Sie die von CastingDevice.GetDeviceSelector zurückgegebene Geräteauswahlzeichenfolge verwenden.
Registrieren Sie schließlich Ereignishandler für die Ereignisse Added, Removed, EnumerationCompleted und Stopped.
private void bStartWatcherButton_Click(object sender, RoutedEventArgs e)
{
bStartWatcherButton.IsEnabled = false;
prWatcherProgressRing.IsActive = true;
lbCastingDevicesListBox.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 Watcher erkannt wird. Erstellen Sie im Handler für dieses Ereignis ein neues CastingDevice-Objekt , indem Sie CastingDevice.FromIdAsync aufrufen und die ID des ermittelten Umwandlungsgeräts übergeben, das im an den Handler übergebenen DeviceInformation-Objekt enthalten ist.
Fügen Sie " CastingDevice " zum ListBox-Umwandlungsgerät hinzu, damit der Benutzer es auswählen kann. Aufgrund der im XAML definierten ItemTemplate wird die FriendlyName-Eigenschaft als Elementtext für das Listenfeld verwendet. Da dieser Ereignishandler nicht im UI-Thread aufgerufen wird, müssen Sie die Benutzeroberfläche innerhalb eines Aufrufs von DispatcherQueue.TryEnqueue aktualisieren.
private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
DispatcherQueue.TryEnqueue(async () =>
{
//Add each discovered device to our listbox
CastingDevice addedDevice = await CastingDevice.FromIdAsync(args.Id);
lbCastingDevicesListBox.Items.Add(addedDevice);
});
}
Das Removed-Ereignis wird ausgelöst, wenn der Watcher erkennt, dass ein Umwandlungsgerät nicht mehr vorhanden ist. Vergleichen Sie die ID-Eigenschaft des hinzugefügten Objekts, das an den Handler übergeben wird, mit der ID jedes hinzugefügten Objekts in der Items-Auflistung des Listenfelds. Wenn die ID übereinstimmt, entfernen Sie dieses Objekt aus der Auflistung. Da die Benutzeroberfläche aktualisiert wird, muss dieser Aufruf innerhalb eines RunAsync-Aufrufs erfolgen.
private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
DispatcherQueue.TryEnqueue( () =>
{
foreach (CastingDevice currentDevice in lbCastingDevicesListBox.Items)
{
if (currentDevice.Id == args.Id)
{
lbCastingDevicesListBox.Items.Remove(currentDevice);
}
}
});
}
Das EnumerationCompleted-Ereignis wird ausgelöst, wenn der Watcher die Erkennung von Geräten abgeschlossen hat. Aktualisieren Sie im Handler für dieses Ereignis die Benutzeroberfläche, um dem Benutzer mitzuteilen, dass die Geräteenumeration abgeschlossen ist, und beenden Sie die Geräteüberwachung, indem Sie "Stop" aufrufen.
private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
DispatcherQueue.TryEnqueue(() =>
{
//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 der Geräteüberwacher das Stoppen abgeschlossen hat. Beenden Sie im Handler für dieses Ereignis das ProgressRing-Steuerelement , und lassen Sie das StartWatcherButton-Element wieder auf , damit der Benutzer den Prozess der Geräteaufzählung neu starten kann.
private void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
{
DispatcherQueue.TryEnqueue( () =>
{
//Update UX when the watcher stops
bStartWatcherButton.IsEnabled = true;
prWatcherProgressRing.IsActive = false;
});
}
Wenn der Benutzer eines der Umwandlungsgeräte aus dem Listenfeld auswählt, wird das SelectionChanged-Ereignis ausgelöst. Innerhalb dieses Handlers wird die Umwandlungsverbindung erstellt und die Umwandlung gestartet.
Stellen Sie zunächst sicher, dass die Gerätebeobachtung beendet ist, damit die Geräteaufzählung das Streaming nicht beeinträchtigt. Erstellen Sie eine Casting-Verbindung, 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, indem Sie RequestStartCastingAsync aufrufen, und übergeben Sie die Umwandlungsquelle, die durch Aufrufen der MediaPlayer-MethodeGetAsCastingSource zurückgegeben wird. Machen Sie schließlich die Schaltfläche zum Trennen sichtbar, damit der Benutzer das Medienstreaming beenden kann.
private async void lbCastingDevicesListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lbCastingDevicesListBox.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)lbCastingDevicesListBox.SelectedItem).CreateCastingConnection();
//Register for events
castingConnection.ErrorOccurred += CastingConnection_ErrorOccurred; ;
castingConnection.StateChanged += CastingConnection_StateChanged; ;
//Cast the loaded video to the selected casting device.
await castingConnection.RequestStartCastingAsync(mediaPlayerElement.MediaPlayer.GetAsCastingSource());
bDisconnectButton.Visibility = Visibility.Visible;
}
}
Im Zustand geänderter Handler hängt die aktion, die Sie ausführen, vom neuen Zustand der Umwandlungsverbindung ab:
- Wenn der Zustand "Verbunden " oder "Rendering" lautet, stellen Sie sicher, dass das ProgressRing-Steuerelement inaktiv ist und die Schaltfläche zum Trennen angezeigt wird.
- Wenn der Zustand getrennt ist, heben Sie die Auswahl des aktuellen Umwandlungsgeräts im Listenfeld auf, machen Sie das ProgressRing-Steuerelement inaktiv, und blenden Sie die Schaltfläche "Trennen" aus.
- Wenn der Status "Verbinden" lautet, aktivieren Sie das ProgressRing-Steuerelement und blenden Sie die Schaltfläche "Trennen" aus.
- Aktivieren Sie das ProgressRing-Steuerelement, wenn der Status "Trennen" lautet, und blenden Sie die Schaltfläche "Trennen" aus.
private void CastingConnection_StateChanged(CastingConnection sender, object args)
{
DispatcherQueue.TryEnqueue( () =>
{
//Update the UX based on the casting state
if (sender.State == CastingConnectionState.Connected || sender.State == CastingConnectionState.Rendering)
{
bDisconnectButton.Visibility = Visibility.Visible;
prWatcherProgressRing.IsActive = false;
}
else if (sender.State == CastingConnectionState.Disconnected)
{
bDisconnectButton.Visibility = Visibility.Collapsed;
lbCastingDevicesListBox.SelectedItem = null;
prWatcherProgressRing.IsActive = false;
}
else if (sender.State == CastingConnectionState.Connecting)
{
bDisconnectButton.Visibility = Visibility.Collapsed;
ShowMessageToUser("Connecting");
prWatcherProgressRing.IsActive = true;
}
else
{
//Disconnecting is the remaining state
bDisconnectButton.Visibility = Visibility.Collapsed;
prWatcherProgressRing.IsActive = true;
}
});
}
Aktualisieren Sie im Handler für das ErrorOccurred-Ereignis die Benutzeroberfläche, damit der Benutzer weiß, dass ein Casting-Fehler aufgetreten ist, und heben Sie die Auswahl des aktuellen CastingDevice-Objekts im Listenfeld auf.
private void CastingConnection_ErrorOccurred(CastingConnection sender, CastingConnectionErrorOccurredEventArgs args)
{
DispatcherQueue.TryEnqueue( () =>
{
//Clear the selection in the listbox on an error
ShowMessageToUser("Casting Error: " + args.Message);
lbCastingDevicesListBox.SelectedItem = null;
});
}
Implementieren Sie schließlich den Handler für die Schaltfläche "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 DispatcherQueue.TryEnqueue an den UI-Thread verteilt werden.
private async void bDisconnectButton_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();
}
}
Windows developer