C#从元数据中获取视频文件持续时间

时间:2009-08-10 19:46:54

标签: c# metadata

我正在尝试从文件中读取元数据。我只需要视频 - >长度属性,但是我无法找到一种简单的方法来读取这些信息。

我认为这很容易,因为它在资源管理器中默认是可见的,但这看起来比我预期的要复杂得多。我最接近的是使用:

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

但是这会抛出一个LoaderLock异常,我不知道如何处理它。

有什么想法吗?

11 个答案:

答案 0 :(得分:10)

shell提供了许多这些细节,因此您可以通过添加对COM库“Microsoft Shell控件和自动化”(Shell32)的引用,然后使用Folder.GetDetailsOf方法查询扩展的详细信息来完成此操作。 。

我最近在寻找这个并在MSDN C#General论坛上遇到this very question。我最后将其写为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)并且只是查询它们。请注意,我没有对索引是否可以更改进行大量研究(我对此表示怀疑),这就是我采用字典方法的原因。

答案 1 :(得分:8)

看看这个SO问题 - Solid FFmpeg wrapper for C#/.NET链接到几个ffmpeg .Net实现。 ffmpeg适用于大多数视频格式/编解码器。这样您就不必担心计算机上安装的编解码器了。

或者查看http://mediainfo.sourceforge.net/en

答案 2 :(得分:3)

我会对Mikael的帖子发表评论,但我还没有足够的代表去做。我同意他使用ffmpeg,因此您不必要求安装编解码器。您可以解析“ffmpeg -i your_filename”的输出,它只会转储有关视频的一些信息,包括持续时间。

我不知道你正在使用哪些编解码器,但是一些容器实际上并没有在元数据中存储持续时间(由于持续时间未知,这是流容器的常见问题)。我不知道ffmpeg如何处理这个,但它似乎以某种方式找到它(可能通过解析整个文件的时间码)。

答案 3 :(得分:2)

我建议使用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);
}

答案 4 :(得分:1)

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

答案 5 :(得分:0)

MediaInfo是一个很好的开源库,用于此目的(DLL是LGPL许可)。下载包中包含C#中的示例应用程序(在Developers\Project\MSCS\Example下)

答案 6 :(得分:0)

我在小视频预览应用中遇到了同样的问题。

问题是托管调试助手。在VS2005或2008中使用Managed DirectX 1.1库时,这是一个问题.Microsoft已经开始专注于MDX2,然后是XNA而不是Managed DirectX 1,所以不要对补丁有太多希望。

简单的解决方法是在调试该解决方案时禁用LoaderLock异常处理。这应该对程序没有实际影响,因为此错误仅出现在调试环境中。

要禁用转到调试 - &gt;例外 - &gt;托管调试助手并取消选中LoaderLock。

此处有更多信息:http://vivekthangaswamy.blogspot.com/2006/11/loaderlock-was-detected-error-when.html

答案 7 :(得分:0)

使用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

答案 8 :(得分:0)

在Win Rt App或Metro C#中获取视频文件的持续时间

StorageFile videoFile;  string path = ApplicationData.Current.LocalFolder.Path;  videoFile = await StorageFile.GetFileFromPathAsync(presentationItem.Slide_path_local); Windows.Storage.FileProperties.VideoProperties x = await videoFile.Properties.GetVideoPropertiesAsync(); 持续时间videoDuration = x.Duration;

答案 9 :(得分:0)

似乎我发帖,我试过,这么晚。希望它会帮助别人。

我试图通过唱歌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 文件夹中。

答案 10 :(得分:0)

您可以将我们的包装用于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;