Подтвердить что ты не робот

С# Получить продолжительность видеофайла из метаданных

Я пытаюсь читать метаданные из файла. Мне нужно только свойство Video → Length, однако я не могу найти простой способ прочитать эту информацию.

Я понял, что это будет довольно легко, поскольку по умолчанию это видно в Explorer, однако это выглядит намного сложнее, чем я ожидал. Ближе всего я пришел:

Microsoft.DirectX.AudioVideoPlayback.Video video = new Microsoft.DirectX.AudioVideoPlayback.Video(str);
double duration = video.Duration;

Однако это вызывает исключение LoaderLock, и я не знаю, как с этим бороться.

Любые идеи?

4b9b3361

Ответ 1

Многие из этих сведений предоставлены оболочкой, поэтому вы можете сделать это, добавив ссылку на библиотеку COM "Microsoft Shell Controls and Automation" (Shell32), а затем используя метод Folder.GetDetailsOf для запроса расширенной информации,

Я недавно искал это и наткнулся на на этот вопрос на форумах MSDN С# General. Я закончил писать это как метод расширения в FileInfo:

    public static Dictionary<string, string> GetDetails(this FileInfo fi)
    {
        Dictionary<string, string> ret = new Dictionary<string, string>();
        Shell shl = new ShellClass();
        Folder folder = shl.NameSpace(fi.DirectoryName);
        FolderItem item = folder.ParseName(fi.Name);

        for (int i = 0; i < 150; i++)
        {
            string dtlDesc = folder.GetDetailsOf(null, i);
            string dtlVal = folder.GetDetailsOf(item, i);

            if (dtlVal == null || dtlVal == "")
                continue;

            ret.Add(dtlDesc, dtlVal);
        }
        return ret;
    }

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

Ответ 2

Взгляните на этот вопрос SO - Solid FFmpeg wrapper для С#/. NET, который ссылается на несколько реализаций ffmpeg.Net. ffmpeg работает с большинством видеоформатов/кодеков. Таким образом, вам не нужно беспокоиться о том, что кодек установлен на компьютере.

Или посмотрите http://mediainfo.sourceforge.net/en.

Ответ 3

Я бы просто прокомментировал сообщение Микаэля, но у меня пока нет достаточного количества повторений. Я согласен с ним в использовании ffmpeg, чтобы вам не требовалось устанавливать кодеки. Вы можете просто проанализировать вывод "ffmpeg -i your_filename", который просто сбрасывает некоторую информацию о видео, включая продолжительность.

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

Ответ 4

Я рекомендую использовать MediaToolkit пакет nuget. Это не требует COM-взаимодействия вашего кода.

using MediaToolkit;

// a method to get Width, Height, and Duration in Ticks for video.
public static Tuple<int, int, long> GetVideoInfo(string fileName)
{
    var inputFile = new MediaToolkit.Model.MediaFile { Filename = fileName };
    using (var engine = new Engine())
    {
        engine.GetMetadata(inputFile);
    }

    // FrameSize is returned as '1280x768' string.
    var size = inputFile.Metadata.VideoData.FrameSize.Split(new[] { 'x' }).Select(o => int.Parse(o)).ToArray();

    return new Tuple<int, int, long>(size[0], size[1], inputFile.Metadata.Duration.Ticks);
}

Ответ 5

используя DirectShowLib (http://directshownet.sourceforge.net/)

   /// <summary>
    /// Gets the length of the video.
    /// </summary>
    /// <param name="fileName">Name of the file.</param>
    /// <param name="length">The length.</param>
    /// <returns></returns>
    static public bool GetVideoLength(string fileName, out double length)
    {
        DirectShowLib.FilterGraph graphFilter = new DirectShowLib.FilterGraph();
        DirectShowLib.IGraphBuilder graphBuilder;
        DirectShowLib.IMediaPosition mediaPos;
        length = 0.0;

        try
        {
            graphBuilder = (DirectShowLib.IGraphBuilder)graphFilter;
            graphBuilder.RenderFile(fileName, null);
            mediaPos = (DirectShowLib.IMediaPosition)graphBuilder;
            mediaPos.get_Duration(out length);
            return true;
        }
        catch
        {
            return false;
        }
        finally
        {
            mediaPos = null;
            graphBuilder = null;
            graphFilter = null;
        }
    }

Ответ 6

Получение продолжительности видео файла в Win Rt App или Metro С#:

StorageFile videoFile;
videoFile = await StorageFile.GetFileFromPathAsync(VIDEO_PATH_HERE);
Windows.Storage.FileProperties.VideoProperties x = await videoFile.Properties.GetVideoPropertiesAsync();
var videoDuration = x.Duration;

Ответ 7

MediaInfo - отличная библиотека с открытым исходным кодом для этой цели (DLL лицензируется LGPL). Пакет загрузки содержит пример приложения в С# (под Developers\Project\MSCS\Example)

Ответ 8

У меня была такая же проблема с небольшим приложением для предварительного просмотра видео.

Проблема - Assassent Assassent. Это проблема при использовании библиотек Managed DirectX 1.1 в VS2005 или 2008. Microsoft перешла на работу с MDX2, а затем XNA, а не с Managed DirectX 1, поэтому не надейтесь слишком много на патч.

Легкое обходное решение - отключить обработку LoaderLock Exception при отладке этого решения. Это не должно иметь никакого реального влияния на программу, так как эта ошибка появляется только в среде отладки.

Чтобы отключить функцию "Отладка" → "Исключения" → "Помощники для отладки" и снимите флажок "LoaderLock".

Дополнительная информация здесь: http://vivekthangaswamy.blogspot.com/2006/11/loaderlock-was-detected-error-when.html

Ответ 9

использовать MCI

его прост в использовании и работает даже на NT:

  using System.Runtime.InteropServices;

  [DllImport("winmm.dll")]
  public static extern int mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback);
  [DllImport("winmm.dll")]
  private static extern int mciGetErrorString(int l1, StringBuilder s1, int l2);

  string cmd = "open " + strFile + " alias video";
  StringBuilder mssg = new StringBuilder(255);

  int h = mciSendString(cmd, null, 0, 0); // open video at mci
  int i = mciSendString("set video time format ms", null, 0, 0); // set time format, you can see other formats at link above
  int j = mciSendString("status video length", mssg, mssg.Capacity, 0); //get video length into mssg 
  Console.WriteLine(mssg.ToString());
  int m = mciSendString("close video", null, 0, 0); //close video

Ответ 10

Кажется, что я публикую, что я пробовал, так поздно. Надеюсь, это поможет кому-то.

Я попытался немного увеличить длину видео, поделив компонент Windows Media Player.
Следующий фрагмент кода может помочь вам:

using WMPLib;
// ...your code here...

var player = new WindowsMediaPlayer();
var clip = player.newMedia(filePath);
Console.WriteLine(TimeSpan.FromSeconds(clip.duration));

и не забудьте добавить ссылку wmp.dll, которая будет присутствует в папке System32.

Ответ 11

Вы можете использовать нашу оболочку для ffprobe Alturos.VideoInfo. Вы можете использовать его, просто установив пакет nuget. Также требуется двоичный файл ffprobe.

PM> install-package Alturos.VideoInfo

пример

var videoFilePath = "myVideo.mp4";

var videoAnalyer = new VideoAnalyzer("ffprobe.exe");
var analyzeResult = videoAnalyer.GetVideoInfo(videoFilePath);

//Video length
var duration = analyzeResult.VideoInfo.Format.Duration;