Windows 7 FLV and MP4 From Opera Cache

Windows 7 は本当に Aspire Timeline 1410 で十二分に快適である。
すっかり気に入って Bluetooth のマウスまで買ってしまった。
Youtube 等の Flash アクセラレーションが効くのが Ubuntu 9.04 より素敵。

Ubuntu 9.10 リリース – スラッシュドット・ジャパン

9.10 は評判悪いな、512MB 超のファイルで破損する可能性って怖すぎる。
デスクトップの Linux は明後日以降にアレが出るまで放置てか様子見。

と思っていたけどやはり Linux ばかり使っていると Windows が少し不便だ。
端末操作がどうのは文化が違うのでどうとか言わない。
だけどスクリプトで定形作業を簡単に済ませるとかをやりたいじゃない。。

ぱぇぽぃ2 ? Blog Archive ? FLV and MP4 From Opera Cache

コレができないとか、Windows で GnomeVSF を呼び出せるはずが無いし。
よし、コレと同じことができる IronPython スクリプトを作ってみよう。
IronPython は Windows SDK 等をインストールせずに .NET が使えるから素晴らしい。

ちなみに 7 及び Vista での Opera10 キャッシュは以下にある。

C:\Users\(UserName)\AppData\Local\Opera\Opera\cache\

とりあえず GnomeVFS がどうやって FLV や MPEG-4 を見分けているか調べる。
ま、FLV は先頭バイナリ 3 バイトが FLV で始まっていると解っているけど。

/usr/share/mime

を開いて video/mp4 な Mime Types を探す。
nano から開けば普通にテキストとして確認できるようだ。

mpeg4bin

んーイマイチ解らないので GHex でも MPEG-4 ファイルを開いて確認。
とにかく 5 バイト目以降に ftypisom か ftypmp42 が続いていれば MPEG-4 ってことね。
それならこうしてみよう。

#-*- coding:utf-8 -*-

"""
    opera_youtube.py
    flv and mp4 Copy from Opera Cache
"""

from System import *
from System.IO import *

FLV  = Text.Encoding.UTF8.GetBytes("FLV")
MP41 = Text.Encoding.UTF8.GetBytes("ftypisom")
MP42 = Text.Encoding.UTF8.GetBytes("ftypmp42")

# Cache Directory Name
local_dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
cache_dir = local_dir + r"\Opera\Opera\cache"

# Copy Directory is Other
copy_dir = r"C:\Users\sasakima-nao\Documents\_temp"

def array_equals(a, b):
    """
        System.Array valus Equals Check Function
    """
    result = True
    n = len(a)
    for i in range(n):
        if a[i] != b[i]:
            result = False
            break
    return result

# Get Opera Cache FileNames
files = Directory.GetFiles(cache_dir)
# roop
for f in files:
    fs = FileStream(f, FileMode.Open)
    # FLV Check
    barray = Array.CreateInstance(Byte, 3)
    fs.Read(barray, 0, 3)
    #if FLV.Equals(barray) is no!
    if array_equals(FLV, barray):
        newfile = "%s\\%s.flv" % (copy_dir, Path.GetFileName(f))
        File.Copy(f, newfile)
    # MPEG-4 Check
    fs.Seek(4, SeekOrigin.Begin)
    barray2 = Array.CreateInstance(Byte, 8)
    fs.Read(barray2, 0, 8)
    if array_equals(MP41, barray2) or array_equals(MP42, barray2):
        newfile = "%s\\%s.mp4" % (copy_dir, Path.GetFileName(f))
        File.Copy(f, newfile)
    fs.Close()

get_cache_file

たったこれだけのスクリプトで 6 時間も掛かった、やっぱり .NET は面倒くさい。
まず IronPython で System.Byte[] を作成する方法を見つけるのに苦労した。
それに System.Byte[] は内容を Equal で比較できない、かなり悩んだ。
Nautilus のように Explorer から呼び出しできれば更にイイんだが無理。

てか普通の Python で作ったほうが楽だったかな?

もっと効率が良いコードがありそうだけど動いたからいいや。
正規表現なんかを使って少し改造すれば色々と応用も効くかも。