首页 文章

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

提问于
浏览
23

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

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

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

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

有任何想法吗?

10 回答

  • 8

    其中许多细节都是由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我相信)并且只是查询它们 . 请注意,我没有对索引是否可以改变进行大量研究(我对此表示怀疑),这就是我采用字典方法的原因 .

  • 10

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

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

  • 3

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

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

  • 0

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

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

  • 0

    我有一个小视频预览应用程序的相同问题 .

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

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

    要禁用,请转到Debug - > Exceptions - > Managed Debugging Assistants并取消选中LoaderLock .

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

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

  • 0

    似乎我发帖,我试过的,这么晚 . 希望它会帮助某人 .

    我试图通过唱歌Windows Media Player组件以不同的方式获取视频长度 .
    以下代码段可能会帮助您:

    using WMPLib;
    // ...your code here...
    
    var player = new WindowsMediaPlayer();
    var clip = player.newMedia(filePath);
    Console.WriteLine(TimeSpan.FromSeconds(clip.duration));
    

    并且不要忘记添加将出现在System32文件夹中的wmp.dll的引用 .

相关问题