媒体播放器
媒体播放涉及通过内联(嵌入在页面中或使用一组其他控件)或专用全屏体验来观看和收听视频和音频。
用户需要一个基本控制集(如播放/暂停、快退、快进),你可以根据需要进行修改(包括媒体播放器的按钮、控件条的背景以及控件排列或布局)。
这是正确的控件吗?
在应用中播放音频或视频时,请使用媒体播放器。 若要显示图像集合,请使用 翻转视图。
建议
媒体播放器支持浅色和深色主题,但深色主题为大多数娱乐场景提供了更好的体验。 深色背景提供更好的对比度,特别是对于低光条件,并限制控制栏干扰观看体验。
播放视频内容时,通过通过内联模式提升全屏模式来鼓励专门的观看体验。 全屏查看体验是最佳的,并且选项在内联模式下受到限制。
如果你有屏幕空间,请使用双行布局。 它为控件提供了比压缩的单行布局更多的空间,并且更易于使用各种输入进行导航。
默认控件已针对媒体播放进行了优化,但你可以向媒体播放器添加所需的自定义选项,以便为应用提供最佳体验。 访问 “创建自定义传输控件 ”,详细了解如何添加自定义控件。
UWP 和 WinUI 2
重要
本文中的信息和示例是针对使用 Windows App SDK 和 WinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请查看 UWP API 参考。
本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。
此控件的 API 存在于 Windows.UI.Xaml.Controls 命名空间中。
- UWP API:MediaPlayerElement 类、MediaTransportControls 类
- 打开 WinUI 2 库应用并查看 MediaPlayerElement 的操作。 WinUI 2 库应用包括大多数 WinUI 2 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码。
建议使用最新的 WinUI 2 来获取所有控件的最新样式和模板。 WinUI 2.2 或更高版本包含此控件的使用圆角的新模板。 有关详细信息,请参阅圆角半径。
如果要针对 10 英尺的体验进行设计,请使用双行布局。 它为控件提供了比紧凑单行布局更多的空间,并且更容易使用 10 英尺的游戏板进行导航。 有关优化应用程序的 10 英尺体验的详细信息,请参阅 Xbox 和电视设计文章。
MediaPlayerElement
仅在 Windows 10 版本 1607 及更高版本中可用。 如果要针对早期版本的 Windows 10 开发应用,你需要改用 MediaElement 控件。 此处提出的所有建议也适用于此文 MediaElement
。
创建媒体播放器
WinUI 3 库应用包括大多数 WinUI 3 控件、特性和功能的交互式示例。 通过 Microsoft Store 获取应用,或在 GitHub 上获取源代码
通过在 XAML 中创建 MediaPlayerElement 对象并将源设置为指向音频或视频文件的 MediaSource,将媒体添加到应用。
此 XAML 创建 MediaPlayerElement 并将其 Source 属性设置为应用本地视频文件的 URI。 页面 MediaPlayerElement
加载时开始播放。 若要立即禁止媒体启动,可以将“自动播放”属性设置为 false
。
<MediaPlayerElement x:Name="mediaPlayerElement"
Source="ms-appx:///Videos/video1.mp4"
Width="400" AutoPlay="True"/>
此 XAML 创建启用了 内置传输控件的 MediaPlayerElement ,并将 AutoPlay 属性设置为 false.
<MediaPlayerElement x:Name="mediaPlayerElement"
Source="ms-appx:///Videos/video1.mp4"
Width="400"
AutoPlay="False"
AreTransportControlsEnabled="True"/>
重要
设置为 MediaPlayerElement.Source
相对 URI(ms-appx/ms-resource)仅适用于使用 Windows 应用程序打包项目打包的应用。 如果你的应用不使用 Windows 应用程序打包项目,建议的解决方法是将相对 ms-appx:///
URI 转换为完全解析的 file:///
URI。 另请参阅本文后面的“ 设置媒体源 ”和 “打开本地媒体文件 ”部分。
媒体传输控件
MediaPlayerElement 具有处理播放、停止、暂停、音量、静音、搜寻/进度、隐藏式字幕和音轨选择的内置传输控件。 若要启用这些控件,请将 AreTransportControlsEnabled 设置为 true
. 若要禁用它们,请设置为 AreTransportControlsEnabled
false
. 传输控件由 MediaTransportControls 类表示。 可以按原样使用传输控件,也可以通过各种方式自定义它们。 有关详细信息,请参阅 MediaTransportControls 类引用和创建自定义传输控件。
传输控件支持单行和双行布局。 此处的第一个示例是单行布局,其中播放/暂停按钮位于媒体时间线左侧。 此布局最适合用于内联媒体播放和紧凑屏幕。
对于大多数使用方案(尤其是较大的屏幕),建议使用双行控件布局(如下所示)。 此布局为控件提供更多空间,使用户能够更轻松地操作日程表。
系统媒体传输控件
MediaPlayerElement 自动与系统媒体传输控件集成。 系统媒体传输控件是按下硬件媒体键时弹出的控件,例如键盘上的媒体按钮。 有关详细信息,请参阅 SystemMediaTransportControls。
设置媒体源
若要在嵌入应用的网络或文件中播放文件,请将 Source 属性设置为具有文件路径的 MediaSource。
提示
若要从 Internet 打开文件,需要在应用的清单(Package.appxmanifest)中声明 Internet(客户端) 功能。 有关声明功能的详细信息,请参阅应用功能声明。
此代码尝试将使用 XAML 定义的 MediaPlayerElement 的 Source 属性设置为输入到 TextBox 中的文件路径。
<TextBox x:Name="txtFilePath" Width="400"
FontSize="20"
KeyUp="TxtFilePath_KeyUp"
Header="File path"
PlaceholderText="Enter file path"/>
private void TxtFilePath_KeyUp(object sender, KeyRoutedEventArgs e)
{
if (e.Key == Windows.System.VirtualKey.Enter)
{
TextBox tbPath = sender as TextBox;
if (tbPath != null)
{
LoadMediaFromString(tbPath.Text);
}
}
}
private void LoadMediaFromString(string path)
{
try
{
Uri pathUri = new Uri(path);
mediaPlayerElement.Source = MediaSource.CreateFromUri(pathUri);
}
catch (Exception ex)
{
if (ex is FormatException)
{
// handle exception.
// For example: Log error or notify user problem with file
}
}
}
若要将媒体源设置为嵌入在应用中的媒体文件,请初始化路径为ms-appx:///
前缀的 URI,使用 Uri 创建 MediaSource,然后将源设置为 Uri。 例如,对于名为“视频”子文件夹中video1.mp4的文件,路径如下所示:ms-appx:///Videos/video1.mp4
重要
设置为 MediaPlayerElement.Source
相对 URI(ms-appx/ms-resource)仅适用于使用 Windows 应用程序打包项目打包的应用。
此代码将以前在 XAML 中定义的 MediaPlayerElement 的 Source 属性设置为 ms-appx:///Videos/video1.mp4
。
private void LoadEmbeddedAppFile()
{
try
{
Uri pathUri = new Uri("ms-appx:///Videos/video1.mp4");
mediaPlayerElement.Source = MediaSource.CreateFromUri(pathUri);
}
catch (Exception ex)
{
if (ex is FormatException)
{
// handle exception.
// For example: Log error or notify user problem with file
}
}
}
打开本地媒体文件
若要在本地系统或 OneDrive 上打开文件,可以使用 FileOpenPicker 获取文件和 源 来设置媒体源,也可以以编程方式访问用户媒体文件夹。
例如,如果你的应用需要访问而无需用户与音乐或视频文件夹交互,例如,如果要枚举用户集合中的所有音乐或视频文件并在应用中显示它们,则需要声明音乐库和视频库功能。 有关详细信息,请参阅音乐、图片和视频库中的文件和文件夹。
FileOpenPicker 不需要特殊功能即可访问本地文件系统上的文件(例如用户的音乐或视频文件夹),因为用户对所访问的文件具有完全控制权。 从安全和隐私的角度来看,最好尽量减少应用使用的功能数量。
使用 FileOpenPicker 打开本地媒体
调用 FileOpenPicker 以允许用户选取媒体文件。
使用 FileOpenPicker 类选择媒体文件。 设置 FileTypeFilter 以指定显示的文件类型
FileOpenPicker
。 调用 PickSingleFileAsync 以启动文件选取器并获取文件。使用 MediaSource 将所选媒体文件设置为 MediaPlayerElement.Source。
若要使用 FileOpenPicker 返回的 StorageFile,需要在 MediaSource 上调用 CreateFromStorageFile 方法,并将其设置为 MediaPlayerElement 的源。 然后对 MediaPlayerElement.MediaPlayer 调用 Play 以启动媒体。
此示例演示如何使用 FileOpenPicker 选择文件并将该文件设置为 MediaPlayerElement 的 Source。
<MediaPlayerElement x:Name="mediaPlayerElement"/>
...
<Button Content="Choose file" Click="Button_Click"/>
private async void Button_Click(object sender, RoutedEventArgs e)
{
await SetLocalMedia();
}
async private System.Threading.Tasks.Task SetLocalMedia()
{
var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, WinRT.Interop.WindowNative.GetWindowHandle(this));
openPicker.FileTypeFilter.Add(".wmv");
openPicker.FileTypeFilter.Add(".mp4");
openPicker.FileTypeFilter.Add(".wma");
openPicker.FileTypeFilter.Add(".mp3");
var file = await openPicker.PickSingleFileAsync();
// mediaPlayerElement is a MediaPlayerElement control defined in XAML
if (file != null)
{
mediaPlayerElement.Source = MediaSource.CreateFromStorageFile(file);
mediaPlayerElement.MediaPlayer.Play();
}
}
设置海报源
可以在加载媒体之前使用 PosterSource 属性为 MediaPlayerElement 提供可视表示形式。 是 PosterSource
一个图像,如屏幕截图、电影海报或专辑艺术,用于代替媒体。 在以下情况下显示:PosterSource
- 未设置有效的源时。 例如,源未设置、
Source
已设置为null
或源无效(如发生 MediaFailed 事件时的情况)。 - 正在加载媒体时。 例如,设置了有效的源,但 尚未发生 MediaOpened 事件。
- 当媒体流式传输到另一台设备时。
- 仅当媒体为音频时。
下面是一个 MediaPlayerElement ,其 Source 设置为专辑曲目,并将 PosterSource 设置为专辑封面的图像。
<MediaPlayerElement Source="ms-appx:///Media/Track1.mp4" PosterSource="ms-appx:///Media/AlbumCover.png"/>
使设备的屏幕保持活动状态
通常,设备会将显示器变暗(并最终关闭),以便在用户离开时节省电池使用时间,但视频应用需要保持屏幕,以便用户能够看到视频。 若要防止在不再检测到用户操作时停用显示,例如当应用正在播放视频时,可以调用 DisplayRequest.RequestActive。 DisplayRequest 类允许你告诉 Windows 保持显示打开状态,以便用户能够看到视频。
若要节省电源和电池使用时间,应调用 DisplayRequest.RequestRelease ,以在不再需要显示请求时释放显示请求。 当应用离开屏幕时,Windows 会自动停用应用的活动显示请求,并在应用返回到前台时重新激活它们。
在以下情况下应该释放显示请求:
- 视频播放因带宽有限而暂停,例如,用户操作、缓冲或调整。
- 播放停止。 例如,视频播放完毕或完成演示文稿。
- 出现播放错误。 例如,存在网络连接问题或损坏的文件。
使屏幕保持活动状态
创建全局 DisplayRequest 变量。 将其初始化为
null
.private DisplayRequest appDisplayRequest = null;
调用 RequestActive 以通知 Windows 应用要求显示保持打开状态。
每当视频播放停止、暂停或因播放错误中断时,调用 RequestRelease 释放显示请求。 当应用不再有任何活动显示请求时,Windows 通过在不使用设备时将显示器变暗(并最终关闭)来节省电池使用时间。
每个 MediaPlayerElement.MediaPlayer 都有 MediaPlaybackSession 类型的 PlaybackSession,用于控制媒体播放的各个方面,如 PlaybackRate、PlaybackState 和 Position。 此处,你对 MediaPlayer.PlaybackSession 使用 PlaybackStateChanged 事件检测应释放显示请求的情况。 然后,使用 NaturalVideoHeight 属性确定音频或视频文件是否正在播放,并且仅在播放视频时使屏幕保持活动状态。
<MediaPlayerElement x:Name="mediaPlayerElement" Source="ms-appx:///Videos/video1.mp4"/>
public sealed partial class MainWindow : Window
{
public DisplayRequest appDisplayRequest = null;
// using Microsoft.UI.Dispatching;
private DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread();
public MainWindow()
{
this.InitializeComponent();
mediaPlayerElement.MediaPlayer.PlaybackSession.PlaybackStateChanged +=
PlaybackSession_PlaybackStateChanged;
}
private void PlaybackSession_PlaybackStateChanged(MediaPlaybackSession sender, object args)
{
MediaPlaybackSession playbackSession = sender as MediaPlaybackSession;
if (playbackSession != null && playbackSession.NaturalVideoHeight != 0)
{
if (playbackSession.PlaybackState == MediaPlaybackState.Playing)
{
if (appDisplayRequest is null)
{
dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
{
appDisplayRequest = new DisplayRequest();
appDisplayRequest.RequestActive();
});
}
}
else // PlaybackState is Buffering, None, Opening, or Paused.
{
if (appDisplayRequest is not null)
{
appDisplayRequest.RequestRelease();
appDisplayRequest = null;
}
}
}
}
}
以编程方式控制媒体播放器
MediaPlayerElement 提供了许多属性、方法和事件,用于通过 MediaPlayerElement.MediaPlayer 属性控制音频和视频播放。 有关属性、方法和事件的完整列表,请参阅 MediaPlayer 参考页。
高级媒体播放方案
对于更复杂的媒体播放方案,例如播放播放列表、切换音频语言或创建自定义元数据曲目,请将 MediaPlayerElement.Source 设置为 MediaPlaybackItem 或 MediaPlaybackList。 有关如何启用各种高级媒体功能的详细信息,请参阅媒体播放页。
调整和拉伸视频的大小
使用 Stretch 属性可更改视频内容和/或 PosterSource 填充容器的方式。 这会根据 Stretch 值调整视频大小并拉伸 视频。 这些 Stretch
状态类似于许多电视机上的图片大小设置。 你可以将此关联到按钮,并允许用户选择他们喜欢的设置。
- 无 一项以原始大小显示内容的本机分辨率。这可能会导致视频边缘裁剪或黑条。
- 统 一填充尽可能多的空间,同时保留纵横比和视频内容。 这可能会导致视频边缘的水平或垂直黑条。 这类似于宽屏模式。
- UniformToFill 会 填充整个空间,同时保留纵横比。 这可能会导致一些视频被裁剪。 这类似于全屏模式。
- 填充 整个空间,但不保留纵横比。 不会裁剪任何视频,但可能会进行拉伸。 这类似于拉伸模式。
在这里, AppBarButton 用于循环访问 Stretch 选项。 语句switch
检查 Stretch 属性的当前状态,并将其设置为枚举中的Stretch
下一个值。 这样,用户就可以循环浏览不同的拉伸状态。
<AppBarButton Icon="Trim"
Label="Resize Video"
Click="PictureSize_Click" />
private void PictureSize_Click(object sender, RoutedEventArgs e)
{
switch (mediaPlayerElement.Stretch)
{
case Stretch.Fill:
mediaPlayerElement.Stretch = Stretch.None;
break;
case Stretch.None:
mediaPlayerElement.Stretch = Stretch.Uniform;
break;
case Stretch.Uniform:
mediaPlayerElement.Stretch = Stretch.UniformToFill;
break;
case Stretch.UniformToFill:
mediaPlayerElement.Stretch = Stretch.Fill;
break;
default:
break;
}
}
启用低延迟播放
将 RealTimePlayback 属性设置为 true
MediaPlayerElement.MediaPlayer ,使媒体播放器元素能够减少播放的初始延迟。 这对于双向通信应用至关重要,适用于某些游戏方案。 请注意,此模式的资源密集型程度更高,电源效率更低。
此示例创建 MediaPlayerElement 并将 RealTimePlayback 设置为 true
。
MediaPlayerElement mediaPlayerElement = new MediaPlayerElement();
mediaPlayerElement.MediaPlayer.RealTimePlayback = true;