アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

ASF オブジェクト

Heade Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid1675B22630-668E-11CF-A6D9-00AA0062CE6C
Object SizeQWORDUInt648Header Object 全体のサイズ
Number of Header ObjectsDWORDUInt324Header Object に含まれる、子オブジェクトの総数。
Reserved1BYTEbyte1予約領域
Reserved2BYTEbyte1予約領域

ASF ファイルは Header Object から始まる。ファイル操作をおこなう場合は、まず先頭から 16 バイト読み込み、それが Header Object の GUID であることを確認する。Header Object の後には、Number of Header Objects として格納された数の子オブジェクトが続いてゆく。

Codec List Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid1686D15240-311D-11D0-A3A4-00A0C90348F6
Object SizeQWORDUInt648オブジェクト全体のサイズ
Codec Entries CountDWORDUInt324コーデック情報の総数

コーデック情報リスト。Codec Entries には Codec Entries Count に定義された数だけ、以下のデータが続く。

名前型 (.NET)サイズ内容
TypeWORDUInt1620x0001 = 動画、0x0002 = オーディオ、0xFFFF = 未知のコーデック
Object SizeQWORDUInt648オブジェクト全体のサイズ
Codec Name LengthWORDUInt162コーデック名の文字数
Codec NameWCHARchar*コーデック名。
Codec Description LengthWORDUInt162詳細情報の文字数
Codec DescriptionWCHARchar*詳細情報
Codec Information LengthWORDUInt162コーデック情報のバイト数
Codec InformationBYTEbyte*コーデック固有の情報

他のテキスト系メタデータと異なり、Codec Name LengthCodec Description Length が文字数という点に留意する必要がある。Codec NameCodec Description は UTF-16LE 文字列なので「長さ x 2」が読み出すバイト数となる。

Content Description Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid1675B22633-668E-11CF-A6D9-00AA0062CE6C
Object SizeQWORDUInt648オブジェクト全体のサイズ
Title LengthWORDUInt162タイトルのバイト数
Author LengthWORDUInt162アーティスト名のバイト数
Copyright LengthWORDUInt162著作権情報タイトルのバイト数
Description LengthWORDUInt162コメントのバイト数
Rating LengthWORDUInt162レーティング (保護者による制限) のバイト数
TitleWCHARchar*タイトル
AuthorWCHARchar*アーティスト名
CopyrightWCHARchar*著作権情報
DescriptionWCHARchar*コメント
RatingWCHARchar*レーティング (保護者による制限)

コンテンツの基本的なメタデータが格納されている。これらは言語非依存で、常にデータ領域が確保されるようだ。Windows Media Player 11 の拡張タグエディタで、コメントを言語別にいくつか書いてみたところ、このオブジェクトの Description Length は 0、Description は空となり、代りに Metadata Library Object へ言語別に登録されていた。

多言語・多ストリームにきちんと対応しているメタデータエディタは少なく、Windows Media Player ですら一部のタグしか対応できていない。一方、ASF や WMA に対応しているアプリケーションなら、大概はこのオブジェクトに書かれるデータに対応していると思われる。

よって、多言語・多ストリーム対応する際は、Metadata Library Object と同時にこちらにもデータを設定したほうがよいだろう。

Extended Content Description Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid16D2D0A440-E307-11D2-97F0-00A0C95EA850
Object SizeQWORDUInt648オブジェクト全体のサイズ
Content Descriptors CountWORDUInt162メタデータの総数

言語・ストリームに依存しない、ファイル全体に対するメタデータ。Content Descriptors Count に定義された数だけ以下のデータが続く。

名前型 (.NET)サイズ内容
Descriptor Name LengthWORDUInt162データ名のバイト数
Descriptor NameWCHARchar*データ名
Descriptor Value Data TypeWORDUInt162データの型 (後述)
Descriptor Value LengthWORDUInt162データのバイト数
Descriptor ValueBYTEbyte[]*データ

メタデータは名前、型、データで構成されている。名前には WMF でおなじみの文字列がはいる。例えば WM/AlbumArtist など。データの内容は型によって決まる。型は以下の数値が定義される。

