编程实战——电影管理器之利用MediaInfo获取高清视频文件的相关信息

简介: 随着高速(20M)宽带、HTPC、大容量硬盘(3T)的普及,下载高清片并利用大屏幕观看也成为普通的事情。 随着下载影片的增多,管理就有了问题,有时在茫茫文件夹下找寻一个影片也是一件费时费力的事。 于是萌生了自己编写电影管理器的想法,并逐步逐步在实现。

随着高速(20M)宽带、HTPC、大容量硬盘(3T)的普及,下载高清片并利用大屏幕观看也成为普通的事情。

随着下载影片的增多,管理就有了问题,有时在茫茫文件夹下找寻一个影片也是一件费时费力的事。

于是萌生了自己编写电影管理器的想法,并逐步逐步在实现。利用博客记录编写的过程,也是和网友之间的交流。期望在交流的过程中,网友能提出一些中肯的意见,使自己少走些弯路。

 

我在拿到一个高清视频文件时。我希望能有办法获知以下的信息

文件名:视频文件的文件名,这个比较简单,利用FileInfo类就能获得

文件大小:视频文件的大小,这个也比较简单,利用FileInfo类能获得

视频分辨率:视频文件的分辨率,例如:宽1980像素,高1040像素。

视频时长:视频文件的时长,例如:长1小时32分

音频数:视频文件中的音频数,有不少的高清视频文件中包含不止一个音频。有的包含英文、中文2个音频;有的包含英文、中文、粤语3个音频

音频的语言类型:具体到每个音频的语言。例如:音频1是英文,音频2是中文等

 

以上信息中的后面四个(视频分辨率、视频时长、音频数、音频的语言类型),用视频播放器都能获得。但是如何在自己的程序中获得这些信息呢?

 

我们可以利用MediaInfo来获取这些信息(视频分辨率、视频时长、音频数、音频的语言类型)

 

