我一直试图从.mov文件(QuickTime文件格式)的元数据中读取一些值,但成效有限。我一直在使用以下链接作为参考:
我设法正确定位和读出/计算媒体持续时间,但我似乎无法找到存储比特率信息的原子。(原子是内部元数据的内部块文件)。
如果有人能指出正确的Atom阅读,我会好好阅读它...我甚至无法在文档中找到它。 "比特率"在整篇文档中只提到了几次。
更新>>>
根据@szatmary提供的非常有限的信息,我已经从相关的 Track Atom解析了样本大小原子和样本原子的时间 ,但我得到了一些奇怪的价值观。例如,我不断获得样本大小值1
(当从具有常量比特率的多个不同单个视频.mov文件中读取时)。相关文档(来自上面的链接)说:
样本量
一个32位整数,指定样本大小。如果所有样本的大小相同,则此字段包含该大小值。如果此字段设置为0,则样本具有不同的大小,并且这些大小存储在样本大小表中。
因此该字段的值为1
,这意味着所有样本的大小相同,条目数 [在样本大小表]字段与 Time to Sample Table (一些非常大的数字)的单个条目中的 Sample Count 字段匹配。文档说明了这一点:
...如果视频媒体具有恒定的帧速率,则该表将具有一个条目,并且计数将等于样本的数量。
因此视频具有恒定的比特率。但是,当从样本大小表中读取大小条目时,它们都是不同的且非感性的......有些是0,而有些是非常大的数字,高达40000左右。为什么它们不同如果视频具有恒定的比特率,或者在这种情况下我不应该读取它们吗?
我发现的另一个问题是 Time to Sample Atom 的 Time to Sample Table 中的单个条目具有以下值:
样本计数:一些非常大的数字(预期)
样本持续时间:1
不幸的是,文档(来自上面的链接)非常简单:
采样时间表
一个表,用于定义介质中每个样本的持续时间。每个表条目都包含计数字段和持续时间字段。
那么这些1
值使用哪些单位(示例持续时间& 样本大小)?
任何有关计算正确比特率的进一步帮助将不胜感激。请注意,我一直在考虑文件的 Big-Endian-ness 并在读取之前反转每个字段值的字节。
更新2>>>
我已经设法计算出采样率的计算如下:
媒体持续时间=持续时间/时间刻度(来自电影标题原子或跟踪标题原子) 采样率=样本计数(来自时间到样本原子)/媒体持续时间
我现在只需要破解比特率,需要进一步的帮助。
答案 0 :(得分:3)
这将为您提供您想要的 “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<string, string> GetMediaProperties(string file)
{
Dictionary<string, string> xtd = new Dictionary<string, string>();
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<string, string> myinfo;
myinfo = ShellInfo.GetMediaProperties(filepath);
测试文件是来自Apple网站的QT mov示例,因此没有什么特别之处。资源管理器中的视图:
GetMediaProperties
的结果:
返回的BitRate还匹配MediaProps
和MediaTab
返回的音频比特率(两者都使用MediaInfo.DLL
来收集所有媒体属性值。)
前35个Shell扩展属性已有详细记录。我认为从Windows 7开始,这就是291(!)。许多是特定于照片,电子邮件等的文件类型。一些可能感兴趣的文件:
282:数据率
283:框架高度
284:帧率
285:框架宽度
286:总比特率
数据速率(282)是视频比特率(匹配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论坛上的Instantiate Shell32.Shell object in Windows 8问题中找到了解决方案。
此外,在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);
答案 1 :(得分:1)
它没有记录在任何地方。作为一般规则,存储可以从其他值计算的值是不好的做法。加上比特率可以随着时间的推移改变相同的视频。您可以做的是在stsz框中添加您感兴趣的框架的大小(原子在iso标准中称为框)以及从stts框到数学的样本持续时间。
答案 2 :(得分:1)
如果您可以阅读信息值(您已经获得了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`
该方法也适用于其他媒体文件格式,通过相应的属性处理程序为其他容器格式使用相同的密钥获取数据。