65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 访问 WMF 元数据

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (9投票s)

2006 年 6 月 21 日

2分钟阅读

viewsIcon

176502

downloadIcon

2427

一篇关于如何使用 C# 和 Windows Media Format SDK 读取 Windows Media Format 文件中的元数据的文章。

引言

那么,您想编写一个 C# 应用程序,可以使用特定的 Windows Media Format (WMF) 元数据字段吗?也许您想列出您拥有的所有电影文件的标题和评级。幸运的是,微软有一个 Windows Media Format 的 SDK。但是,WMF SDK 不是托管代码。但是,它非常出色地为元数据访问提供了托管包装器。实际上,SDK 包含一个用于编辑 WMF 元数据的完整示例程序。那么,为什么不直接使用它呢?因为,在我的情况下,它对于我的客户的需求来说是多余的。在这种情况下,我只需要能够查询一个 WMF 文件(特别是 WMV 文件)以获取作者和版权信息。所以,我编写了自己的类,该类经过优化,专门处理字符串元数据。(它可以很容易地修改以适应其他数据类型,或者通过索引而不是名称来访问元数据。)

由于我需要一些这么简单的东西,我想其他人可能也需要。此外,这个例子可以作为在应用程序中使用 WMF 元数据的一个简单介绍。

背景

首先,我们谈论的是哪种元数据? WMF 元数据字段是四种数据类型之一

  • QWORD (四字)
  • DWORD (双字)
  • BOOL
  • STRING (字符串)

例如,以下是我测试 WMV 文件之一中可用的元数据属性列表

 Index    Name                   Stream Language Type  
 -----    ------                 ------ -------- ----  
   0      Duration                    0    0    QWORD  
   1      Bitrate                     0    0    DWORD  
   2      Seekable                    0    0     BOOL  
   3      Stridable                   0    0     BOOL  
   4      Broadcast                   0    0     BOOL  
   5      Is_Protected                0    0     BOOL  
   6      Is_Trusted                  0    0     BOOL  
   7      Signature_Name              0    0   STRING  
   8      HasAudio                    0    0     BOOL  
   9      HasImage                    0    0     BOOL  
  10      HasScript                   0    0     BOOL  
  11      HasVideo                    0    0     BOOL  
  12      CurrentBitrate              0    0    DWORD  
  13      OptimalBitrate              0    0    DWORD  
  14      HasAttachedImages           0    0     BOOL  
  15      Can_Skip_Backward           0    0     BOOL  
  16      Can_Skip_Forward            0    0     BOOL  
  17      FileSize                    0    0    QWORD  
  18      HasArbitraryDataStream      0    0     BOOL  
  19      HasFileTransferStream       0    0     BOOL  
  20      WM/ContainerFormat          0    0    DWORD  
  21      Title                       0    0   STRING  
  22      Author                      0    0   STRING  
  23      Copyright                   0    0   STRING  
  24      Description                 0    0   STRING  
  25      Rating                      0    0   STRING  
  26      BannerImageURL              0    0   STRING  
  27      CopyrightURL                0    0   STRING  
  28      WMFSDKVersion               0    0   STRING  
  29      WMFSDKNeeded                0    0   STRING  
  30      IsVBR                       0    0     BOOL  
  31      WM/AlbumTitle               0    0   STRING  
  32      WM/Track                    0    0   STRING  
  33      WM/PromotionURL             0    0   STRING  
  34      WM/AlbumCoverURL            0    0   STRING  
  35      WM/Genre                    0    0   STRING  
  36      WM/Year                     0    0   STRING  
  37      WM/GenreID                  0    0   STRING  
  38      WM/Composer                 0    0   STRING  
  39      WM/Lyrics                   0    0   STRING  
  40      WM/ToolName                 0    0   STRING  
  41      WM/ToolVersion              0    0   STRING  
  42      WM/AlbumArtist              0    0   STRING  
  43      WM/AuthorURL                0    0   STRING  
  44      WM/AudioFileURL             0    0   STRING  
  45      WM/Language                 0    0   STRING  
  46      WM/ParentalRating           0    0   STRING  
  47      WM/BeatsPerMinute           0    0   STRING  
  48      WM/InitialKey               0    0   STRING  
  49      WM/Mood                     0    0   STRING  
  50      WM/DVDID                    0    0   STRING  
  51      WM/UniqueFileIdentifier     0    0   STRING  
  52      WM/ModifiedBy               0    0   STRING  
  53      WM/RadioStationName         0    0   STRING  
  54      WM/RadioStationOwner        0    0   STRING  
  55      WM/PlaylistDelay            0    0   STRING  
  56      WM/Codec                    0    0   STRING  
  57      WM/DRM                      0    0   STRING  
  58      WM/ISRC                     0    0   STRING  
  59      WM/Provider                 0    0   STRING  
  60      WM/ProviderRating           0    0   STRING  
  61      WM/ProviderStyle            0    0   STRING  
  62      WM/ContentDistributor       0    0   STRING  
  63      WM/SubscriptionContentID    0    0   STRING  
  64      WM/ASFPacketCount           0    0    QWORD  
  65      WM/ASFSecurityObjectsSize   0    0    QWORD

