【问题标题】:Windows phone 8 on emulator - why can't I play audio files?模拟器上的 Windows phone 8 - 为什么我不能播放音频文件?
【发布时间】:2013-01-19 19:58:04
【问题描述】:

我正在转换一个用 Silverlight 编写的应用程序,到目前为止,我已经成功解决了所有问题,除了一个问题:

由于某种原因,模拟器拒绝播放应用程序的任何音频文件,甚至没有抛出异常。我查过,在铃声类别中它可以发出声音。

原来的代码是:

<Grid x:Name="sharedFullScreenFilePathContainer"
Tag="{Binding StringFormat=\{0\},Converter={StaticResource fullScreenImageConverter}}">

    <Image x:Name="fullScreenImage" Stretch="Fill"
Source="{Binding ElementName=sharedFullScreenFilePathContainer,Path=Tag, StringFormat=../Assets/images/\{0\}.jpg}"
ImageFailed="onFullScreenImageFailedToLoad" MouseLeftButtonDown="onPressedOnFullScreenImage" />

    <MediaElement x:Name="mediaPlayer" AutoPlay="True"
Source="{Binding ElementName=sharedFullScreenFilePathContainer,Path=Tag, StringFormat=../Assets/sounds/\{0\}.wma}" />
</Grid>

所以,我设置到这个项目的上下文的图像确实显示了,但是我设置的路径上真正存在的声音没有播放(我已经检查了“Bin”文件夹)。

我尝试使用代码而不是 xaml,但我仍然遇到同样的问题。

我试过这个(虽然它通常用于背景音乐):

AudioTrack audioTrack = new AudioTrack(new Uri("../Assets/sounds/" + fileToOpen, UriKind.Relative), "", "", "", null);
BackgroundAudioPlayer player = BackgroundAudioPlayer.Instance;
player.Track = audioTrack;
player.Play();

它没有播放任何东西,也没有抛出任何异常。

我也试过下一个代码,但是它抛出了一个异常(文件未找到异常)可能是因为我没有正确调用它:

Stream stream = TitleContainer.OpenStream("@Assets/sounds/" + fileToOpen);
SoundEffect effect = SoundEffect.FromStream(stream);
FrameworkDispatcher.Update();
effect.Play();

我也尝试过使用 wma 文件,但也没有用。

我还尝试使用 mp3 文件的“复制到输出目录”参数(“始终”和“仅当新”)和“构建操作”参数(“无”和“内容” )。没有任何帮助。

谁能帮帮我?我很长时间没有为 Silverlight/WP 开发,我不知道如何修复它。

顺便说一句,因为稍后我需要知道声音何时播放完毕(并且还能够停止它),我还是想使用代码。如果你也能告诉我怎么做,我会很高兴(如果需要,我可以在新帖子上问)。


编辑: 好的,我发现了问题:在使用 MediaPlayer.Play() 方法时,我一直收到一个奇怪的异常,在检查了异常之后,我发现这是一个已知的问题,我需要在调用 Play() 方法之前调用 FrameworkDispatcher.Update();

所以解决方案是这样做:

Song song = Song.FromUri(...);
MediaPlayer.Stop(); 
FrameworkDispatcher.Update();
MediaPlayer.Play(song);

例外是:

'System.InvalidOperationException'发生在 System.Windows.ni.dll"

我找到了解决方案here

现在的问题是为什么,为什么我在 windows phone 的演示中没有找到任何相关的东西?另外,我想知道这个函数是做什么的。


好的,既然没人给我两个问题的答案,我仍然希望给予赏金,我会问另一个问题:

如果除了使用 windows phone 的 MediaPlayer 类之外真的没有其他解决方案,我如何捕获完成播放音频文件的事件?即使获取音频文件的持续时间也不起作用(无论我尝试使用哪个类,都会返回 0 length )...

