Как мне написать метод, чтобы открыть, начать воспроизведение, а затем вернуть длительность аудиофайла с помощью MediaPlayer в WPF? - PullRequest
2 голосов
/ 08 января 2009

Очевидно, что я пытаюсь сделать ниже, но я получаю следующее исключение:

Невозможно вернуть значение свойства TimeSpan для значения Duration «Автоматически».

Я был обескуражен, чтобы прочитать это

NaturalDuration не может быть определено, пока не произойдет MediaOpened. (* 1 010 * ссылка )

Значит ли это, что мне нужно придумать надуманный метод, чтобы открыть файл, дождаться события открытия носителя в отдельном потоке, а затем вернуть продолжительность только после его запуска?

    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;
        }
    }

Ответы [ 3 ]

5 голосов
/ 30 мая 2009

Мне нужно придумать надуманный метод, чтобы открыть файл, дождаться события открытия носителя в отдельном потоке, а затем вернуть продолжительность только после того, как событие сработало

Это именно то, что это означает, к сожалению. Вот что я только что придумал для этого:

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); } }
}
3 голосов
/ 31 мая 2009

Да, простого способа открыть файл мультимедиа и получить его продолжительность не существует, причина в том, что файл открывается в фоновом режиме (для поддержки файлов, которые открываются долго, например, файлы на удаленных серверах). ), поэтому сразу после вызова Open файл еще не был открыт.

Лучшим вариантом является реструктуризация кода, чтобы вы открывали файл, не возвращая длительность, а затем ожидали события MediaOpened / MediaFailed.

Если вам абсолютно необходимо открыть файл и вернуть время, в течение которого вы столкнулись с какими-либо проблемами, просто попытайтесь избежать Thread.Sleep, поскольку он заблокирует ваш пользовательский интерфейс и помнит, что пользователь может продолжать взаимодействовать с графическим интерфейсом, пока вы ждете файл, который можно открыть, потенциально открывая другой файл во время ожидания.

0 голосов
/ 08 января 2009

Можно получить информацию о продолжительности из тегов ID3 ​​в MP3 и подобных тегов в WMA, используя одну из библиотек, упомянутых в этом вопросе .

Вы могли бы получить эту информацию до загрузки файла в элемент управления MediaPlayer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...