MediaElement 拒绝循环

MediaElement is refusing to loop

所以我试图在我的 UWP 应用程序中循环播放背景音乐,我有一个名为 soundControl 的 class 来处理音乐和声音,如下所示:

public class soundControl
{
    private static MediaElement loop = new MediaElement();
    public static async void stopLoop()
    {
        loop.Stop();
    }
    public static async void loadLoopTimeBG()
    {
         Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(@"Assets\Sounds");
        Windows.Storage.StorageFile file = await folder.GetFileAsync("battle.wav");
        var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
        loop.AutoPlay = false;
        loop.SetSource(stream, file.ContentType);
        loop.IsLooping = true;
    }
    public static  void loopTimeBG()
    {
        loop.Play();
    }

每当我想播放这首音乐时,我都会拨打电话:

soundControl.loadLoopTimeBG();    
soundControl.loopTimeBG();

问题是它只播放一次就停止了,我不知道为什么 我尝试了另一种方法,例如:

loop.MediaEnded += mediaEnded;

和这样的事件处理程序:

    private static void mediaEnded(object sender, RoutedEventArgs e)
    {
        loop.Position = TimeSpan.Zero;
        loop.Play();
    }

它也不起作用,在调试时它甚至不会在音乐播放完毕时触发 mediaEnded 事件。

如有任何帮助,我们将不胜感激。 谢谢

MediaPlayer

Windows.Media.Playback.MediaPlayer 是不需要在 XAML 可视化树中的 recommended player for UWP

其API与MediaElement非常相似:

private static MediaPlayer _mediaPlayer = new MediaPlayer();

public static async Task PlayUsingMediaPlayerAsync()
{
    Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(@"Assets");
    Windows.Storage.StorageFile file = await folder.GetFileAsync("Click.wav");
    _mediaPlayer.AutoPlay = false;
    _mediaPlayer.Source = MediaSource.CreateFromStorageFile(file);

    _mediaPlayer.MediaOpened += _mediaPlayer_MediaOpened;

    _mediaPlayer.IsLoopingEnabled = true;

}

private static void _mediaPlayer_MediaOpened(MediaPlayer sender, object args)
{
    sender.Play();
}

您甚至可以使用 MediaPlayerElement 在 XAML 中显示 MediaPlayer 的视觉效果。

MediaPlayer 允许使用 MediaPlaybackList 支持循环、随机播放和无缝播放的更高级播放方案。

mediaElement.SetPlaybackSource(mediaPlaybackList);

MediaElement

经过一番挖掘,似乎有两个问题。

MediaElement 是基于 XAML 的控件(在 Windows.UI.Xaml.Controls 命名空间中),在实际附加到可视化树之前,它似乎无法正常工作。一旦您将 MediaElement 放在页面上,它就会按预期工作。

其次,加载源媒体不会立即发生。设置源后,控件需要一些时间来实际加载媒体。为此,您可以使用 MediaOpened 事件,它会在真正加载后通知您。

所以代码可能看起来像这样:

public static async Task LoadAndPlayAsync()
{
    Windows.Storage.StorageFolder folder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync(@"Assets");
    Windows.Storage.StorageFile file = await folder.GetFileAsync("Click.wav");
    var stream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
    loop.AutoPlay = false;
    loop.SetSource(stream, file.ContentType);
    //or simpler -
    //loop.Source = new Uri("ms-appx:///Assets/Click.wav", UriKind.Absolute);
    loop.MediaOpened += Loop_MediaOpened;
    loop.IsLooping = true;
}

private static void Loop_MediaOpened(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    //play once the media is actually ready
    loop.Play();
}

在调用 LoadAndPlayAsync 方法之前,您必须将控件附加到某处(例如在 Grid 中):

GridContainer.Children.Add(SoundController.loop);
await SoundController.LoadAndPlayAsync();

我创建了一个sample project for my tests on my GitHub,你可以看看我是如何实现的。应用程序中的第一个按钮连接控件,第二个按钮加载并播放声音。可以看到如果只点第二个,是没有声音的