先看看MediaInfo的介绍,MediaInfo官网。在官网上有相关的介绍,并给出了调用的代码(很完备。C++,C#,Visual Basic等都有)

 

高清视频文件的相关信息都保存在文件的头部区域,记录的信息有很多(除却上面的四种外,还包括码率、编码类型等等)。而MediaInfo就是利用读取头部区域的信息来获得相关的信息。官网的更新很快,笔者下载的是2013年7月6日发布的最新版。

 

下面就介绍如何利用MediaInfo来获得高清视频文件的相关信息。

 

1、下载相应的DLL

http://sourceforge.net/projects/mediainfo/files/development_snapshots/上点击Download MediaInfo_GUI_0.7.64_Windows.exe (4.5 MB),下载最新的版本。安装后在安装的目录中找到MediaInfo.dll和MediaInfo_i386.dll这两个DLL文件。

 

2、新建项目

在VS2010中新建项目,把相关的DLL复制到可执行程序的目录(在项目文件夹下的bin\Debug\,或者复制到系统目录中)

注:MediaInfo.dll貌似是64位的;MediaInfo_i386.dll貌似是32位的;在后面的调试中,MediaInfo.dll始终会报错,反而MediaInfo_i386.dll改成MediaInfo.dll后复制到目录中调试一遍成功。

 

3、把官网中的提供的调用代码添加到项目中来

由于DLL仅仅提供了函数。而目前的编码基本上都是面向对象,所以在官网上针对很多的语言都提供了相应的代码,把函数调用包装成类,方便调用者使用。Visual Basic的调用代码在http://sourceforge.net/p/mediainfo/code/5846/tree/MediaInfoLib/trunk/Project/MSVB2010/上,其他语言在相关的网页上也能找到,这里就不赘述了。

 

要注意的是,在如上所做时,还得在VS2010中进行设置

image

在打开的项目属性中,点开“调试”,勾上“启用非托管代码调试”,才能正常调试。

如果没有勾上,运行时则会出现下面的对话框

image

可能是缺少Lib文件的缘故,不过我没在官网上找到Lib文件的下载

另,不需要在项目中对MediaInfo.dll引用。引用会出错,如下所示:

image

 

 

官网上的Visual Basic 2010调用代码如下:


Imports System.Runtime.InteropServices 

Public  Enum  StreamKind  As  UInteger 
    General 
    Visual 
    Audio 
    Text 
    Chapters 
    Image 
    Menu 
    Max 
End  Enum 

Public  Enum  InfoKind  As  UInteger 
    Name 
    Text 
    Measure 
    Options 
    NameText 
    MeasureText 
    Info 
    HowTo 
    Max 
End  Enum 

Public  Enum  InfoOptions  As  UInteger 
    ShowInInform 
    Reserved 
    ShowInSupported 
    TypeOfValue 
    Max 
End  Enum 

Public  Class  MediaInfo 
     Private  Declare  Unicode  Function MediaInfo_New  Lib  "MediaInfo.DLL" ()  As  IntPtr 
     Private  Declare  Unicode  Sub MediaInfo_Delete  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtr
     Private  Declare  Unicode  Function MediaInfo_Open  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal FileName  As  StringAs  UIntPtr 
     Private  Declare  Unicode  Sub MediaInfo_Close  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtr
     Private  Declare  Unicode  Function MediaInfo_Inform  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal Reserved  As  UIntPtrAs  IntPtr 
     Private  Declare  Unicode  Function MediaInfo_GetI  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal StreamKind  As  UIntPtrByVal StreamNumber  As  UIntPtrByVal Parameter  As  UIntPtrByVal KindOfInfo  As  UIntPtrAs  IntPtr  
     Private  Declare  Unicode  Function MediaInfo_Get  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal StreamKind  As  UIntPtrByVal StreamNumber  As  UIntPtrByVal Parameter  As  StringByVal KindOfInfo  As  UIntPtrByVal KindOfSearch  As  UIntPtrAs  IntPtr 
     Private  Declare  Unicode  Function MediaInfo_Option  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal Option_  As  StringByVal Value  As  StringAs  IntPtr 
     Private  Declare  Unicode  Function MediaInfo_State_Get  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrAs  UIntPtr  
     Private  Declare  Unicode  Function MediaInfo_Count_Get  Lib  "MediaInfo.DLL" ( ByVal Handle  As  IntPtrByVal StreamKind  As  UIntPtrByVal StreamNumber  As  IntPtrAs  UIntPtr  

     Dim Handle  As  IntPtr 

     Sub  New() 
        Handle = MediaInfo_New() 
     End  Sub 
     Protected  Overrides  Sub Finalize() 
        MediaInfo_Delete(Handle) 
     End  Sub 
     Function Open( ByVal FileName  As  StringAs System. UIntPtr 
         Return MediaInfo_Open(Handle, FileName) 
     End  Function 
     Sub Close() 
        MediaInfo_Close(Handle) 
     End  Sub 
     Function Inform()  As  String 
         Return  Marshal.PtrToStringUni(MediaInfo_Inform(Handle,  CType(0,  UIntPtr))) 
     End  Function 
     Function Get_( ByVal StreamKind  As  StreamKindByVal StreamNumber  As  IntegerByVal Parameter  As  IntegerOptional  ByVal KindOfInfo  As  InfoKind =  InfoKind.Text)  As  String 
         Return  Marshal.PtrToStringUni(MediaInfo_GetI(Handle,  CType(StreamKind,  UIntPtr),  CType(StreamNumber,  UIntPtr),  CType(Parameter,  UIntPtr),  CType(KindOfInfo,  UIntPtr))) 
     End  Function 
     Function Get_( ByVal StreamKind  As  StreamKindByVal StreamNumber  As  IntegerByVal Parameter  As  StringOptional  ByVal KindOfInfo  As  InfoKind =  InfoKind.Text,  Optional  ByVal KindOfSearch  As  InfoKind =  InfoKind.Name)  As  String
         Return  Marshal.PtrToStringUni(MediaInfo_Get(Handle,  CType(StreamKind,  UIntPtr),  CType(StreamNumber,  UIntPtr), Parameter,  CType(KindOfInfo,  UIntPtr),  CType(KindOfSearch,  UIntPtr))) 
     End  Function 
     Function Option_( ByVal Option__  As  StringOptional  ByVal Value  As  String =  ""As  String 
         Return  Marshal.PtrToStringUni(MediaInfo_Option(Handle, Option__, Value)) 
     End  Function 
     Function State_Get()  As  Integer 
         Return  CInt(MediaInfo_State_Get(Handle)) 
     End  Function 
     Function Count_Get( ByVal StreamKind  As  StreamKindOptional  ByVal StreamNumber  As  UInteger =  UInteger.MaxValue)  As  Integer 
         If StreamNumber =  UInteger.MaxValue  Then 
             Return  CInt(MediaInfo_Count_Get(Handle,  CType(StreamKind,  UIntPtr),  CType(-1,  IntPtr))) 
         Else 
             Return  CInt(MediaInfo_Count_Get(Handle,  CType(StreamKind,  UIntPtr),  CType(StreamNumber,  IntPtr))) 
         End  If 
     End  Function 
End  Class

 

 

 

 

4、再次包装,方便调用

 

由于上面的代码是提供了一个类供调用者使用,因此,我决定再包装一下,使其看起来简单一些(我只需要分辨率、时长、音频数、音频语言这四个信息)。

我包装的代码如下:


Public  Class  clsMediaInfo 
     Private _M  As  MediaInfo 

     Public  Sub  New() 
        _M =  New  MediaInfo 
     End  Sub 

     Public  Function GetInfo(FileName  As  StringAs  String 
        _M.Open(FileName) 
        _M.Option_( "Complete"
         Return _M.Inform 
     End  Function 

     Public  Function Width()  As  String 
         Return _M.Get_( StreamKind.Visual, 0,  "Width"
     End  Function 

     Public  Function Height()  As  String 
         Return _M.Get_( StreamKind.Visual, 0,  "Height"
     End  Function 

     Public  Function Duration()  As  String 
         Return _M.Get_( StreamKind.General, 0,  "Duration/String3"
     End  Function 

     Public  Function AudioCount()  As  Integer 
         Return  Convert.ToInt32(_M.Get_( StreamKind.General, 0,  "AudioCount")) 
     End  Function 

     Public  Function AudioLanguage(Index  As  IntegerAs  String 
         If Index < 0  OrElse Index > AudioCount() - 1  Then Index = 0 
         Return _M.Get_( StreamKind.Audio, Index,  "Language/String"
     End  Function 

     Public  Function AudioLanguage()  As  String() 
         Dim I  As  Integer, C  As  Integer = AudioCount() 
         Dim L(C - 1)  As  String 

         For I = 0  To C - 1 
            L(I) = _M.Get_( StreamKind.Audio, I,  "Language/String"
         Next 

         Return L 
     End  Function 
End  Class

解释一下:

首先在类的内部定义一个MediaInfo类的实例,具体的功能都是通过该实例来完成。

在查看信息前,需调用GetInfo(FileName As String)函数,该函数的目的是获得相关的信息,一共三句话

_M.Open(FileName) 
_M.Option_("Complete"
Return _M.Inform

第1句,打开FileName指定的文件;第2句,获取相关信息,并通知类,已经获取完毕(可能在DLL中会有释放资源等操作);第3句,返回视频文件的相关信息。

第3句话返回的是所有的信息,长长的一串。

 

如果仅仅是想获得某一个信息,则需要调用下面的语句

_M.Get_(StreamKind.Visual, 0, "Width")

一共三个参数。

第1个参数,获取信息的类别。一般取StreamKind.General(通用信息)、StreamKind.Visual(视频信息)、StreamKind.Audio(音频信息)

第2个参数,获取信息的流编号。一般取0(第1个流,视频一般就1个流,音频有可能多于1个流),音频的话,取相应的流编号(0开始,到流数减1)

第3个参数,获取信息的名字。根据该参数返回对应的信息。

 

那么,对应的调用就是

视频宽度:_M.Get_(StreamKind.Visual, 0, "Width")

视频高度:_M.Get_(StreamKind.Visual, 0, "Height")

视频时长:_M.Get_(StreamKind.General, 0, "Duration/String3")。这个有多种选择,该调用返回 01:34:48.683 这种格式;如果是:_M.Get_(StreamKind.General, 0, "Duration"),则返回 5688683 ,还需要自己转换。

音频个数:_M.Get_(StreamKind.General, 0, "AudioCount")

音频语言:_M.Get_(StreamKind.Audio, I, "Language/String")。也是多种选择,该调用返回 English 这种格式;如果是:_M.Get_(StreamKind.Audio, I, "Language"),则返回 en 这种格式。

 

如果想获取其他的信息,直接给出相应的参数就行了。例如想获得视频的最大码率,给出参数BitRate_Maximum就行了。如下调用

_M.Get_(StreamKind.Visual, 0, "BitRate_Maximum")

 

那么,如何能知道有哪些参数呢?参看

MediaInfo参数大全

C#使用MediaInfo查看媒体信息

这两篇文章对参数介绍的很详细,只是文章写得早,提供的DLL版本比较低罢了

 

下面是获取 G:\Despicable.Me.2010.BluRay.1080p.DTS.2Audio.x264-CHD.mkv 这个高清视频文件信息的调用代码:

Dim S As New clsMediaInfo

S.GetInfo("G:\Despicable.Me.2010.BluRay.1080p.DTS.2Audio.x264-CHD.mkv")

Dim S1 As String = "" 
S1 &= S.Width & "  " & S.Height & vbNewLine 
S1 &= S.Duration & vbNewLine 
S1 &= S.AudioCount & vbNewLine 
S1 &= S.AudioLanguage(0) & "," & S.AudioLanguage(1)

RichTextBox1.Text = S1

 

返回的信息如下:

1920  1040 
01:34:48.683 

English,Chinese

说明视频分辨率为1920*1040;时长:1小时34分48秒;2个音频;分别是英文和中文;

 

这个代码在做高清视频文件的信息库的时候特别有用。可以根据高清视频文件自动获取相关信息,毋须再手动填充信息。


    本文转自万仓一黍博客园博客,原文链接:http://www.cnblogs.com/grenet/p/3222731.html,如需转载请自行联系原作者


相关文章
|
9月前
|
关系型数据库 MySQL 数据库连接
docker拉取MySQL后数据库连接失败解决方案
通过以上方法,可以解决Docker中拉取MySQL镜像后数据库连接失败的常见问题。关键步骤包括确保容器正确启动、配置正确的环境变量、合理设置网络和权限,以及检查主机防火墙设置等。通过逐步排查,可以快速定位并解决连接问题,确保MySQL服务的正常使用。
1384 82
|
8月前
|
人工智能 算法 程序员
揭秘 AI 编程工具的费用真相:2025 年开发者视角-优雅草卓伊凡
揭秘 AI 编程工具的费用真相:2025 年开发者视角-优雅草卓伊凡
388 1
揭秘 AI 编程工具的费用真相:2025 年开发者视角-优雅草卓伊凡
|
数据采集 存储 安全
利用爬虫技术自动化采集汽车之家的车型参数数据
汽车之家是一个专业的汽车网站,提供了丰富的汽车信息,包括车型参数、图片、视频、评测、报价等。如果我们想要获取这些信息,我们可以通过浏览器手动访问网站,或者利用爬虫技术自动化采集数据。本文将介绍如何使用Python编写一个简单的爬虫程序,实现对汽车之家的车型参数数据的自动化采集,并使用亿牛云爬虫代理服务来提高爬虫的稳定性和效率。
910 0
利用爬虫技术自动化采集汽车之家的车型参数数据
|
存储 数据采集 Kubernetes
一文详解K8s环境下Job类日志采集方案
本文介绍了K8s中Job和Cronjob控制器用于非常驻容器编排的场景,以及Job容器的特点:增删频率高、生命周期短和突发并发大。文章重点讨论了Job日志采集的关键考虑点,包括容器发现速度、开始采集延时和弹性支持,并对比了5种采集方案:DaemonSet采集、Sidecar采集、ECI采集、同容器采集和独立存储采集。对于短生命周期Job,建议使用Sidecar或ECI采集,通过调整参数确保数据完整性。对于突发大量Job,需要关注服务端资源限制和采集容器的资源调整。文章总结了不同场景下的推荐采集方案,并指出iLogtail和SLS未来可能的优化方向。
|
12月前
|
算法 数据可视化 物联网
埃隆·马斯克:第一性原理和五步工作法
马斯克的逆推式五步工作法不仅是一种高效解决问题的思维框架,也为团队提供了一种优化流程的清晰路径。
810 1
埃隆·马斯克:第一性原理和五步工作法
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
1163 1
|
监控 物联网 数据安全/隐私保护
云上智能工厂:重塑生产模式,引领未来制造业的新纪元
更加注重数据安全与隐私保护:随着智能制造的深入发展,数据安全与隐私保护问题将日益凸显。云上智能工厂将加强数据加密、访问控制、审计追踪等安全措施的应用和实施力度,确保生产数据的安全性和隐私性。
862 0
|
机器学习/深度学习 人工智能 算法
自动化测试中AI驱动的决策框架
【5月更文挑战第28天】 本文探讨了在自动化软件测试过程中,如何利用人工智能(AI)技术来优化测试用例的选择和执行。通过引入一个基于机器学习算法的智能决策框架,我们可以提高测试的效率和有效性,同时减少冗余和不必要的测试活动。与传统的摘要不同,本摘要将直接深入到文章的核心议题,介绍AI在自动化测试中的作用,并指出其在未来的发展趋势。
|
Web App开发
电力电子技术实现电能变换与控制的原理
本文介绍了电力变换的四大类型:AC-DC、DC-AC、DC-DC和AC-AC,以及相关变换电路的工作原理。DC-DC变换分为非隔离(Buck、Boost、Buck-Boost)和隔离型电路,如推挽、反激等。AC-DC变换,即整流,通过桥式整流电路实现,可控整流用于调节输出电压。逆变(DC-AC)涉及全桥逆变电路,用于将直流电转换回交流电。这些变换在电源转换、电机控制和通信系统中至关重要。
861 4
电力电子技术实现电能变换与控制的原理