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

26

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

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

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

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

有什么想法吗?


它是在Visual Studio 2008中,使用DirectX 10。 - David Božjak
请尝试以下链接,希望对您有用:确定视频大小和持续时间 - IordanTanev
如果您需要有关材料交换、基本媒体文件、高级系统格式/Windows Media、资源交换和Matroska容器的文件和轨道级别详细信息,可以访问https://net7mma.codeplex.com。该库完全使用C#编写,没有任何依赖项,并且还包含Rtsp和Rtp堆栈,如果您需要将视频托管并回放给客户端。编写支持和纯管理解码和编码正在开发中。 - Jay
11个回答

11
许多这些细节是由Shell提供的,因此您可以通过添加对COM库“Microsoft Shell Controls and Automation”(Shell32)的引用,然后使用Folder.GetDetailsOf方法查询扩展详细信息来实现。我最近正在寻找这个并在MSDN C#一般论坛上找到了这个问题。最终,我将其编写为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)并直接查询它们会更快。请注意,我没有深入研究索引是否会改变(我怀疑不会),这就是为什么我采用了字典方法的原因。

8

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

3

我本想在Mikael的帖子上评论,但我还没有足够的声望来这样做。我同意他使用ffmpeg的观点,这样就不必要求安装编解码器。您可以解析“ffmpeg -i your_filename”的输出,其中将仅转储有关视频的一些信息,包括持续时间。

我不知道您正在使用哪些编解码器,但某些容器实际上不会在元数据中存储持续时间(这对于流式传输容器很常见,因为持续时间是未知的)。我不知道ffmpeg如何处理此问题,但它似乎以某种方式找到了它(也许通过解析整个文件的时间代码)。


2
你可以使用我们为ffprobe编写的封装库Alturos.VideoInfo。只需安装nuget软件包即可使用。还需要安装ffprobe二进制文件。最初的回答:使用我们的Alturos.VideoInfo ffprobe封装库,只需安装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;

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

1

如何在Win Rt应用程序或Metro C#中获取视频文件的时长:

StorageFile videoFile;
videoFile = await StorageFile.GetFileFromPathAsync(VIDEO_PATH_HERE);
Windows.Storage.FileProperties.VideoProperties x = await videoFile.Properties.GetVideoPropertiesAsync();
var 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));

不要忘记添加引用 wmp.dll,该文件位于 System32 文件夹中。

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

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


如果您需要有关材料交换、基本媒体文件、高级系统格式/Windows Media、资源交换和Matroska容器的文件和轨道级别详细信息,可以访问https://net7mma.codeplex.com。该库完全使用C#编写,没有任何依赖项,并且还包含Rtsp和Rtp堆栈,如果您需要将视频托管并回放给客户端。编写支持和纯管理解码和编码正在开发中。 - Jay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接