型 (.NET)サイズ
0x00000WCHARchar*
0x00001BYTEbyte[]*
0x00002BOOLbool4
0x00003DWORDUInt324
0x00004QWORDUInt648
0x00005WORDUInt162

C# の型に変換する場合、WCHAR は Encoding.Unicode.GetString() を使用し、得られた文字列の末尾に NULL 文字があれば削除する。C# の文字列は NULL 文字終端ではないので、これを行わないと正しく処理できない。書き込むときは NULL 文字を足した上でバイト配列にする。

BOOL、DWORD、QWORD、WORD は、BitConverter.To~() でそのまま変換できる。

BYTE の場合は専用のデータ型となるので、データ名を判定して自前で変換する必要がある。ジャケット画像やタイムライン付きの歌詞データなどがこれに該当する。

File Properties Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid168CABDCA1-A947-11CF-8EE4-00C00C205365
Object SizeQWORDUInt648オブジェクト全体のサイズ
File IDGUIDGuid16ファイル ID
File SizeQWORDUInt648ファイルのサイズ
Creation DateQWORDUInt648ファイルの作成日 (UTC)
Data Packets CountQWORDUInt648Data Object 内に存在するパケットエントリの総数
Play DurationQWORDUInt648再生時間
Send DurationQWORDUInt648送信時間
PrerollQWORDUInt648ファイル再生を始める前に必要なバッファリング時間
FlagsDWORDUInt324フラグ
Minimum Data Packet SizeDWORDUInt324送信時における最小のデータパケットのサイズ
Maximum Data Packet SizeDWORDUInt324送信時における最大のデータパケットのサイズ
Maximum BitrateDWORDUInt324送信時における最大ビットレート

ファイル情報が格納されている。File ID は Data Object 側の定義と対応している必要があり、ファイルを編集した場合は、ユニークな値を再割り当てする必要があるとのこと。編集とは Data Object 側のことを指しており、メタデータの場合は更新不要と思われる。

File Size はファイルを編集した場合、必ず更新しなければならない。このデータは WMF の FileSize タグに対応する。

Creation Date はファイル作成日なので、ゼロからファイルを構築するときだけ設定するのだろう。

コンテンツの再生時間を取得する場合は、Play Duration から Preroll を差し引く必要がある。Preroll はミリ秒単位で格納されており、10,000 倍することで Play Duration と同位になる。つまり時間は「Play Duration - (Preroll x 10,000)」で求められる。この数値は WMF の Duration タグに対応する。

他のデーターは、オンラインストリーミングに関するものと予想されるので割愛。

Stream Bitrate Properties Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid168CABDCA1-A947-11CF-8EE4-00C00C205365
Object SizeQWORDUInt648オブジェクト全体のサイズ
Bitrate Records CountWORDUInt162Bitrate Records の総数。

ビットレートに関する情報を格納している。Bitrate Records Count に指定された数だけ、以下のデータが続く。

名前型 (.NET)サイズ内容
FlagsWORDUInt162フラグ。0 ~ 6 ビットがストリーム番号、それ以降は予約領域
Average BitrateDWORDUInt324平均ビットレート

ストリーム内の平均ビットレートを表している。VBR なストリームを扱う場合に使用するのだろうか?

Header Extension Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid165FBF03B5-A92E-11CF-8EE3-00C00C205365
Object SizeQWORDUInt648オブジェクト全体のサイズ
Reserved Field 1GUIDGuid16予約領域
Reserved Field 2WORDUInt162予約領域
Header Extension Data SizeDWORDUInt324拡張ヘッダのバイト数

拡張ヘッダ情報が格納されている。通常のヘッダ情報は Header Object、オプション情報はこのオブジェクトの子となる。階層構造で表すと「Header Object → Header Extension Object → Language List Object、Metadata Object、…etc」のように構成される。

