C# 如何使用WPF中的MediaPlayer编写方法来打开、开始播放,然后返回音频文件的持续时间?

C# 如何使用WPF中的MediaPlayer编写方法来打开、开始播放,然后返回音频文件的持续时间?,c#,wpf,audio,C#,Wpf,Audio,很明显,我在下面尝试做什么,但我得到以下例外: 无法返回持续时间值为“自动”的TimeSpan属性值 读到那篇文章我很沮丧 在MediaOpen发生之前,无法确定自然耐久性。() 这是否意味着我必须想出一种人为的方法来打开文件,在单独的线程中等待媒体打开事件,然后仅在事件触发后返回持续时间 public static int PlayAudio(string fileName) { try { myMediaPlayer.S

很明显,我在下面尝试做什么,但我得到以下例外:

无法返回持续时间值为“自动”的TimeSpan属性值

读到那篇文章我很沮丧

在MediaOpen发生之前,无法确定自然耐久性。()

这是否意味着我必须想出一种人为的方法来打开文件,在单独的线程中等待媒体打开事件,然后仅在事件触发后返回持续时间

    public static int PlayAudio(string fileName)
    {
        try
        {
            myMediaPlayer.Stop();
            myMediaPlayer.Close();
            myMediaPlayer.Open(new Uri(filename));
            myMediaPlayer.Play();
            return myMediaPlayer.NaturalDuration.TimeSpan.Milliseconds;
        }
        catch (Exception e)
        {
            MessageBox.Show(e.Message);
            return -1;
        }
    }

使用本文提到的库之一,可以从MP3中的ID3标签和WMA中的类似标签中获取持续时间信息

在MediaPlayer控件中加载文件之前,您可能会获得此信息

我必须想出一种人为的方法来打开文件,在一个单独的线程中等待媒体打开事件,然后仅在事件触发后返回持续时间

不幸的是,这正是它的意思。下面是我刚刚想到的:

using System;
using System.Threading;
using System.Windows.Media;
using System.Windows.Threading;

class Program
{
    static void Main(string[] args)
    {
        var mediaFile = @"c:\path\to\mediafile.mp3";
        var duration = GetMediaDuration(mediaFile, TimeSpan.FromMilliseconds(500));
        Console.WriteLine(duration.ToString());
        Console.ReadKey();
    }

    static TimeSpan GetMediaDuration(string mediaFile)
    {
        return GetMediaDuration(mediaFile, TimeSpan.Zero);
    }

    static TimeSpan GetMediaDuration(string mediaFile, TimeSpan maxTimeToWait)
    {
        var mediaData = new MediaData() {MediaUri = new Uri(mediaFile)};

        var thread = new Thread(GetMediaDurationThreadStart);
        DateTime deadline = DateTime.Now.Add(maxTimeToWait);
        thread.Start(mediaData);

        while (!mediaData.Done && ((TimeSpan.Zero == maxTimeToWait) || (DateTime.Now < deadline)))
            Thread.Sleep(100);

        Dispatcher.FromThread(thread).InvokeShutdown();

        if (!mediaData.Done)
            throw new Exception(string.Format("GetMediaDuration timed out after {0}", maxTimeToWait));
        if (mediaData.Failure)
            throw new Exception(string.Format("MediaFailed {0}", mediaFile));

        return mediaData.Duration;
    }

    static void GetMediaDurationThreadStart(object context)
    {
        var mediaData = (MediaData) context;
        var mediaPlayer = new MediaPlayer();

        mediaPlayer.MediaOpened += 
            delegate 
                {
                    if (mediaPlayer.NaturalDuration.HasTimeSpan)
                        mediaData.Duration = mediaPlayer.NaturalDuration.TimeSpan; 
                    mediaData.Success = true; 
                    mediaPlayer.Close();
                };

        mediaPlayer.MediaFailed += 
            delegate
                {
                    mediaData.Failure = true;
                    mediaPlayer.Close();
                };

        mediaPlayer.Open(mediaData.MediaUri);

        Dispatcher.Run();
    }
}

class MediaData
{
    public Uri MediaUri;
    public TimeSpan Duration = TimeSpan.Zero;
    public bool Success;
    public bool Failure;
    public bool Done { get { return (Success || Failure); } }
}
使用系统;
使用系统线程;
使用System.Windows.Media;
使用System.Windows.Threading;
班级计划
{
静态void Main(字符串[]参数)
{
var mediaFile=@“c:\path\to\mediaFile.mp3”;
var duration=GetMediaDuration(mediaFile,TimeSpan.frommilluses(500));
Console.WriteLine(duration.ToString());
Console.ReadKey();
}
静态TimeSpan GetMediaDuration(字符串mediaFile)
{
返回GetMediaDuration(mediaFile,TimeSpan.Zero);
}
静态TimeSpan GetMediaDuration(字符串mediaFile,TimeSpan maxTimeToWait)
{
var mediaData=new mediaData(){MediaUri=new Uri(mediaFile)};
var thread=新线程(GetMediaDurationThreadStart);
DateTime deadline=DateTime.Now.Add(maxTimeToWait);
thread.Start(mediaData);
而(!mediaData.Done&((TimeSpan.Zero==maxTimeToWait)| |(DateTime.Now
是的,没有直接的方法可以打开媒体文件并获取媒体持续时间,原因是该文件是在后台打开的(以支持需要很长时间才能打开的文件,例如远程服务器上的文件),因此在调用“打开”后,该文件尚未打开

最好的选择是重新构造代码,以便在不返回持续时间的情况下打开文件,然后等待MediaOpen/MediaFailed事件


如果您确实需要打开文件并返回遇到问题的持续时间,请尽量避免使用Thread.Sleep,因为它会锁定您的UI,并记住用户可以在您等待文件打开时与GUI保持交互,在您等待时可能会打开另一个文件。

什么类型的“myMediaPlayer”?它是用代码创建的MediaPlayer。如果有一些优势,我可以使用MediaElement,但我不需要。不幸的是,我正在播放各种音频文件,包括wav文件。ID3标签不是我的解决方案。