アニメを観る(1)

日々の仕事に役立てるため、録画サーバを自宅に作ってアニメをたくさん観ています。 多くて全部観られないので重要なところだけ観たいと考え、地デジのメタデータについて調べはじめました。 メタデータと重要なところというのがどうつなげられるかは今の段階では不明ですが、字幕を取り出すところまでやりたいです。 手元で字幕が検索できたら便利そう。

地デジをPT3等で録画したときに得られるmpeg2tsファイルの中身をみます。 ググったところ、ファイルは188バイトごとのパケットからなっていて、47というワードを探すところから始まります。 バイナリファイルをみるためにコードを書きました。

import java.io.FileInputStream

object Dumpper {
  def main(args: Array[String]) {
    val in = Some(new FileInputStream(args(0)))
    val buffer = new Array[Byte](188)

    while ({val c = in.get.read(buffer); c != -1}) {
      println(buffer.map { b =>
        "%02X".format(b & 0xFF)
      }.grouped(20).map(_.mkString(" ")).mkString("\n"))
    }

  }
}

出力

47 01 11 12 1B 3F 39 65 28 B1 CD FD 1D 04 00 29 00 2D FF D2
30 18 9E F1 F6 A5 44 69 A0 81 F9 9F DC FB 5F 2D DB 62 A9 CD
5F C9 CD A1 C8 CA A4 6D FC E5 D8 A1 AD 63 CB 3D BF A0 A0 81
F9 C0 81 F9 04 EF A2 5E E2 1E 52 37 14 10 3E 9C 00 BC 01 E0
AF 64 F9 D4 A7 4A 51 6D D0 00 FB BB A7 59 5A 29 4D BF 0B BC
B6 D1 C8 7B 7E BC 04 0F 93 F6 FB 7C 54 F9 E3 95 18 B0 F6 F0
A0 81 F5 40 08 05 FD 08 A9 78 B0 02 55 8D E8 FD 3D DD CE 0D
0C 6C EC B2 B6 F8 43 C3 DB 5B C3 DB D7 00 13 80 38 22 FC 7F
41 08 01 B7 AD 81 6D C7 17 96 EA CB 03 1B D9 CE 73 BC 0F 96
36 08 8D B3 3C 3D BA 1B
47 01 11 13 F9 65 78 7B 6C 7F E5 BD 1D 0F AD 8C 29 B5 94 3D
B7 50 F6 A6 87 B6 A3 DB A6 96 D1 5B 58 35 92 30 8D 23 10 A6
2B 63 0B 62 D5 C6 91 A2 33 3D B5 E7 B3 9E D4 9E D6 9E D4 D4
DA DA 5B 5A 7B 56 7B 5E 7B 51 ED 47 B6 63 D8 9C C6 96 CE DA
33 6D 9E 94 D4 52 9B 55 0E 6A 29 4C 0C 61 B6 62 63 66 26 01
CA 48 6D 74 38 0E 6C D7 F0 07 32 3D 91 CC 00 00 01 1E 1B 7F
23 6F E1 5B 9D 7F 0D D7 A1 CD 87 7F 0D F7 34 3A 37 8D 1B 71
AF E1 B0 50 30 DD 7D FC 36 0D FC 37 9F 40 C3 68 4D 6D CC 26
56 FB E0 21 FE DF D0 10 3F 43 E5 02 E0 02 41 78 2A 82 5F FE
B7 C1 E8 73 7D E2 02 17

47が見つかったので今日は以上です。

formatは遅いようなので書き換えました。

(参考 Javaでbyte配列を16進文字列にする時の速度比較: Repy Blog)

import java.io.FileInputStream

object Dumpper {
  def main(args: Array[String]) {
    val in = Some(new FileInputStream(args(0)))
    val buffer = new Array[Byte](188)

    while ( {
      val c = in.get.read(buffer); c != -1
    }) {
        println(buffer.grouped(20).map(_.foldLeft(new StringBuilder) { (sb, b) =>
          sb.append(Character.forDigit(b >> 4 & 0xF, 16))
          sb.append(Character.forDigit(b & 0xF, 16))
          sb.append(" ")
        }.toString()).mkString("\n"))
    }
  }
}