オプション情報は他のオブジェクトと同様に、識別子となる GUID とオブジェクトサイズを持ち、Header Extension Data Size に示されたサイズ分の領域を持つ。そのため、読み取り処理は以下のような実装になる。

  1. 「Header Extension Data Size + ストリームの現在位置」を領域の終端位置として記録
  2. 終了条件を「終端位置 > ストリームの現在位置」とした do-while 内へ以降の処理を実装
  3. ストリームの現在位置をオブジェクトの始点として記録
  4. GUID (16 バイト) とオブジェクトのサイズ (8 バイト) を記録
  5. オブジェクトを読む
  6. ストリームを先頭から「オブジェクトの始点 + オブジェクトのサイズ」の位置へシークする

Language List Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid167C4346A9-EFE0-4BFC-B229-393EDE415C85
Object SizeQWORDUInt648オブジェクト全体のサイズ
Language ID Records CountWORDUInt162言語リストの総数

Header Extension Object 内のオブジェクト。言語リストを格納している。このオブジェクトは言語依存のメタデータを持つ場合に必要となる。Language ID Records Count に定義された数だけ以下のデータが続く。

名前型 (.NET)サイズ内容
Language ID LengthBYTEbyte1言語 ID のバイト数
Language IDWCHARchar*言語 ID

Language ID は UTF-16LE の NULL 終端文字列で、RFC-1766 として定義される形式の言語名が格納される。具体的な文字列としては以下を参照のこと。

ただし Windows Vista 日本語の環境で Windows Media Player 11 の拡張タグエディタを利用して日本語と英語 (米国) のメタデータを設定したところ、このリストには以下のようなデータが格納されていた。

  1. ja
  2. ja-JP
  3. en-US

日本語として ja と ja-JP が定義されている上、ja-JP は前述の Language Strings (Windows) には掲載されていない。このような場合、メタデータを操作する側としては、どのように言語を扱うのか判断が難しいところである。

Metadata Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid16C5F8CBEA-5BAF-4877-8467-AA8C44FA4CCA
Object SizeQWORDUInt648オブジェクト全体のサイズ
Description Records CountWORDUInt162メタデータの総数

Header Extension Object 内のオブジェクト。特定のストリームに属し、言語に依存しないメタデータのリストを格納している。Description Records Count に定義された数だけ以下のデータが続く。

名前型 (.NET)サイズ内容
ReservedWORDUInt162予約領域 (値は常に 0 となる)
Stream NumberWORDUInt162ストリーム番号
Name LengthWORDUInt162データ名のバイト数
Data TypeWORDUInt162データ型
Data LengthDWORDUInt324データのバイト数
NameWCHARchar2データ名
DataBYTEbyte[]*データ

データの配置がすこし異なるが、基本的な内容は Extended Content Description Object と同様。複数のストリームを持つ ASF ファイルの場合、このオブジェクトを利用することで、ストリームごとにメタデータを定義できる。

手持ちの WMA ファイルをダンプしたところ、ストリーム番号 1 に対して「IsVBR」と「 DeviceConformanceTemplate」が定義されていた。ストリーム番号は 0 から開始され、単純なオーディオならばストリーム数は単一だと思っていたので、なぜ 1 番なのか不明である。

Metadata Library Object

名前型 (.NET)サイズ内容
Object IDGUIDGuid1644231C94-9498-49D1-A141-1D134E457054
Object SizeQWORDUInt648オブジェクト全体のサイズ
Description Records CountWORDUInt162メタデータの総数

Header Extension Object 内のオブジェクト。特定のストリームに属し、言語に依存するメタデータのリストを格納している。Description Records Count に定義された数だけ以下のデータが続く。

名前型 (.NET)サイズ内容
Language List IndexWORDUInt162言語インデックス
Stream NumberWORDUInt162ストリーム番号
Name LengthWORDUInt162データ名のバイト数
Data TypeWORDUInt162データ型
Data LengthDWORDUInt324データのバイト数
NameWCHARchar2データ名
DataBYTEbyte[]*データ

データの配置がすこし異なるが、基本的な内容は Extended Content Description Object と同様。Metadata Object を拡張し、Language List Object に対応する言語インデックスが追加されている。