如何从mp4、wmv、flv、mov视频中获取视频时长

28

好的,实际上我主要需要mp4格式。但如果能够获取其他类型的格式也可以。我只需要读取文件的时长信息。如何使用C# 4.0实现?

所以我需要的东西就像这个视频: 13 分钟 12 秒

我还可以使用三个第三方exe工具,它们可以将文件信息保存到文本文件中。我可以解析那个文本文件。

谢谢。

10个回答

18

这个答案关于P/Invoke访问Shell32让我想起了Windows API Code Pack,可以访问常见的Windows Vista/7/2008/2008R2 APIs。

使用示例中包含的PropertyEdit演示很容易弄清楚如何使用Shell32 API获取各种媒体文件属性,例如持续时间。

我认为同样需要安装适当的解复用器前提条件,但这很简单,只需要添加对Microsoft.WindowsAPICodePack.dllMicrosoft.WindowsAPICodePack.Shell.dll的引用以及以下代码:

using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Shell.PropertySystem;

using (ShellObject shell = ShellObject.FromParsingName(filePath))
{
    // alternatively: shell.Properties.GetProperty("System.Media.Duration");
    IShellProperty prop = shell.Properties.System.Media.Duration; 
    // Duration will be formatted as 00:44:08
    string duration = prop.FormatForDisplay(PropertyDescriptionFormatOptions.None);
}

其他内容

一些MPEG-4/AAC音频媒体文件的常见属性:

System.Audio.Format = {00001610-0000-0010-8000-00AA00389B71}
System.Media.Duration = 00:44:08
System.Audio.EncodingBitrate = ?56kbps
System.Audio.SampleRate = ?32 kHz
System.Audio.SampleSize = ?16 bit
System.Audio.ChannelCount = 2 (stereo)
System.Audio.StreamNumber = 1
System.DRM.IsProtected = No
System.KindText = Music
System.Kind = Music

如果你正在寻找可用的元数据,那么遍历所有属性非常容易:

using (ShellPropertyCollection properties = new ShellPropertyCollection(filePath))
{
    foreach (IShellProperty prop in properties)
    {
        string value = (prop.ValueAsObject == null) ? "" : prop.FormatForDisplay(PropertyDescriptionFormatOptions.None);
        Console.WriteLine("{0} = {1}", prop.CanonicalName, value);
    }
}

非常不错,但持续时间的分辨率是秒 - 我也需要小数。对于任何尝试此操作的人,请注意,您需要添加对Windows7APICodePack-Core / Shell的NuGet引用。 - Bill Hoag
我非常喜欢CodePack。请注意,该属性的原始值似乎是10^-7秒...我不知道是否为所有文件类型提供了这么多细节,但您可以查找它。原始值位于属性“.ValueAsObject”中,它是一个ulong,您需要从通用对象中转换出来。我会编辑答案尝试添加这个信息。 - Mike M

17

你也可以使用Windows Media Player,不过它并不支持你请求的所有文件类型。

using WMPLib;

public Double Duration(String file)
    {
        WindowsMediaPlayer wmp = new WindowsMediaPlayerClass();
        IWMPMedia mediainfo = wmp.newMedia(file);
        return mediainfo.duration;
    }
}

谢谢,但该应用程序将在Windows Server 2008上运行。我想他们没有Windows Media Player。 - Furkan Gözükara
@MonsterMMORPG 看起来你是对的 http://stackoverflow.com/a/13929540/188926 - Dunc

12
你可以使用DirectShow API中的MediaDet对象,通过DirectShow.NET包装库。查看获取视频长度的代码示例,get_StreamLength将以秒为单位返回持续时间。这假定Windows已安装MPEG-4分离器(在 Windows 7 之前需要第三方组件,我认为对于cezor的另一个答案也适用,虽然有免费的可重新分发的组件)。


这个 DirectShot API 在哪里?你能给我第三方的 URL 吗?或者你是指像 K Lite Mega Codec Pack 这样的东西吗? - Furkan Gözükara
谢谢,这行代码以秒为单位给出了正确的持续时间:mediaDet.get_StreamLength(out mediaLength); - Furkan Gözükara
好的,这个在Windows Server 2008 R2上失败了,但在我的本地计算机上工作正常。我需要安装什么样的Windows Server?K Lite Mega Codec Pack可以使用吗? - Furkan Gözükara
是的,我相信如此。或者,使用上面的GCDL链接。您需要从那里获取DLL并在目标系统中使用“regsvr32”进行注册-这应该足够了。 - Roman R.
是的,我想应该是一样的。我印象中它在Server 2008的早期版本中缺失,然后又回到了原位。http://groups.google.com/group/microsoft.public.win32.programmer.directx.video/browse_thread/thread/2f508e5944d2111e?q=qedit.dll+windows+server+2008&pli=1 - Roman R.
显示剩余2条评论

