How to read the bit rate information from a .mov video file header (QuickTime File Format)?

隐身守侯 提交于 2019-12-03 21:58:11

This will get you what you want, "The Bit Rate that is shown in Windows Explorer", but not from the QT metadata. If it is not appropriate for some reason, maybe it will work as a fallback solution until you can work out the Atom based answer or as something to compare the QT Atom results to.

In short, if you want what Explorer shows, get it from Explorer:

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

    }
}

Usage:

Dictionary<string, string> myinfo;
myinfo = ShellInfo.GetMediaProperties(filepath);

The test file is a sample QT mov from Apple's site, so there is nothing special about it. The view in Explorer:

The results from GetMediaProperties:

The BitRate returned also matched the Audio BitRate returned by MediaProps and MediaTab (both use MediaInfo.DLL to gather all media property values).


The first 35 Shell extended properties are pretty well documented. I think as of Windows 7, this goes to 291(!). Many are file type specific for photos, emails etc. A few which may be of interest:

282: Data rate
283: Frame height
284: Frame rate
285: Frame width
286: Total bitrate

Data rate (282) is the Video BitRate (matches MediaInfo) ; Total Bitrate (286) is the combined a/v bitrate.


Windows 8 (UPDATE)

While the above code appears to run OK on Windows 7, for computers running Windows 8, to avoid a System.InvalidCastException on the following line...:

Shell shell = new Shell();

... the following code will need to be run to instantiate the Shell and Folder COM objects:

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

Solution found in the Instantiate Shell32.Shell object in Windows 8 question on the Visual Studio Forum.

Also, on Windows 8, it appears that more attributes have been added so that the maximum index is now 309 (with a few empty entries) and the above mentioned attributes have different indices:

298: Data rate
299: Frame height
300: Frame rate
301: Frame width
303: Total bitrate


It seems the returns from Shell32 has some characters in it which prevent a simple and direct conversion to an int value. For the Bit Rate:

string bRate = myinfo["Bit rate"];       // get return val
bRate = new string(bRate.Where(char.IsDigit).ToArray());  // tidy up

int bitRate = Convert.ToInt32(bRate);

Its not recorded anywhere. As a general rule, it is bad practice to store a value that can be calculated from other values. Plus bitrate can change over time with the same video. What you can do is add up the sizes of the frames you are interested in the stsz box (atoms are called boxes in the iso standard) and the sample durations from he stts box and to the math.

If you are OK to read informational value (you already have szatmary's answer for more accurate information), shell reports this by parsing the file and reading metadata through Media Foundation MPEG-4 Property Handler class.

Native API entry point for this is PSLookupPropertyHandlerCLSID and then regular COM instantiation for IPropertyStore interface and then reading the properties. Even if you don't have C# interface into this, you could easily get this through P/Invoke and interoperability layer.

The properties you can read this way are easily discovered by this helper app, wrapping the API: FilePropertyStore (Win32, x64). That is, what you see through the app is also available to you through the API mentioned.

Here is an excerpt from what it gets for a .MOV file (note PKEY_Audio_EncodingBitrate and 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`

The method also works for other media file formats, getting data using the same keys through respective property handlers for other container formats.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!