C# 从元数据中获取视频文件时长

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1256841/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:18:48  来源:igfitidea点击:

C# Get video file duration from metadata

c#metadata

提问by David Bo?jak

I am trying to read metadata from a file. I only need the Video -> Length property, however I am unable to find a simple way of reading this information.

我正在尝试从文件中读取元数据。我只需要 Video -> Length 属性,但是我找不到读取此信息的简单方法。

I figured this would be fairly easy since it is visible by default in Explorer, however this looks to be way more complicated than I anticipated. The closest I came was using:

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

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

However this throws a LoaderLock exception, and I don't know how to deal with it.

但是这会引发 LoaderLock 异常,我不知道如何处理。

Any ideas?

有任何想法吗?

回答by Mikael Svenson

Take a look at this SO question - Solid FFmpeg wrapper for C#/.NETwhich links to several ffmpeg .Net implementations. ffmpeg works with most video formats/codecs. That way you don't need to worry about the codec being installed on the machine.

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

Or look at https://mediaarea.net/en/MediaInfo.

或查看https://mediaarea.net/en/MediaInfo

回答by Jason B

I would have just commented on Mikael's post, but I don't quite have enough rep to do it yet. I agree with him on using ffmpeg so that you don't have to require that codecs be installed. You could just parse the output of "ffmpeg -i your_filename" which will just dump some info about the video including the duration.

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

I don't know what codecs you're working with, but some containers do not actually store the duration in the metadata (this is common of streaming containers since duration is unknown). I don't know how ffmpeg handles this, but it seems to find it somehow (maybe by parsing the whole file for timecodes).

我不知道您正在使用什么编解码器,但有些容器实际上并未将持续时间存储在元数据中(这在流容器中很常见,因为持续时间未知)。我不知道 ffmpeg 如何处理这个,但它似乎以某种方式找到它(也许通过解析整个文件的时间码)。

回答by Igal Tabachnik

MediaInfois a great open source library for that purpose (the DLL is licensed LGPL). The download package contains sample application in C# (under Developers\Project\MSCS\Example)

MediaInfo是用于此目的的出色开源库(DLL 已获得 LGPL 许可)。下载包中包含 C# 示例应用程序(在 下Developers\Project\MSCS\Example

回答by chsh

Many of these details are provided by the shell, so you can do this by adding a reference to the COM Library "Microsoft Shell Controls and Automation" (Shell32), and then using the Folder.GetDetailsOf method to query the extended details.

其中许多详细信息是由外壳提供的,因此您可以通过添加对 COM 库“Microsoft Shell 控件和自动化”(Shell32) 的引用,然后使用 Folder.GetDetailsOf 方法查询扩展的详细信息来实现。

I was recently looking for this and came across this very questionon the MSDN C# General forums. I wound up writing this as an extension method to FileInfo:

我最近正在寻找这个,并在 MSDN C# 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;
    }

If you're looking for specific entries, you can do something similar, though it will be far faster to find out what index those entries are at (Length is index 27 I believe) and just query those. Note, I didn't do much research into whether or not the index can change (I doubt it), which is why I took the dictionary approach.

如果您正在寻找特定的条目,您可以执行类似的操作,尽管找出这些条目所在的索引会快得多(我相信 Length 是索引 27)并查询这些条目。请注意,我没有对索引是否可以更改进行太多研究(我对此表示怀疑),这就是我采用字典方法的原因。

回答by Brian Duncan

I had the same issue with a small video preview app.

我在一个小型视频预览应用程序中遇到了同样的问题。

The issue is Managed Debugging Assisstants. This is an issue when using The Managed DirectX 1.1 libraries in VS2005 or 2008. Microsoft has moved on to focus on MDX2 and then XNA rather than Managed DirectX 1 so don't hope too much for a patch.

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

The easy workaround is to disable the LoaderLock Exception handling while debugging that solution. This should have no real effect on the program anyways since this error only shows up in a debug environment.

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

To disable go to Debug -> Exceptions -> Managed Debugging Assistants and uncheck LoaderLock.

要禁用,请转到调试 -> 异常 -> 托管调试助手并取消选中 LoaderLock。

More info here:http://vivekthangaswamy.blogspot.com/2006/11/loaderlock-was-detected-error-when.html

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

回答by mneves

using DirectShowLib (http://directshownet.sourceforge.net/)

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

回答by Nooneelse

use MCI

使用MCI

its easy to use and works even on NT:

它易于使用,甚至可以在 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

回答by user3714810

Getting duration of video file in Win Rt App or Metro C#:

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

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

回答by Youngjae

I recommend to use MediaToolkitnuget package. It does not require COM interop on your code.

我建议使用MediaToolkitnuget 包。它不需要对您的代码进行 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);
}

回答by Rish

It seems that I am posting, what I have tried, so late. Hope it will help someone.

看来我发帖了,我试过的,这么晚了。希望它会帮助某人。

I have tried to get the video length in a bit different way by sing Windows Media Player Component.
Following code snippet may help you guys :

我试图通过播放 Windows Media Player 组件以不同的方式获得视频长度。
以下代码片段可能对你们有所帮助:

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

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

and don't forget to add the reference of wmp.dllwhich will be present in System32folder.

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