【问题讨论】:

  • 你看到了吗,那是因为你用XNA播放音频! msdn.microsoft.com/library/ff842408.aspx
  • 请见谅。我写过我是 WP 的新手。我可以选择如何播放音频文件吗?我只想玩它(如果需要,可以停止前一个)。如果应用程序使用 XNA 是否重要?它不是 API 的一部分吗?我真的对此知之甚少,我无法理解为什么要采取如此多的步骤来做一些如此基本和简单的事情。
  • 没问题,我只是认为你在将媒体资源的正确引用从应用程序写入 MediaElement 时有些问题,在 Windows Phone 上播放音频文件没什么大不了的:- )
  • 不,我已将其设置为“内容”类型并将其设置为“如果较新则复制”。那不是问题。这个问题是一个非常奇怪的异常,我仍然不明白它的含义,以及为什么我找到的东西可以解决它。
  • 这里描述了如何以及为什么正确使用 FrameworkDispatcher:kunal-chowdhury.com/2012/07/… 我知道,这有点痛苦,但是对于 WP8 中的某些功能,您只需要深入挖掘。并非所有内容都包含在基本示例中。

标签: mp3 media-player windows-phone-8 filenotfoundexception


【解决方案1】:

BackgroundAudioPlayer 可以播放来自隔离存储或远程 URI 的文件,这就是为什么您可以在此处播放任何文件的原因!

如果您将文件作为应用中的资源,您必须先将它们复制到独立存储中,然后将独立存储中的文件引用到您的 BackgroundAudioPlayer。

    private void CopyToIsolatedStorage()
    {
        using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
        {
            string[] files = new string[] 
                { "Kalimba.mp3", 
                    "Maid with the Flaxen Hair.mp3", 
                    "Sleep Away.mp3" };

            foreach (var _fileName in files)
            {
                if (!storage.FileExists(_fileName))
                {
                    string _filePath = "Audio/" + _fileName;
                    StreamResourceInfo resource = Application.GetResourceStream(new Uri(_filePath, UriKind.Relative));

                    using (IsolatedStorageFileStream file = storage.CreateFile(_fileName))
                    {
                        int chunkSize = 4096;
                        byte[] bytes = new byte[chunkSize];
                        int byteCount;

                        while ((byteCount = resource.Stream.Read(bytes, 0, chunkSize)) > 0)
                        {
                            file.Write(bytes, 0, byteCount);
                        }
                    }
                }
            }
        }
    }

然后你就可以列出你的歌曲了​​

    private static List<AudioTrack> _playList = new List<AudioTrack>
    {
        new AudioTrack(new Uri("Kalimba.mp3", UriKind.Relative), 
                        "Kalimba", 
                        "Mr. Scruff", 
                        "Ninja Tuna", 
                        null),

        new AudioTrack(new Uri("Maid with the Flaxen Hair.mp3", UriKind.Relative), 
                        "Maid with the Flaxen Hair", 
                        "Richard Stoltzman", 
                        "Fine Music, Vol. 1", 
                        null),

        new AudioTrack(new Uri("Sleep Away.mp3", UriKind.Relative), 
                        "Sleep Away", 
                        "Bob Acri", 
                        "Bob Acri", 
                        null),

        // A remote URI
        new AudioTrack(new Uri("http://traffic.libsyn.com/wpradio/WPRadio_29.mp3", UriKind.Absolute), 
                        "Episode 29", 
                        "Windows Phone Radio", 
                        "Windows Phone Radio Podcast", 
                        null)
    };

然后播放你的曲目!

    private void PlayNextTrack(BackgroundAudioPlayer player)
    {
        if (++currentTrackNumber >= _playList.Count)
        {
            currentTrackNumber = 0;
        }

        PlayTrack(player);
    }

    private void PlayPreviousTrack(BackgroundAudioPlayer player)
    {
        if (--currentTrackNumber < 0)
        {
            currentTrackNumber = _playList.Count - 1;
        }

        PlayTrack(player);
    }

    private void PlayTrack(BackgroundAudioPlayer player)
    {
        // Sets the track to play. When the TrackReady state is received, 
        // playback begins from the OnPlayStateChanged handler.
        player.Track = _playList[currentTrackNumber];
    }