正如您所看到的,可以有很多可用的属性!但是,重要的是要注意,并非所有文件都包含相同的属性列表。请确保您正在查询的文件具有您请求的字段。如果没有,查询将返回一个错误:来自 HRESULT 的异常:0xC00D07F0来自 HRESULT 的异常:0xC00D001D

使用代码

由于托管包装器是微软的代码,并且是 WMF SDK 的一部分,因此我没有将其作为本文的下载内容包含在内。但您可以从 MSDN 下载 SDK。安装完成后,找到“Managed”目录(对于默认安装,它将是:C:\WMSDK\WMFSDK95\samples\managed\)。在该目录下,您将找到包装器项目。使用它的最简单方法是将该项目导入到您的 Visual Studio 解决方案中,然后在您的主应用程序项目中添加对该项目的引用。现在,将我的 MetaDataReader 类文件导入到您的主项目中,并使用 GetFieldByName 方法检索您所需的元数据字段的值。

这是 MetaDataReader

using System;
using System.Collections.Generic;
using System.Text;
using WMFSDKWrapper;
//managed wrapper to WMF SDK -
//        provides access to metadata

namespace MyNamespace
{

    /// This class contains the functionality
    /// for handling interaction with the media file
    /// metadata, via the WMF SDK managed wrapper class.
    public class MetaDataReader
    {

        /// Default constructor
        public MetaDataReader()
        {
        }

        /// Method to obtain a metadata attribute by passing in its name. 
        /// Assumes the metadata type is STRING.
        /// Uses the SDK function GetAttributeByName.
        ///
        /// param name="filename" - the filename
        ///            (including path) of media file to interrogate
        /// param name="attrName" - the name of the field we're looking for
        /// returns - the value of the named attribute,
        ///           empty string if not found, or error message
        public string GetFieldByName(string fileName, string attrName)
        {
            try
            {
                //object used to access WMF file 
                IWMMetadataEditor MetadataEditor;
                //object to use access metadata 
                IWMHeaderInfo3 HeaderInfo3;
                //media stream to interrogate
                ushort streamNum = 0;
                //data type of attribute
                WMT_ATTR_DATATYPE wAttribType;
                //value of attribute (as returned by method call)
                byte[] pbAttribValue = null;
                //length of attribute (byte array)
                ushort wAttribValueLen = 0;

                WMFSDKFunctions.WMCreateEditor(out MetadataEditor);

                MetadataEditor.Open(fileName);

                HeaderInfo3 = (IWMHeaderInfo3)MetadataEditor;

                //make call to get attribute length
                HeaderInfo3.GetAttributeByName(ref streamNum, attrName, 
                  out wAttribType, pbAttribValue, ref wAttribValueLen);
                //set byte array length
                pbAttribValue = new byte[wAttribValueLen];
                //make call again, which will get value 
                //into correct-length byte array
                HeaderInfo3.GetAttributeByName(ref streamNum, 
                                               attrName, out wAttribType, 
                                               pbAttribValue, 
                                               ref wAttribValueLen);

                MetadataEditor.Close();

                return ConvertAttrToString(pbAttribValue, 
                                           wAttribValueLen);
            }
            catch (Exception e)
            {
                return "ERROR: " + e.Message;
            }
        }//end method

        /// Method to convert byte array value into string. 
        /// (From the Microsoft WMF SDK sample.)
        ///
        /// param name="pbValue" - byte array value of attribute
        /// param name="dwValueLen" - Length of byte array
        private string ConvertAttrToString(byte[] pbValue, ushort dwValueLen)
        {
            string Value = "";

            if (0 == dwValueLen)
            {
                Value = "";
            }
            else
            {
                if ((0xFE == Convert.ToInt16(pbValue[0])) &&
                     (0xFF == Convert.ToInt16(pbValue[1])))
                {
                    Value = "UTF-16LE BOM+";

                    if (4 <= dwValueLen)
                    {
                        for (int i = 0; i < pbValue.Length - 2; i += 2)
                        {
                            Value += 
                              Convert.ToString(BitConverter.ToChar(pbValue, i));
                        }
                    }
                }
                else if ((0xFF == Convert.ToInt16(pbValue[0])) &&
                          (0xFE == Convert.ToInt16(pbValue[1])))
                {
                    Value = "UTF-16BE BOM+";
                    if (4 <= dwValueLen)
                    {
                        for (int i = 0; i < pbValue.Length - 2; i += 2)
                        {
                            Value += 
                              Convert.ToString(BitConverter.ToChar(pbValue, i));
                        }
                    }
                }
                else
                {
                    Value = "";
                    if (2 <= dwValueLen)
                    {
                        for (int i = 0; i < pbValue.Length - 2; i += 2)
                        {
                            Value += 
                              Convert.ToString(BitConverter.ToChar(pbValue, i));
                        }
                    }
                }
            }//end else not a 0-length string

            return Value;
            
        }//end method

    }//end class
}

这是一个示例调用的代码片段

MetaDataReader objMetaData = new MetaDataReader();
string Author = objMetaData.GetAttrByName("C:\Videos\MyVideo.wmv", "Author");

就是这样!我希望这个简单的例子能为您提供编写一些访问 WMF 元数据的酷炫应用程序所需的基础知识。

历史

  • 06.20.06 - 初始版本。
© . All rights reserved.