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