【讨论】:

  • 但是这样不会占用2倍的空间吗?这不是浪费时间和空间吗?
  • 是的,但如果您想将 BackgroundAudioPlayer 用于您的应用程序中的文件,这是唯一的方法。
  • 没有其他播放声音的方法吗?一个不需要这么浪费的动作?我写的 BackgroundAudioPlayer 只是作为我尝试过的东西,而不是我认为应该使用的东西。当然,我也想知道为什么这个类不支持在应用程序上播放文件,但也许我只是不太了解它的用途,因为我是 Windows Phone 的新手。
  • BackgroundAudioPlayer 播放来自隔离存储或 uri 的音频,因为它可以在您关闭应用程序时继续播放文件。 BackgroundAudioPlayer 无法访问应用程序资源,因此您必须将媒体文件放在应用程序和 BackgroundAudioPlayer 共享的位置。
  • 您可以改用 MediaElement,它可以直接从您的应用程序播放 mp3 文件。 this.MyMedia.Source = new Uri("Assets/AwesomeMusic.mp3", UriKind.RelativeOrAbsolute); this.MyMedia.Play();我在下面发布另一个答案!
【解决方案2】:

如果您希望 MediaElement 从您的代码中工作,您可以执行以下操作!

        MediaElement me = new MediaElement();
        // Must add the MediaElement to some UI container on 
        // your page or some UI-control, otherwise it will not play!
        this.LayoutRoot.Children.Add(me);
        me.Source = new Uri("Assets/AwesomeMusic.mp3", UriKind.RelativeOrAbsolute);
        me.Play();

【讨论】:

  • hmmm ...现在我也尝试为其放置一个超短的xaml标签,它就像我一开始尝试的那样工作。也许路径是错误的。请将此答案与上一个答案合并,并尝试回答以下问题:声音播放完毕后如何收到通知?通过使用 CurrentStateChanged ,我得到了被暂停多次而不是一次的事件。另外,为什么它甚至需要在 UI 中?
  • 我将合并答案。我认为这是因为 MediaElement 是一个 UI 组件,需要 UI 线程才能工作!
  • 那么问题是怎么来的。我的意思是,根本不可视的东西怎么可能必须在 ui 中,而不是至少是可选的。我还问我为什么会多次获得 MediaElementState.Paused 即使我播放一个音频文件。
  • 按照设计,因为 MediaElement 确实源自标准 XAML 控件!不知道为什么 Pause 事件被抽了多次,一定是 bug!
  • 谢谢我昨天合并了答案,还有更多!
【解决方案3】:

改为使用 MediaElement,这可以播放存储在您的应用程序中的媒体文件,但在应用程序停止时停止播放(您可以为您的应用程序提供一些提前机会,使其继续运行,但它不会很好地运行)

在您的 XAML 中:

        <Button x:Name="PlayFile"
                Click="PlayFile_Click_1"
                Content="Play mp3" />

在你的代码后面:

    MediaElement MyMedia = new MediaElement();
    // Constructor
    public MainPage()
    {
        InitializeComponent();

        this.LayoutRoot.Children.Add(MyMedia);

        MyMedia.CurrentStateChanged += MyMedia_CurrentStateChanged;
        MyMedia.MediaEnded += MyMedia_MediaEnded;
    }

    void MyMedia_MediaEnded(object sender, RoutedEventArgs e)
    {
        System.Diagnostics.Debug.WriteLine("Ended event " + MyMedia.CurrentState.ToString());
        // Set the source to null, force a Close event in current state
        MyMedia.Source = null;
    }

    void MyMedia_CurrentStateChanged(object sender, RoutedEventArgs e)
    {

        switch (MyMedia.CurrentState)
        {
            case System.Windows.Media.MediaElementState.AcquiringLicense:
                break;
            case System.Windows.Media.MediaElementState.Buffering:
                break;
            case System.Windows.Media.MediaElementState.Closed:
                break;
            case System.Windows.Media.MediaElementState.Individualizing:
                break;
            case System.Windows.Media.MediaElementState.Opening:
                break;
            case System.Windows.Media.MediaElementState.Paused:
                break;
            case System.Windows.Media.MediaElementState.Playing:
                break;
            case System.Windows.Media.MediaElementState.Stopped:
                break;
            default:
                break;
        }

        System.Diagnostics.Debug.WriteLine("CurrentState event " + MyMedia.CurrentState.ToString());
    }

    private void PlayFile_Click_1(object sender, RoutedEventArgs e)
    {
        // Play Awesome music file, stored as content in the Assets folder in your app
        MyMedia.Source = new Uri("Assets/AwesomeMusic.mp3", UriKind.RelativeOrAbsolute);
        MyMedia.Play();
    }

