如何从.movvideo文件头(QuickTime文件格式)中读取比特率信息?
我一直试图从.mov文件(QuickTime文件格式)的元数据中读取一些值,但成效有限。 我一直在使用以下链接作为参考:
QuickTime文件格式规范简介
我已经设法正确定位和读出/计算媒体持续时间,但我似乎无法找到存储比特率信息的primefaces。(primefaces是文件内部元数据的内部块)。
如果有人能指出我正确的Atom阅读,我会好好读它…我甚至无法在文档中找到它。 “比特率”仅在整个文档中提及过几次。
更新>>>
通过@szatmary下面提供的非常有限的信息,我已经从相关的跟踪primefaces解析了样本大小primefaces和样本primefaces的时间 ,但是我得到了一些奇怪的值。 例如,我不断获得样本大小值1
(当从具有恒定比特率的多个不同单个video.mov文件中读取时)。 相关文档(来自上面的链接)说:
样本量
一个32位整数,指定样本大小。 如果所有样本的大小相同,则此字段包含该大小值。 如果此字段设置为0,则样本具有不同的大小,并且这些大小存储在样本大小表中。
因此该字段的值为1
,这意味着所有样本具有相同的大小,并且[ 样本大小表 ]字段中的条目数与样本时间表的单个条目中的样本计数字段的数量相匹配(一些非常大的数字)。 文档说明了这一点:
…如果video媒体具有恒定的帧速率,则该表将具有一个条目,并且计数将等于样本的数量。
因此video具有恒定的比特率。 但是,当从样本大小表中读取大小条目时,它们都是不同的且非感性的…有些是0,而有些则是非常大的数字,大约40000.如果video具有恒定位,为什么它们不同评价,或者在这种情况下我不应该阅读它们吗?
我发现的另一个问题是Sample to Sample Atom的Time to Sample Table中的单个条目具有以下值:
样本数: 一些非常大的数字 (预期)
样本持续时间:1
不幸的是,文档(来自上面的链接)非常简单:
时间表样本
一个表,用于定义介质中每个样本的持续时间。 每个表条目包含计数字段和持续时间字段。
那么这1
值使用哪些单位( 样本持续时间和样本量 )?
任何有关计算正确比特率的进一步帮助将不胜感激。 请注意,我一直在考虑文件的Big-Endian ,并在读取之前反转每个字段值的字节。
更新2 >>>
我已经设法计算出采样率的计算如下:
媒体持续时间=持续时间/时间刻度(来自电影标题primefaces或轨道标题primefaces )采样率=样本计数(来自样本时间primefaces )/媒体持续时间
我现在只需要破解比特率 ,需要进一步的帮助。
这将为您提供所需的“Windows资源管理器中显示的比特率” ,而不是来自QT元数据。 如果由于某种原因它不合适,它可能会作为一个后备解决方案,直到您可以计算出基于Atom的答案或者将QT Atom结果与之比较。
简而言之,如果您想要资源管理器显示,请从资源管理器中获取:
// add reference to Microsoft Shell controls and Automation // from the COM tab using Shell32; class ShellInfo { // "columns" we want: // FileName = 0; const int PerceivedType = 9; // FileKind = 11; // MediaBitrate = 28; // MediaLength = 27; static int[] info = {0, 9, 11, 27, 28}; // note: author and title also available public static Dictionary GetMediaProperties(string file) { Dictionary xtd = new Dictionary(); Shell32.Shell shell = new Shell32.Shell(); Shell32.Folder folder; folder = shell.NameSpace(Path.GetDirectoryName(file)); foreach (var s in folder.Items()) { if (folder.GetDetailsOf(s, 0).ToLowerInvariant() == Path.GetFileName(file).ToLowerInvariant()) { // see if it is video // possibly check FileKind ??? if (folder.GetDetailsOf(s, PerceivedType).ToLowerInvariant() == "video") { // add just the ones we want using the array of col indices foreach (int n in info) { xtd.Add(folder.GetDetailsOf(folder.Items(), n), folder.GetDetailsOf(s, n)); } } break; } // ToDo: freak out when it is not a video or audio type // depending what you are trying to do } return xtd; } }
用法:
Dictionary myinfo; myinfo = ShellInfo.GetMediaProperties(filepath);
测试文件是来自Apple网站的QT mov示例,因此没有什么特别之处。 资源管理器中的视图:
GetMediaProperties
的结果:
返回的MediaTab
还匹配MediaProps
和MediaTab
返回的Audio MediaTab
(两者都使用MediaInfo.DLL
来收集所有媒体属性值)。
前35个Shell扩展属性已有详细记录。 我认为从Windows 7开始,这就是291(!)。 许多是特定于照片,电子邮件等的文件类型。一些可能感兴趣的:
282:数据速率
283:框架高度
284:帧速率
285:框架宽度
286:总比特率
数据速率(282)是video比特率(匹配MediaInfo); 总比特率(286)是组合的a / v比特率。
Windows 8(更新)
虽然上面的代码似乎在Windows 7上运行正常,但对于运行Windows 8的计算机,以避免在以下行上出现System.InvalidCastException
…:
Shell shell = new Shell();
…需要运行以下代码来实例化Shell
和Folder
COM对象:
Type shellType = Type.GetTypeFromProgID("Shell.Application"); Object shell = Activator.CreateInstance(shellType); Folder folder = (Folder)shellType.InvokeMember("NameSpace", BindingFlags.InvokeMethod, null, shell, new object[] { Path.GetDirectoryName(file) });
在Visual Studio论坛上的Windows 8问题中的Instantiate Shell32.Shell对象中找到的解决方案。
此外,在Windows 8上,似乎添加了更多属性,以便最大索引现在为309(带有一些空条目),并且上述属性具有不同的索引:
298:数据速率
299:框架高度
300:帧速率
301:帧宽
303:总比特率
看来Shell32的返回值中有一些字符阻止了简单直接转换为int值。 对于比特率:
string bRate = myinfo["Bit rate"]; // get return val bRate = new string(bRate.Where(char.IsDigit).ToArray()); // tidy up int bitRate = Convert.ToInt32(bRate);
它没有记录在任何地方 作为一般规则,存储可以从其他值计算的值是不好的做法。 加上比特率可以随着时间的推移改变相同的video。 您可以做的是在stsz框中添加您感兴趣的框架的大小(primefaces在iso标准中称为框)以及从stts框到数学的样本持续时间。
如果您可以阅读信息值(您已经获得了szatmary的答案以获得更准确的信息),shell会通过解析文件并通过Media Foundation MPEG-4 Property Handler类读取元数据来报告此情况。
本机API入口点是PSLookupPropertyHandlerCLSID
,然后是IPropertyStore
接口的常规COM实例化,然后读取属性。 即使您没有C#接口,也可以通过P / Invoke和互操作性层轻松实现。
这个帮助器应用程序很容易发现这种方式可以读取的属性,包装API: FilePropertyStore
( Win32
, x64
)。 也就是说,您通过应用程序看到的内容也可通过所提到的API获得。
以下摘录自.MOV文件的内容(注意PKEY_Audio_EncodingBitrate
和PKEY_Video_EncodingBitrate
):
## Property * `PKEY_Media_Duration`, Length: `855000000` (`VT_UI8`) // `855,000,000` * `PKEY_Audio_EncodingBitrate`, Bit rate: `43744` (`VT_UI4`) // `43,744` * `PKEY_Audio_ChannelCount`, Channels: `1` (`VT_UI4`) // `1` * `PKEY_Audio_Format`, Audio format: `{00001610-0000-0010-8000-00AA00389B71}` (`VT_LPWSTR`) // FourCC 0x00001610 * `PKEY_Audio_SampleRate`, Audio sample rate: `32000` (`VT_UI4`) // `32,000` * `PKEY_Audio_SampleSize`, Audio sample size: `16` (`VT_UI4`) // `16` * `PKEY_Audio_StreamNumber`: `1` (`VT_UI4`) // `1` * `PKEY_Video_EncodingBitrate`, Data rate: `263352` (`VT_UI4`) // `263,352` * `PKEY_Video_FrameWidth`, Frame width: `640` (`VT_UI4`) // `640` * `PKEY_Video_FrameHeight`, Frame height: `480` (`VT_UI4`) // `480`
该方法也适用于其他媒体文件格式,通过相应的属性处理程序为其他容器格式使用相同的密钥获取数据。