5

我认为你可以使用MediaInfo,它可以提供有关媒体文件的大量信息。
它还有一个CLI,因此您可以从代码中使用它并获取所需的信息。
您可以查看此链接


你好。我无法将mediainfodll添加为引用。你知道为什么吗?这是错误信息:http://img707.imageshack.us/img707/8130/hataow.png - Furkan Gözükara
@MonsterMMORPG:你必须使用参数调用应用程序并获取输出,不能在解决方案内部将其用作引用。 - Marco

5

我认为您正在寻找FFMPEG - https://ffmpeg.org/

还有一些免费的替代方案,您可以在这个问题中了解它们 - 在.NET中使用FFmpeg?

   FFMpeg.NET
   FFMpeg-Sharp
   FFLib.NET

您可以查看此链接以获取使用FFMPEG和查找持续时间的示例 - http://jasonjano.wordpress.com/2010/02/09/a-simple-c-wrapper-for-ffmpeg/

        public VideoFile GetVideoInfo(string inputPath)
        {
            VideoFile vf = null;
            try
            {
                vf = new VideoFile(inputPath);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            GetVideoInfo(vf);
            return vf;
        }
        public void GetVideoInfo(VideoFile input)
        {
            //set up the parameters for video info
            string Params = string.Format("-i {0}", input.Path);
            string output = RunProcess(Params);
            input.RawInfo = output;

            //get duration
            Regex re = new Regex("[D|d]uration:.((\\d|:|\\.)*)");
            Match m = re.Match(input.RawInfo);

            if (m.Success)
            {
                string duration = m.Groups[1].Value;
                string[] timepieces = duration.Split(new char[] { ':', '.' });
                if (timepieces.Length == 4)
                {
                    input.Duration = new TimeSpan(0, Convert.ToInt16(timepieces[0]), Convert.ToInt16(timepieces[1]), Convert.ToInt16(timepieces[2]), Convert.ToInt16(timepieces[3]));
                }
            }
       }

这是一款付费应用程序。他们只提供试用版。这对我来说行不通 :( - Furkan Gözükara
@MonsterMMORPG ffrmpeg是一款免费软件!请参见:https://ffmpeg.org/legal.html - F. Hauri - Give Up GitHub

3
使用Windows Media Player组件,我们也可以获取视频的时长。
以下代码片段可能会对大家有所帮助:
using WMPLib;
// ...
var player = new WindowsMediaPlayer();
var clip = player.newMedia(filePath);
Console.WriteLine(TimeSpan.FromSeconds(clip.duration));

不要忘记添加wmp.dll的引用,它将存在于System32文件夹中。

3
FFMPEG项目有一个工具,称为ffprobe,可以提供关于多媒体文件的所需信息,并以格式良好的JSON输出信息。
可以参考此答案了解示例。

2

我发现NReco.VideoInfo库是最好的选择,比上述库简单得多。只需给该库一个文件路径,它就会输出元数据:

var ffProbe = new FFProbe();
var videoInfo = ffProbe.GetMediaInfo(blob.Uri.AbsoluteUri);
return videoInfo.Duration.TotalMilliseconds;

1
请注意,此软件的商业使用需要购买许可证。 - user230910

1
我遇到了同样的问题,我们为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);

var duration = analyzeResult.VideoInfo.Format.Duration;

0
StreamReader errorreader;
string InterviewID = txtToolsInterviewID.Text;

Process ffmpeg = new Process();

ffmpeg.StartInfo.UseShellExecute = false;
ffmpeg.StartInfo.ErrorDialog = false;
ffmpeg.StartInfo.RedirectStandardError = true;

ffmpeg.StartInfo.FileName = Server.MapPath("ffmpeg.exe");
ffmpeg.StartInfo.Arguments = "-i " + Server.MapPath("videos") + "\\226.flv";


ffmpeg.Start();

errorreader = ffmpeg.StandardError;

ffmpeg.WaitForExit();

string result = errorreader.ReadToEnd();

string duration = result.Substring(result.IndexOf("Duration: ") + ("Duration: ").Length, ("00:00:00.00").Length);

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