【讨论】:

  • 没用。它没有崩溃,但也没有播放任何东西。事实上,这与我在开始使用 silverlight 项目时使用的解决方案大致相同。无论如何,我已经使用 MediaPlayer 成功播放了音频,但在播放之前,我调用了 FrameworkDispatcher.Update() 。我已经更新了我的问题,如果当前的任何答案都不能回答当前的问题(因为我已经设置了赏金,并且我确实希望给予它以防答案是值得的),我会添加我自己的。跨度>
  • 我不明白为什么不能从 MediaElement 播放文件。您如何将媒体文件添加到项目中? MediaFile 必须添加到项目中。从我的项目中播放大型 mp3 文件完全没有问题!
  • 在模拟器上?我不明白为什么它对我不起作用。这次我使用纯代码而不是 xml。你能做同样的事情并告诉我它是否也适合你吗?
  • 是的,我在 Windows 8 + VS2012 + Phone 8 项目的模拟器中做了。这是相同的设置吗(还有一个带有电话 7.5 的版本)?我的答案(MediaElement)中的代码行是我用过的,记得把你的媒体文件标记为内容!!
  • 所以我不知道。我有 windows 8 pro 和 VS2012,它也是一个 windows phone 8 项目。我没有对 VS 的安装做任何特别的事情。你试过用纯代码代替 xaml 吗?
【解决方案4】:

音轨播放存储在隔离存储中或通过互联网流式传输的音频文件。

【讨论】:

  • 好的,那么我如何播放 mp3 文件,为什么它在 silverlight 和 wpf 上都能正常工作,但在这里却不行?
【解决方案5】:

播放存储在应用程序包中的音频文件对我来说很好。我在项目文件夹 Resources\Alarms 中有名为“Alarm01.wma”的文件。然后我会像这样播放这些声音:

using Microsoft.Xna.Framework.Media;
...
Song s = Song.FromUri("alarm", new Uri(@"Resources/Alarms/Alarm01.wma", UriKind.Relative));
MediaPlayer.Play(s);

别忘了引用 Microsoft.Xna.Framework 库。

我想它应该也适用于 mp3 文件和存储在 IsolatedStorage 中的文件。

【讨论】:

  • 第一个参数是什么?我不能告诉它播放文件吗?另外,我为什么需要添加参考,而不是 VS 来提供我,因为它内置在它支持的库中?显然,没有人能记住安装的库提供的所有类和函数,对吧?在 Eclipse 上,每次您使用未导入的类时,它都会为您提供建议。是否至少有一个默认安装的基本库及其类的列表?
  • 现在我已尝试添加参考,但找不到。怎么会这样 ?我真的需要安装一个特殊的组件才能让 Windows Phone 应用支持播放音频吗?
  • 在您的 Visual Studio 项目中,只需单击参考 -> 添加参考 -> Microsoft.Xna.Framework。 Visual Studio 为您提供了使用的自动包含,但仅适用于当前引用的库中的类型。
  • 是的,我知道,但我找不到“Microsoft.Xna.Framework”库。事实上,那里只有非常几个项目(无论我选择哪个类别)。关于我所写的烦恼,您实际上证实了它的存在——开发人员需要确切地知道为他需要使用的每个类使用哪个引用,这与自动提供它的 eclipse 相反。我认为这是VS缺乏的一个非常基本的功能。
  • 自己找到了问题的解决方案。更新了问题。请检查一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-12
  • 1970-01-01
  • 2011-04-30
  • 2018-03-12
  • 1970-01-01
相关资源
最近更新 更多