2010年12月19日日曜日

TAEC.py

またまた某所にて
(silverfilain) どうせならMaxMBPSとMaxFSも考慮して幅・高さ・fpsから
最適なレベルを表示するのも作って欲しいぉ
(Chikuzen) じゃあ、ちょっと調べてみる
てな感じで、また書くことになった。
#!/bin/env python
# coding: utf-8
#****************************************************************************
#  TAEC(Tiny Avc Encode Consultant).py 
#                                                     written by Chikuzen
#  Reference literature:
#    Rec. ITU-T H.264 (03/2010) – Prepublished version
#    インプレス標準教科書シリーズ改訂版 H.264/AVC教科書
#           著者:(監修)大久保 榮/(編者)角野 眞也、菊池 義浩、鈴木 輝彦
#    http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
#    猫科研究所( http://www.up-cat.net/ )
#         x264(vbv-maxrate,vbv-bufsize,profile,level),H.264(Profile/Level)
#
#****************************************************************************

__version__ = '0.3.3'
import sys
import getopt
import math

def set_default():
    width   = int(1280) 
    height  = int(720)
    fpsnum  = int(30000)
    fpsden  = int(1001)
    profile = 'high'
    mode    = 'progressive'
    return [[width, height], [fpsnum, fpsden], profile, mode]

def usage():
    param = set_default()
    print "\nUsage: taec.py [options]\n"
    print "  -r, --resolution <string> :set 'width x height' ('%ix%i')" % tuple(param[0])
    print "  -f, --fps <string>        :set 'fpsnum / fpsden' ('%i/%i')" % tuple(param[1])
    print "  -p, --profile <string>    :set 'profile' ('%s')" % param[2]
    print "  -i, --interlaced          :specify interlaced mode (not specified)"
    print "  -v, --version             :display version"
    print "  -h, --help                :display this help and exit\n"

def check_res_and_fps(arg, r_or_f):
    try:
        param = [abs(int(i)) for i in arg.split('x' * r_or_f or '/')]
        if len(param) != 2:
            raise SyntaxError
    except:
        print "\nERROR : invalid %s setting." % ('resolution' * r_or_f or 'fps')
        usage()
        sys.exit()
    else:
        return param

def check_profile(profile, ipflag):
    if profile in ('baseline', 'main', 'high'):
        if profile != 'baseline' or ipflag != 'interlaced':
            return 1
        else:
            print "\nERROR : baseline cannot accept interlaced."
    print "\nERROR : invalid profile setting."
    usage()
    sys.exit()

def calc_bs(resolution, fps, ipflag):
    fstmp = [int(math.ceil(i / 16.0)) for i in resolution]
    fs = dbp = fstmp[0] * fstmp[1]
    mbps  = fs * fps[0] // fps[1]
    if ipflag == 'interlaced':
        dbp += fstmp[0] * (fstmp[1] % 2)
    return [mbps, fs, dbp]

def calc_lv(bs, ipflag, spec):
    for i in spec:
        if bs[0] <= i[1] and bs[1] <= i[2] and bs[2] <= i[3]:
            return i[0]
    if ipflag == 'interlaced':
        print "ERROR : interlaced encoding cannot be done to this video."
    print "ERROR : there is no suitable setting."
    usage()
    sys.exit()

def calc_result(profile, bitstream, line):
    vbv = [int(i * ((profile == 'high') * 1.25 or 1)) for i in line[4]]
    ref = [16 * (i > 16) or i for i in [line[3] // bitstream[2]]]
    return tuple([line[0]] + vbv + ref)

def display_result(level, profile, bitstream, spec):
    index = [i[0] for i in spec]
    try:
        for i in xrange(len(index)):
            if index[i] == level:
                line = spec[i]
                print "%5s%12i%13i%8i" % calc_result(profile, bitstream, line)
                level = index[i + 1]
    except:
        return 0

def get_spec():
#H.264/AVC spec [(level, MaxMBPs, MaxFS, MaxDbpMBs, [MaxBR, MaxCPB], ipflag]}
    return [('1.0',   1485,    99,    396, [    64,    175], 'p'),
            ('1b ',   1485,    99,    396, [   128,    350], 'p'),
            ('1.1',   3000,   396,    900, [   192,    500], 'p'),
            ('1.2',   6000,   396,   2376, [   384,   1000], 'p'),
            ('1.3',  11880,   396,   2376, [   768,   2000], 'p'),
            ('2.0',  11880,   396,   2376, [  2000,   2000], 'p'),
            ('2.1',  19800,   792,   4752, [  4000,   4000], 'i'),
            ('2.2',  20250,  1620,   8100, [  4000,   4000], 'i'),
            ('3.0',  40500,  1620,   8100, [ 10000,  10000], 'i'),
            ('3.1', 108000,  3600,  18000, [ 14000,  14000], 'i'),
            ('3.2', 216000,  5120,  20480, [ 20000,  20000], 'i'),
            ('4.0', 245760,  8192,  32768, [ 20000,  25000], 'i'),
            ('4.1', 245760,  8192,  32768, [ 50000,  62500], 'i'),
            ('4.2', 491520,  8192,  34816, [ 50000,  62500], 'p'),
            ('5.0', 589824, 22080, 110400, [135000, 135000], 'p'),
            ('5.1', 983040, 36864, 184320, [240000, 240000], 'p')]

def set_param(opts, param):
    for opt, arg in opts:
        if opt in ("-r", "--resolution"):
            param[0] = check_res_and_fps(arg, 1)
        elif opt in ("-f", "--fps"):
            param[1] = check_res_and_fps(arg, 0)
        elif opt in ("-p", "--profile"):
            param[2] = arg
        elif opt in ("-i", "--interlaced"):
            param[3] = 'interlaced'
        elif opt in ("-h", "--help"):
            usage()
            sys.exit()
        elif opt in ("-v", "--version"):
            print "tiny avc encode consultant %s" % __version__
            sys.exit()
    return param

if __name__ == '__main__':
    try:
        opts, args = getopt.getopt(sys.argv[1:], "r:f:p:ihv",
            ["resolution=","fps=","profile=","interlaced","help","version"])
    except:
        usage()
        sys.exit()

    param = set_default()

    if len(opts) > 0:
        param = set_param(opts, param)
    else:
        usage()

    check_profile(param[2], param[3])

    print
    print " resolution       : %i x %i" % tuple(param[0])
    print " fps              : %i / %i" % tuple(param[1])
    print " profile          : %s"      % param[2]
    print " encoding mode    : %s\n"    % param[3]

    bitstream = calc_bs(param[0], param[1], param[3])
    print " MBPS ... %6iMB/s" % bitstream[0]
    print " FS   ... %6iMBs"  % bitstream[1]
    print " DPB  ... %6iMBs\n"  % bitstream[2]

    if param[3] == 'interlaced':
        avcspec = [i for i in get_spec() if i[5] == 'i']
    else:
        avcspec = get_spec()

    minlv = calc_lv(bitstream, param[3], avcspec)

    print " suitable settings are ...\n"
    print " level  vbv-maxrate  vbv-bufsize  max-ref"
    print " ----------------------------------------"
    display_result(minlv, param[2], bitstream, avcspec)

#changelog
# 2010/12/19     0.1.0 公開
# 2010/12/19     0.1.1 いろいろ計算がおかしかったのを修正
# 2010/12/20     0.2.0 lambda式面白い
# 2010/12/21     0.3.0 リスト内包とgetoptの存在を知る
#    〃          0.3.1  getoptの長文形式における要引数要素に=を付けていなかったのを修正
# 2010/01/02     0.3.2  処理が重複する関数(check_resolution, check_fps)をひとつにまとめた
# 2011/03/17     0.3.3  cosmetics
# 2011/10/12     0.3.4  Fix 10L
なにせ「コンサルタント」ですから、まず役にたたないと思われます。

追記:
06_taro氏がメンテナンスを引き継いでくれたようです。
https://gist.github.com/2325004

2010年12月18日土曜日

avc_refcalc.py

某所にて
(boiled_sugar) level計算機とかないのかなー
(Chikuzen) どんな計算したいの?
(boiled_sugar) 解像度とlevelで最大ref計算
(Chikuzen) この前D_Sがそんなの書いてx264に組み込んでなかったっけ?
(boiled_sugar) 独立したプログラムが欲しい
というわけで、書いてみた。
#!/bin/env python
# coding: utf-8

#****************************************************************************
#  avc_refcalc.py 0.20
#                                   written by Chikezun
#  Reference literature:
#    インプレス標準教科書シリーズ改訂版 H.264/AVC教科書
#           著者:(監修)大久保 榮/(編者)角野 眞也、菊池 義浩、鈴木 輝彦
#    http://en.wikipedia.org/wiki/H.264/MPEG-4_AVC
#    猫科研究所(http://www.up-cat.net/FrontPage.html)
#         x264(vbv-maxrate,vbv-bufsize,profile,level),H.264(Profile/Level)
#
#****************************************************************************

import sys
import math

def usage():
    print "Usage: avc_refcalc.py [options]\n"
    print "  -r, --resolution <string> :set 'width x height' ('1280x720')"
    print "  -l, --level <string>      :set 'level' ('4.1')"
    print "  -p, --profile <string>    :set 'profile' ('high')"
    print "  -i, --interlaced          :specify interlaced mode (not specified)"
    print "  -h, --help                :display this help and exit\n"

def check_prof(pr, ip):
    for i in ['baseline', 'main', 'high']:
        if i == pr:
            if i != 'baseline' or ip != 'interlaced':
                return i
            else:
                print "ERROR : baseline cannot accept interlaced."
    print "ERROR : invalid profile setting.\n"
    usage()
    sys.exit()

def check_level(lv, ip, dic):
    lvl = lv.replace('0','').replace('.','')
    if dic.has_key(lvl):
        if ip[0] != 'i' or dic.get(lvl)[0] == 'i':
            return lvl
        else:
            print "ERROR : specified level cannot accept interlaced."
    print "ERROR : invalid level value.\n"
    usage()
    sys.exit()

def calc_mbs(w, h, ip):
    mbh = int(math.ceil(float(w) / 16))
    mbv = int(math.ceil(float(h) / 16))
    if mbv % 2 == 1 and ip == 'interlaced':
        mbv += 1
    mbs = mbh * mbv
    if mbs > 0:
        return mbs
    else:
        print "ERROR : invalid resolution setting.\n"
        usage()
        sys.exit()

def calc_vbv(lv, pr, dic):
    vbvmax = dic.get(lv)[1]
    vbvbuf = dic.get(lv)[2]
    if pr == 'high':
        return [int(vbvmax * 1.25), int(vbvbuf * 1.25)]
    else:
        return [vbvmax, vbvbuf]

def calc_maxref(lv, mbs, dic):
    ref = int(dic.get(lv)[3] / mbs)
    if ref > 16:
        ref = 16
    if ref > 0:
        return ref
    else:
        print "ERROR : resolution is too large to level.\n"
        usage()
        sys.exit()

options = sys.argv
len_opt = len(options)

#set default values
width  = 1280
height = 720
level  = '4.1'
prof   = 'high'
mode   = 'progressive'
help   = 0

#H.264/AVC level dictionary {level: [interlaced flag, MaxBR, MaxCPB, MaxDbpMbs]}
avcdic = {'1' :['p',     64,    175,    396], '1b':['p',    128,    350,    396],
          '11':['p',    192,    500,    900], '12':['p',    384,   1000,   2376],
          '13':['p',    768,   2000,   2376], '2' :['p',   2000,   2000,   2376],
          '21':['i',   4000,   4000,   4752], '22':['i',   4000,   4000,   8100],
          '3' :['i',  10000,  10000,   8100], '31':['i',  14000,  14000,  18000],
          '32':['i',  20000,  20000,  20480], '4' :['i',  20000,  25000,  32768],
          '41':['i',  50000,  62500,  32768], '42':['p',  50000,  62500,  34816],
          '5' :['p', 135000, 135000, 110400], '51':['p', 240000, 240000, 184320]}

if len_opt > 1:
    for i in range(len_opt):
        try:
            if options[i] == '-r' or options[i] == '--resolution':
                res    = options[i + 1].split('x')
                width  = int(res[0])
                height = int(res[1])
            if options[i] == '-l' or options[i] == '--level':
                level = options[i + 1]
            if options[i] == '-p' or options[i] == '--profile':
                prof = options[i + 1]
            if options[i] == '-i' or options[i] == '--interlaced':
                mode = 'interlaced'
            if options[i] == '-h' or options[i] == '--help':
                help = 1

        except:
            print "ERROR : invalid arguments\n"
            help = 1

        else:
            pass

    if help == 1:
        usage()
        sys.exit()

else:
    usage()

profile = check_prof(prof, mode)
lv_tmp  = check_level(level, mode, avcdic)
mbs     = calc_mbs(width, height, mode)
vbv     = calc_vbv(lv_tmp, profile, avcdic)
maxref  = calc_maxref(lv_tmp, mbs, avcdic)

print " resolution       : %i x %i" % (width, height)
print " level            : %s" % level
print " profile          : %s" % profile
print " mode             : %s" % mode
print " vbv-maxrate(vlc) : %i" % vbv[0]
print " vbv-bufsize(vlc) : %i" % vbv[1]
print " max ref number   : %i" % maxref

2010年11月26日金曜日

mod16

およそ動画系の話題を扱うforumであればたまに出てくる話題に"mod16"なるものがある。
そう、「動画の解像度は縦横ともに16の倍数にすべきである」ってやつですな。
これは正しいといえば正しいが、正しくないといえば正しくない。
とりあえず事実だけを言うのであれば「(mpeg系のエンコーダーは)解像度が16の倍数でないと圧縮出来ない」になるだろう。

mpeg系エンコーダー(そしてこれらの影響を受けているH.263とかVPxとか)は、まず映像を左上を原点にとって16x16のMB(マクロブロック)の集まりに分割してから動き検索やらDCT(離散コサイン変換)やらを行う。
規格によっては16x16のMBをさらに4x4に分割したり8x8とか8x16とかにも分割したりするが(SMB:サブマクロブロック)、とりあえず一回16x16で分割しないことには何も始まらない。
さあ、16x16の集まりに分割するのだ。

でも、たとえば642x484なんていう解像度を圧縮する場合はどうすればいいのよ?
右端の2x16とか下端の16x4とか一番右下の2x4は処理できないじゃん。
困るよ、おい。

これを何とかするため、16の倍数になっていないものの場合はエンコーダーの内部でpadding(パディング)なるものが行われるようになっている。
paddingを英和辞典で引けば「詰め物」とかそういった感じの意味で載っているだろう。
つまり、本来存在しない映像をを付け足して、16の倍数になるようにするわけだ。642x484であれば、映像の右端に幅14ピクセル、下端に幅12ピクセルのダミーをくっつけて656x496にしてしまう。
よーし、これで圧縮にとりかかれますな。

ところでこのpaddingされる映像ってどんなものなのか、知ってます?
黒ベタ? 灰色ベタ?
正解は右端および下端の縁の色です。
つまり、こんな感じ。
なんでこんな絵の具が垂れたみたいな感じに?
それは、このようにpaddingを行うのが一番、本来の映像に影響を与えずに圧縮できるから。
単色ベタ塗りは色々とまずいことがあるのですよ。色々ね。
もし自分でこのようなpaddingをしてみたければ、AviUtlなら「"縁塗りつぶし"を"縁の色で塗る"にチェックを入れて値をマイナスに設定」、AviSynthなら「"AddBorders"と"BorderControl"または"FillMargins"を併用」で可能です。
#padding.avs
AVISource("642x484.avi")
AddBorders(0,0,14,12)

#BorderControlの場合
LoadPlugin("BorderControl.dll")
BorderControl(XRS=14,YBS=12)

#FillMarginsの場合
LoadPlugin("FillMargins.dll")
FillMargins(0,0,14,12)

さて、これで圧縮は出来たけど、いざ動画を再生するときに、こんな変な部分まで表示されたら、それはそれで嫌ではないかな?
本来存在しないはずのものまで見えるのってうざいと思うよっつーかうざいんだよボケ。心霊写真じゃあるまいし。
そういう文句が出ることは分かりきっているので、paddingされたデータはまともなデコーダーならデコード時にはcropしてしまうようになっています。つまりさっきくっつけた右端14ピクセルと下端12ピクセルは表示されず、もとの642x484として表示される。
やれやれ、これにて一件落着。

でもね。
影響の少ないダミーによる水増しとはいえ、映像は642x484ではなく656x496の状態で圧縮されてるわけですよ。
解像度が大きければ、その分ファイルサイズも当然大きくなります。
もし640x480だったならばpaddingも必要なく、ファイルサイズも小さくなるだろうに…。
表示されない屑データのために膨れるなんて、そんな贅肉見苦しいんだよ、メタボだよ、ああむかつくこんちくしょう、うーんと、えーっと、そもそも水平2ピクセル、垂直4ピクセルくらいなら、削っちゃっても問題なくね?フフフそうだよそれくらい削っても気にならないだろ普通は、っつーかむしろ気にするやつのほうがおかしいだろ頭悪いだろキ○○イだろフヒヒヒヒええい削ってしまえバカヤローウギャー…orz

というわけで、やたら圧縮率にこだわる人であれば16の倍数になるようにするでしょう。
これが「動画の解像度は縦横ともに16の倍数にするべきである」の正体です。
まあ、もともと16の倍数になるように絵が作られていれば、こんな葛藤も起こらないわけで、それにこしたことはないんですが…はぁ(ため息)。

ちなみにたまに「mod16に出来ないならば、次善の策としてmod8(8の倍数)にするべきである」という人がいますが、これは迷信の類です。
mod16でなければpaddingは起こります。
そしてpaddingされるデータ量は、解像度を16で割った余りが16に近ければ近いほど小さくなります。
644x484、648x488、652x492という3種類の映像があったとすれば、ファイルサイズに対してpadding分のデータ量の占める割合は、644x484 > 648x488 > 652x492です。
つまりpaddingは少ないほどよいってことですね。
「652x492か。縦横12ずつ削るってのはさすがに嫌だよなあ…でも縦横4ずつくらいならそれほど嫌じゃないぞ。よし、648x488でmod8にしよう」
「それはつまり、大事な映像をわざわざ削った挙句に無駄になるデータを増やそうってことですかそーですか…手前の馬鹿さ加減にゃあ父ちゃん情けなくって涙出てくらぁ!!」(CV:東野英心)

あと、「mod16じゃないと、映像の端がゆがむ」という人もいますが、これもどうなんでしょうかね。
よっぽどひどいエンコーダーでもない限り、前述したような適切なpaddingを行っていれば、まず人間の目ではソースと並べて見比べてもなかなか視認出来るものではないはずなんですが。

2010年10月23日土曜日

Console2

XhmikosR氏のファイル置き場を眺めていたら、/toolsにconsole_2.00_Beta_b146というのがあった。
なんだろうと思ってググって見たら、sourceforgeの本家のページが見つかったので、最新のzipをDLして、ヘルプを読んでみた。
Console is a Windows console window enhancement.
(consoleはWindowsのコンソールウィンドウの拡張用ツールです)
Console is simply a nice-looking front end for a shell of your choice (cmd.exe, 4NT, bash, etc.) Other command-line utilities can also be used as 'shells' by Console.
(単純に言ってしまえば、consoleはあなたの選んだshell(cmd.exeとかbashとか)のためのかっこいいフロントエンドであり、他のCLIユーティリティでもshell同様に使えます)
どうやら複数のCLI端末のウィンドウをタブで管理できたり、コピペ操作がテキストエディタぽくマウスで出来たり、フォントを変えたり、背景を個別に設定できたりするらしい。
端末がタブで扱えるのは大変うれしいので、早速使ってみることにした。

1. とりあえずzipを解凍し、適当なところに置く。
2. 次にヘルプ(.chm)を開き、軽く目を通す。
3. console.exeをダブルクリック。
4. ヘルプのSetting -> Language settingを読みながら、フォントの設定を行う。
5. その他設定を行う。

ためしに「console2 日本語」で検索したら、4のあたりの情報がいくつか出てきた。ヘルプを読むのは大事よね。

とりあえずタブの設定は3種類作ってみた。
ひとつはcmd.exe用
Shellとして、C:\Windows\System32\cmd.exeを登録し、Startup dirはC:\にした。
2つ目はmsysのbash用。
これは
@echo off
G:\msys\bin\sh.exe --login -i
だけ書いたbatを用意して、それをShellとして登録する。
3つ目はCygwinのbash用。
これもmsysと同様にbatを登録するだけ。

これでやることはとりあえず終了。
いざ使ってみると…これはイイ!
新しい端末をショートカットキー一発でタブで開けて、切り替えもラクラク。
特にノートPCとか狭い画面で複数の端末を操作する必要がある人にはお奨めですね。
あとは背景とかも設定できるのでいろいろいじってみるのもいいかも。

2010年10月22日金曜日

GPACが

mingw / mingw-w64共に再びビルドできるようになったみたい。(SVN rev2183時点)

でも
./configure --cross-prefix=x86_64-w64-mingw32-
ってやったら
C   compiler: x86_64-w64-mingw32-gcc
C++ compiler: g++
と表示されるあたり、次に壊れるのも早そう…つーか、まだ直ってはいないといったほうがいいのかも。

2010年10月19日火曜日

AvsPのブックマーク位置をずらすマクロ

AvsP(mod)でTrimSelectionを使ってCMカットすると、各パートの終端フレームにブックマークが打たれた状態になる。
これが結構曲者で、例えば動画にチャプターを打つ場合、チャプターポイントは各パートの先頭フレームに来るように打つものであるが、ブックマークが打たれている場所が各パートの終端だと、そのまま"Bookmarks to Chapter.py"を使うわけにいかない。
各パートの終端フレームの次のフレームは当然、次のパートの先頭フレームになるわけだが、この1フレームのずれを修正するために、いちいちブックマークを消して、1フレーム移動して、もう一度ブックマークを打ち直すのはめんどくさい、なんとかならんもんかいな?

と思ったので、これもマクロで何とかしてみようというのが今回のお話。
-----------------------------------------------------------------------------
既存のブックマークすべてを1フレーム右(未来方向)にずらすだけなら簡単である。
#Shift Bookmarks right+1.py
before=avsp.GetBookmarkList()
if len(before):
    after = [i + 1 for i in before]
    after.sort()
    avsp.SetBookmark(before) #ブックマークは二重に打つと消える。
    avsp.SetBookmark(after)
しかし、これをそのまま使うと、もし最終フレームにブックマークが打たれていた場合、そのブックマークは範囲外に飛び出して消えてしまう。
それに、すでにブックマークを1フレームずらし終えたのに、何らかの操作ミスでもう一回ずらしてしまったらどうしよう? マクロを使った場合、undoは効かないよ?
はたまた、例えばブックマークを打ち終え、チャプターを出力する段になったところでトリムのし残しを発見してしまった場合は? その部分が全部で10個打ったブックマークの2番目と3番目の間に30フレームあったりしたら、1番目と2番目は打ち直すとしても、3番目以降のためにこれを30回実行するの?
ずらすフレーム数を任意に指定できるようにしたとして、全部で10000フレームしかないクリップに対して、桁を間違えて100000なんて指定してしまったら?
などと不測の事態についていろいろ考えていたら、最後にはこうなっていた。
#Shift Bookmarks.py
def newBM(present, shift, last):
    if 0 <= present + shift <= last:
        return present + shift
    elif present + shift > last:
        return newBM(present, shift - last - 1, last)
    else:
        return newBM(present, shift + last + 1, last)

input = avsp.GetTextEntry('Input an integer value',default='1')
shift = int(input)
before = avsp.GetBookmarkList()
if shift and len(before):
    framecount = avsp.GetVideoFramecount() 
    after = [newBM(old, shift, framecount - 1) for old in before]
    after.sort()
    avsp.SetBookmark(before)
    avsp.SetBookmark(after)
うーむ、再帰なんて初めて使ったよ。
-------------------------------------------------------------------------
使い方:
ブックマークが打たれた状態でマクロを実行するとダイアログが現れるので、数値を入力する。デフォルトは1。
正ならば右(未来方向)、負ならば左(過去方向)にすべてのブックマークが指定した数値分だけ移動する。
最終フレーム + 1 = 0番フレーム(0番フレーム - 1 = 最終フレーム)として循環処理される。
数値以外の文字列を入力した場合はエラーとなり何もしない。小数点以下は切り捨て。
操作を取り消したい場合はもう一度マクロを実行し、事前の指定値の反数を入力すること。

2010年10月18日月曜日

CM検出マクロ for AvsP

この前のSCx264 to Bookmarksは、少々時間がかかり過ぎるので、CMカットにはいまいち不向きなようだった。
もっと短時間で可能な方法はないものだろうか?
しばし悩んだ末、そういえばAviUtlにもなにやらCMカット用のシーンチェンジ検出プラグインがあると小耳に挟んだことを思い出したので、見てみることにした。
「チャプター編集 for AviUtl by ぽむ + 無音&シーンチェンジ検索機能 by ru」
読み込んでいる動画の音声トラックをスキャンし、無音連続部分を検出して、その「開始部分」にチャプターを打ちます。
その後チャプターへのシーク時に無音部分内のシーンチェンジを検出し、その位置へ移動できます。
うーむ、なるほど…。
シーンチェンジ検出を無音部分に限定すれば高速化が可能かも!?
-------------------------------------------------------------------------
では早速やってみましょう。

まずサンプルクリップを用意します。
今回はMPEG2-TS、音声AACで再生時間31分、総フレーム数55749フレームの地デジソース(1440x1080)です。
#sample.avs
MPEG2Source("sample.d2v")
AudioDub(last, WAVSource("sample.wav"))

#とりあえず普通に再生できる音声(FAWとかの偽装WAVはこの場合は駄目)でディレイ補正処理を済ませておく。
#今回はソースが地デジTSなので、とりあえず
#[DGIndexでdemuxしたaac -> FAWを2回通してディレイ処理済のaac -> FAADでPCM.wavに変換]
#したものを使った。
#処理終了後に差し替えれば、偽装WAVでも大丈夫。
#もしaacを直読みしたい場合は、BassAudioでも使ってDelayAudio()で補正することになる。
このクリップの無音部分を検出しなければならんわけですが、使えそうな道具は…MinMaxAudioかな?
AudioMax(0)が-100dbよりも低ければ、そのフレームは無音と判定することにしましょう(テキトー)。
#sample.avs
MPEG2Source("sample.d2v")
AudioDub(last, WAVSource("sample.wav"))

LoadPlugin("MinMaxAudio.dll")
AudioDub(BlankClip(last, width=160, height=80), last)
#スピードアップのため、クリップを映像160x80で真っ黒、音声はそのままに変換する
WriteFileIf("silence.log", "AudioMax(0) < -100", "current_frame")
#該当フレームのフレーム番号をテキストに書き出す
このavsをVirtuaDubの"Run Video Analysis pass"にかけてやると、約1250fpsくらいのスピードでsilence.logが生成されます。
結果を見てみると、どうやら無音のフレームは、各CM及び本編の切れ目あたりにだいたい10~30フレーム入るみたいです。
具体的には全55749フレームのうち、41-53、475-504、926-954、1376-1402、1825-1837、2289-2302、2725-2738、9077-9092、9990-10003、10874-10905、26915-26923、27373-27385、27808-27821、28707-28738、46494-46507、49179-49206、49628-49656、50078-50103、50525-50553、50975-50987、51439-51451、51874-51902、52783-52788、53043-53101、53523-53535、54422-54434、54886-54898、55320-55350、55735-55748の全29箇所561フレームが無音(-100db未満)です。

そこでsample.avsをこうしてやり
#sample.avs
MPEG2Source("sample.d2v")
AudioDub(last, WAVSource("sample.wav"))

PointResize(last.width / 4, last.height / 4)
#シーンチェンジ検出には320x270程度で十分なのでPointResizeでリサイズ
FreezeFrame(0,41,41)
FreezeFrame(53,475,475)
FreezeFrame(504,926,926)
#途中24行省略
FreezeFrame(54898,55320,55320)
FreezeFrame(55350,55735,55735)
FreezeFrame(55748,0, 0)

#AviSynthの仕様ではFreezeFrameでコピーされるフレームはデコードされないので、
#MPEG2Sourceのボトルネックが解消されるはず
このavsをこの前のSCx264 to Bookmarks.pyにかけてやると、x264はなんと約2200fpsという想像を絶するスピードでシーンチェンジ検出を終え、ブックマークを打ち終わりました。
あとはFreezeFrameの行を消してやれば…YATTA!!
-----------------------------------------------------------------------------
てなことがありまして、これらの操作を自動で行うべく書いたAvsPマクロが以下の通りです。
使い方は、とりあえずAudioDubまで書いたavsを用意して、マクロを実行するだけです。
FAW使用者は、実行後に音声を偽装WAVに差し替えればいいです。ちょっと書き換えれば、そこらへんも自動化できるでしょう
前回約10分かかってたのが、約1分まで縮まりました(on Q9450定格)。
著作権は…発生するのかどうか知りませんが、もし発生するのであればGPLv3です(なんとなく)。
つーか、Pythonスクリプトですから、バイナリと違って秘密にはしようがないと思うけど…。

EDIT:
よく考えたらavs2aviのnull出力とx264の--preset ultrafast -o nul ではスピードは大して変わらないので(っていうか、今度はMinMaxAudioがボトルネックになっているので)、avs2aviをx264に変更。
avs2aviは要らなくしました。
#Silent_Scenechanges to Boolmarks.py for AvsP
#Author : Chikuzen (http://csbarn.blogspot.com/)
#Requiament: MinMaxAudio.dll, x264.exe, (avs2avi.exe)

#--------------preparation----------------------------------
import os

avsname = avsp.SaveScript()
script_org = avsp.GetText()

#あらかじめ各ツールのパスを設定しておくこと
#ファイルパスを変数に入れる際、前にrをつけるのはPythonのお約束
mmaudio = r'C:\AviSynth 2.5\Plugins_x86\MinMaxAudio.dll'
x264cli = r'G:\Enctools\x264_x86.exe'
#avs2avi = r'G:\Enctools\avs2avi.exe'
if mmaudio and x264cli and avsname and script_org:
#if mmaudio and x264cli and avs2avi and avsname and script_org:
#--------------------------------------------------------------
    #Search Silence
    logfile_si = avsname + '_silence.log'
    text1 = '\nLoadPlugin("%s")' % mmaudio
    text1 += '\nAudioDub(BlankClip(last, width = 160, height = 120), last)'
    text1 += '\nWriteFileIf("%s", "AudioMax(0) < -100", "current_frame", append = false)' % logfile_si
    avsp.InsertText(text1, pos = -1, index = None)
    avsp.SaveScript()
    os.system('%s %s --preset ultrafast --crf 51 -I infinite -o nul' % (x264cli, avsname))
    #os.system('%s %s -c null -o n' % (avs2avi, avsname))

    #silence_log to freezeframelines
    avsp.SetText(script_org)
    sifile=open(logfile_si)
    lines_si=sifile.readlines()
    sifile.close()
    text2='\nPointResize(last.width / 4, last.height / 4)'
    if len(lines_si):
        x = 0
        for line_si in lines_si:
            log_si = int(line_si.strip())
            if x != log_si - 1:
                text2 += '\nFreezeFrame(%i, %i, %i)' % (x, log_si, log_si)
                x = log_si
            else:
                x += 1
        text2 += '\nFreezeFrame(%i, %i, %i)\n' % (int(lines_si[-1].strip()), 0, 0)
    avsp.InsertText(text2, pos = -1, index = None)
    avsp.SaveScript()
    
    #SCx264
    logfile_sc = avsname + '_scenechange.log'
    opts = '--preset ultrafast --crf 30 -I infinite -i 1 --scenecut 50 -o nul'
    os.system('%s %s -p 1 --stats %s %s' % (x264cli, avsname, logfile_sc, opts))
    avsp.SetText(script_org)
    avsp.SaveScript()

    #scenechange_log to bookmarks
    scfile = open(logfile_sc)
    lines_sc = scfile.readlines()
    scfile.close()
    bookmarks = []
    for line_sc in lines_sc:
        log_sc = line_sc.split(' ')
        if log_sc[2] == 'type:I':
            bmpoint = int(log_sc[0].lstrip('in:'))
            bookmarks.append(bmpoint)
    avsp.SetBookmark(bookmarks)

2010年10月16日土曜日

Syntax Highlighting

Henry氏の薦めもあって、このブログにSyntax Highlightingを入れてみた。

初めはこちらのwidgetを入れてみたのだが、いざ適用してみるとFirefox3.6やIE8だとちゃんとHighlightingしてくれない。
してくれないだけならまだいいが、ついでに"can't find brush for:python"なんていうのまで表示される。
それも適用したコード全てに対して表示されるので、例えばコードが10個あれば10回、100個あれば100回表示されるという始末である。
Chromeなら大丈夫みたいだけど、みんながみんなChromeを使っているわけではないだろうから(そもそも自分自身、メインで使っているのはFirefoxである)すぐにやめた。

で、結局こちらのほうを見ながら、テンプレートの編集なんてことをやる羽目になったわけだが、いざ導入してみると、これはこれで対応している言語が少ない、少ない、少なすぎる。

AviSynthがないのは仕方ない(つーかavsをHighlightingできるところなんて、世界広しと言えどもCCCPastebinくらいのものだろう。流石はMeWikiのメンテナーcheckers氏がやってるだけのことはある)けど、shellに対応してないってのは痛いなぁ…。

まあ、ないものは仕方がないので他で代用することにした。
とりあえずAviSynthはPythonでいいだろう。なんか似てるし。
Shellはどうしようとなやんだが、これも結局Pythonにした。特に問題はないみたいだし。

やっぱりCSSとかも勉強したほうがいいのかな。

SCx264 to Bookmarks for AvsP

またまたAvsPマクロネタ。

さて、AviSynthのプラグインにはいろいろと毛色の変わったものがありますが、そんな中にSClavcSCXvidというものがあります。
オリジナルのSClavcはx264のペンギン様ことLoren Merritt氏作、SCXvidの作者は#darkholdのいかつい人、MyrsloikことFredrik Mellbin氏であります。(以前一度、JEEB氏に写真を見せてもらったことがあるのですが、Myrsloik氏はやたら人相の怖い太っちょでした。一方、一緒に写ってたTheFluff氏は小柄で柔和そうな感じで、普段の言動から受ける印象とあまりにも違いすぎるので、思わず大笑いしたものです)

で、これらが何のためにあるかというと、要するにffmpegやXvidの2pass用のログを利用して、クリップ内のシーンチェンジの場所とかを割り出して色々利用しようというものらしい。
なんで「らしい」かといえば、使い方がよくわからないから。
とりあえずavs書いてVirtualDubに食わせて"Run Video Analysis pass"を走らせるなりすれば、2pass用のlogファイルが作られるわけですが、そこから先がどうしたものやら…。
AviSynth.infoによれば、「元々は、Yattaにおいて、libavcodecのシーンチェンジ・メトリクスの利用を可能するために書かれた。」とありますが、Yattaってねぇ…あれの使い方がわかる日本人なんているのかしら?
7月ごろにJEEB氏に「#yattaでmenter氏が初心者講習会を開くので来ないか?」と誘われたのでROMってみましたが、何をしゃべってるのかさっぱりわかりませんでした。(そもそも知りたかったのは理論やテクニックではなく、操作方法そのものなのですが、そこらへんはやってくれなかったし…orz)

まあ、Yattaの使い方は今もさっぱりわかりませんが、2pass用logからシーンチェンジ検出というのは理解できます。
そこでふと思ったことが「それならx264のlogファイル使ったほうがよくね? lavcのmpeg4やXvidよりもlog出力速いじゃん」。
で、こんなのを書いてみた。
#SCx264 to bookmarks.py
frames = avsp.GetVideoFramecount()
logfilename = avsp.GetFilename(title='Select x264_logfile')

if logfilename:
    logfile = open(logfilename)
    logs = logfile.readlines()
    logfile.close()
    if len(logs) == frames + 1:
        bookmarks = []
        for logline in logs:
            log = logline.split(' ')
            if log[2] == 'type:I':
                bmpoint = int(log[0].lstrip('in:'))
                bookmarks.append(bmpoint)
        avsp.SetBookmark(bookmarks)
    else:
        avsp.MsgBox('This log is not corresponding to the number of frames of current clip.',title='Warning')

あらかじめx264.exeで --pass 1 をつけてエンコしたlogから、IDRフレームと判定されたフレームにブックマークを自動で打つマクロである。(またブックマークか…)
とりあえずシーンチェンジを検出して、ちゃんとIDRと判定されるようなオプションにしていれば、ほぼ100%検出できるはずである。

さて、ただlog読んでブックマーク打つだけでは面白くないので、さらに発展させてみる。
#SCx264 to bookmarks AUTO.py
import os
avsname = avsp.SaveScript()
#使用するx264.exeを毎回指定したい場合はこちら
#exe = avsp.GetFilename(title = 'Specify x264.exe used.')
#x264.exeのパスを固定したい場合は、こちらにフルパスで書いておく
exe = r'G:\Enctools\x264_x86.exe'

if avsname and exe:
    x264opt = '--preset ultrafast --crf 30 -p 1 -I infinite -i 1'
    thresh = '--scenecut 50'
    logfilename = avsname + '.sc_log'
    os.system('%s %s %s %s --stats %s -o nul' % (exe, avsname, x264opt, thresh, logfilename))

    logfile = open(logfilename)
    logs = logfile.readlines()
    logfile.close()
    bookmarks = []
    for logline in logs:
        log = logline.split(' ')
        if log[2] == 'type:I':
            bmpoint = int(log[0].lstrip('in:'))
            bookmarks.append(bmpoint)
    avsp.SetBookmark(bookmarks)

log出力も一緒にやるようにしてみた。

ううむ、これをどう使えばいいのだろうか?

例えばMPEG2Source("hogehoge.d2v")だけのavsの状態でこれを実行するとCMカットは楽になる。
なぜって、ただブックマーク移動していくだけで本編とCMの切れ目を確実にシークできるから。
AvsP初期装備のTrimEditorと併用すれば、ほとんどストレスなくCMカットできるはず(ただし、TrimEditorでTrimを実行する際は、ブックマークをすべてクリアしてからにすること。これを忘れるとプレビューの更新で随分時間を食うことになります)。
x264は--preset ultrafastならものすごく高速です。自分のそろそろ時代遅れなQ9450でも、1440x1080
のMPEG2-TSを90fps~100fpsで処理します。つーかMPEG2Sourceがボトルネックになっているので、本当はもっと速いです。2本同時にlog出力したりするといいかもしれません。

なお、「30分のTSだとlog出力だけで10分かかるじゃねえか、それだけあればCMカットなんか終わってるよ」とかいう意見は無視します…orz

2010年10月15日金曜日

分割結合マクロ for AvsP

前回のTrimEditorは、いざ使ってみるとメリットはそれほどなかったような気もするけど、まあ、マクロの練習にはなった。
さて、今回もBookmarkを使ったマクロを書いてみる。
#Divide and Concatenate.py
bookmarks=avsp.GetBookmarkList()
if bookmarks:
    bookmarks.sort()
    start, trim, cat = 0, "", "\n"
    for i in xrange(len(bookmarks)):
        trim += "\nV%02i = last.Trim(%i, %i)" % (i, start, bookmarks[i] - 1)
        cat += "V%02i ++ " % i
        start = bookmarks[i]
    i += 1
    trim += "\nV%02i = last.Trim(%i, 0)" % (i, start) 
    cat += "V%02i\n" % i
    avsp.InsertText(trim + cat, pos=None, index=None)
例えば
AVISource("hoge.avi")
AudioDub(Last, WAVSource("hoge.wav"))
なんていうavsがあったとして、1234,5678,9012フレームにブックマークを打ってからこのマクロを実行すると
AVISource("hoge.avi")
V01 = Last.Trim(0, 1233)
V02 = Last.Trim(1234, 5677)
V03 = Last.Trim(5678, 9011)
V04 = Last.Trim(9012, 0)
V01 + V02 + V03 + V04
AudioDub(Last, WAVSource("hoge.wav"))
というように、いったんブックマークの位置で分割して、最後に結合するスクリプトが挿入される(挿入位置はカーソルの位置)。
なににこんなものを使うかといえば、
AVISource("hoge.avi")
V01 = Last.Trim(0, 999).Sharpen(1.0)
V02 = Last.Trim(1000, 1999).Blur(1.0)
V03 = Last.Trim(2000, 2999).FlipVertical()
V04 = Last.Trim(3000, 0).FlipHorizontal()
V01 + V02 + V03 + V04
AudioDub(Last, WAVSource("hoge.wav"))
てな感じでFilterRangeのかわりにするとか、はたまたEasyVFRとか使う人には便利かもしれない。

2010年10月13日水曜日

俺様TrimEditor for AvsP

スクリプトなんて簡単なBash scriptとAviSynth scriptしか書けない私ですが、最近はほんの少しだけPythonをいじるようになりました。
なんでPythonかといえば、AvsP(AviSynth script editor)がPythonで書かれていて、マクロもPythonで書かないといけないから。

さて、本日のお題はTrimEditor。
AvsPには始めからTrimEditorが付いていますが、これが自分にはどうも使いにくい。
まずHomeを押すと出現するダイアログがウザい。
ある範囲を選択(削除)するごとにTrim(a,b)を1行挿入するので、Trimし終わったころには、それだけで7,8行のスクリプトになってしまうのもウザい。
というわけで、自分用のTrimEditorをでっち上げます。
#Bookmarks to TrimLine.py
bookmarks = avsp.GetBookmarkList()
num = len(bookmarks)
if num % 2 == 0 and num:
    bookmarks.sort()
    text = ''
    for i in range(0, num, 2):
        trimrange = bookmarks[i:i+2]
        cattext = '++Trim( %i, %i)' % (trimrange[0], trimrange[1])
        text += cattext
    avsp.InsertText(text.lstrip('++') + '\n', pos=None, index=None)
else:
    avsp.MsgBox('The number of bookmarks is odd (or zero).', title='Warning')
使い方:
ブックマーク(Ctrl+B)を適当にガンガン打って、マクロ実行。
2つのブックマークにはさまれた部位を残すスクリプトが、カーソル位置に1行で挿入されます。
例)ブックマークを1000,2000,3000,4000,5000,6000フレームに打って実行したら Trim(1000,2000)++Trim(3000,4000)++Trim(5000,6000) となる
なお、10行目のpos=Noneをpos=-1に書き換えると、スクリプトの最後に挿入位置が変更されます。

2010年10月3日日曜日

regression test

#ffmpeg-develでDark Shikari氏のregression test用スクリプトを見つけた。
#!/bin/sh
vid=videos/foreman_cif.y4m
for tune in film zerolatency
do for m in "--intra-refresh" ""
  do for j in "" "--no-cabac"
    do for i in "--keyint 250 --slice-max-size 1000" "--no-weightb --interlaced"
      do for p in ultrafast superfast veryfast faster fast medium slow slower
        do ./x264 $vid --quiet --preset $p --tune $tune $i $j $m -o test.h264 --dump-yuv test.yuv
           ~/x264/JM/bin/ldecod.exe -i test.h264 > /dev/null
           cmp test.yuv test_dec.yuv
        done
      done
    done
  done
done
えーと、2x2x2x2x8=128パターンか。

2010年9月27日月曜日

JMェ

そーいえば、UbuntuにはJM reference入れてなかったなー、と思い出し、ビルドすることにした。

wget http://iphome.hhi.de/suehring/tml/download/jm17.2.zip
unzip ./jm17.2.zip
cd ./JM
chmod +x ./unixprep.sh && ./uniexprep.sh
make

/JM/binにldecod.exeとlencod.exeの出来上がり!…って、.exe?

どうやらJMの中の人たちにとって、UNIXとはCygwinのことらしいです。

2010年9月20日月曜日

Spamming Dutchman

x264.nlが配布しているx264.exe(for 32bit Windows)のr1722でmp4出力が出来なかった件について。

#L-SMASH@freenodeにて
2010年9月18日
00:15 (golgol7777) seems GPAC guys commited the patch today.
00:16 (jarod) what patch?
00:16 (jarod) something good?
00:17 (golgol7777) this patch@r2043 https://sourceforge.net/tracker/?func=detail&aid=3058368&group_id=84101&atid=571738
00:18 (golgol7777) but mingw build is still broken...
00:21 (Chikuzen) jarod: GPAC broke completely as it is impossible to compile with mingw after all.
00:21 (Chikuzen) you cannot update GPAC any longer.
00:22 (jarod) ah ok, well thats their problem then
00:22 (jarod) my script will keep using latest working libs it has
00:23 (jarod) and when x264 no longer thinks it should use gpac, we shall move along

2010年9月19日
20:55 (Chikuzen) jarod: https://sourceforge.net/projects/gpac/forums/forum/287547/topic/3857579
23:01 (jarod) Chikuzen
23:01 (jarod) - gpac revision 2053 done
23:02 (jarod) but i heard its making x264 buggy
23:02 (jarod) with .mp4 output
23:03 (Chikuzen) indeed
23:04 (jarod) but it does compile (and create the lib)
23:07 (Chikuzen) realy? I challenged and got failed for about three hours ago.
23:10 (Chikuzen) if you are good in build at r2053 , then use it
23:10 (Chikuzen) r2053 has finished the bug fix
23:11 (Chikuzen) r2053 includes wewk's patch
23:34 (jarod) but cruncher reports x264 failing with .mp4 output
23:44 (Chikuzen) x264_x86_r1722_nl.exe --help
23:45 (Chikuzen) .mp4 -> MP4 if compiled with GPAC support (no)
23:46 (Chikuzen) your binary has not linked libgpac_static.a
23:47 (jarod) lol ok
23:47 (jarod) that explains
23:50 (jarod) but then x264 fails to link but continues compiling
23:50 (jarod) lemme test
23:52 (jarod) Warning: gpac is too old, update to 2007-06-21 UTC or later
23:52 (jarod) gpac: no
23:52 (jarod) hihi
01:05 (jarod) ok
01:05 (jarod) gpac 2039 is now being used
01:05 (jarod) better something then nothing :)

「GPACの更新はしないように」って、ちゃんと釘を刺しといたんだけど…orz
golgol氏曰く「 libgpac_static.a は ar で固めてるだけなんだから、例えビルドに失敗してても.aが生成されるのは当たり前」だそうである。

jarod氏がGPAC公式のsvnを使わずgolgol氏のgitレポを使えばすべては解決する。
golgol氏のレポは色々なバグフィックスが行われていて、最新のmingwでも問題なくビルドできるようになっているから。
しかし、このオランダ人はとにかくplainビルドにこだわり、自分が配布するバイナリには絶対にパッチをあてたりしないのである。
確かにx264自体はplainにこだわる必要があるだろう。彼のバイナリはx264のバグ検出用という重要な側面がある。
でも、バグがあるにもかかわらず半ば放置状態のGPACまでplainにこだわる必要はあるんかいな?

ちなみに、こんな人がビルドしてるx264.nlのバイナリですが、信頼性は(基本的には)高いです。
なんせ周りにいる人たち(主にkemuri_9氏)が面倒見てますから。
どこのビルドのx264を使えばいいのかわからない人は、x264.nlのバイナリを使ってください。

2010年9月10日金曜日

ふわふわさん

某月某日某所にて
19:23 (Chikuzen) "Reminder: only 152 days left"ってなんのことだろうと思ったら
19:23 (JEEB) wwww
19:24 (Chikuzen) 「空の境界」のBD発売までのカウントダウンかよ
19:24 (JEEB) TheFluff氏が予約したしねぇw
19:26 (TheFluff) kara no kyoukai is important ok

Anime makes you stupidってのは、自分のことなのだな…

2010年9月7日火曜日

x264_L-SMASHのビルド

以前書いたlavf/ffmsつきx264のビルドに関する記事を数ヶ月ぶりに読み返してみた。
なんというか冷や汗ものである。
このまま放置しておくのは色々危険そうな気がするので、もう一度書いておく。
でも、普通のx264では面白くないので、今回は現在開発進行中のx264_L-SMASHのビルドにする。

用意するもの
autoconf/libtoolが使えるmsys環境、mingw、pkg-config、wget、subversion、msysgit、nasm、yasm、pthread-w32、zlib、bzip2
あきれるほどマメなMPC-HC開発者XhmikosR氏がこちらで配布しているセットを使えば、msysgit以外すべて揃っているのでとても楽である。 (説明の手間が省けるので)
あとは自分の環境に合わせて/etc/fstabと/etc/profileをいじり、別にインストールしたmsysgitのgit.exeにPATHを通すなりすればよい。

1.x264_L-SMASH_clone.sh
x264_L-SMASHはこちらで公開されているが、そのままgit cloneすると、バイナリのバージョン表記がおかしくなるので、ここにあるx264_L-SMASH_clone.shを使ってcloneする。
DLしたら、この.shを$HOMEに置いておくこと。
もしくは
wget http://up-cat.net/wiki.cgi?action=ATTACH&page=L-SMASH&file=x264_L-SMASH_clone.sh -O $HOME/x264_L-SMASH_clone.sh
を、スクリプトに追加する。

2.ビルド
あとは以下のスクリプトを実行すればおしまい。現状で使用できるaudio用codecを全部リンクしたx264.exeが出来る。
変数の内容は各自で自分の環境にあわせていじるように。
QuickTime SDKをインストールしていない場合や、libfaacをリンクさせたくない場合は、適当にコメントアウトすること。
#!/bin/sh
#Preparation
WORK=$HOME/LSMASH
PREF32=/mingw/i686-pc-mingw32
PREF64=/mingw/x86_64-w64-mingw32
HOST64=x86_64-w64-mingw32
CROSS64=x86_64-w64-mingw32-
QTSDK=/g/quicktime_sdk

cp /bin/pkg-config.exe /bin/${CROSS64}-pkg-config.exe

mkdir $WORK/src

#download src
cd $WORK/src
wget\
    http://downloads.sourceforge.net/project/lame/lame/3.98.4/lame-3.98.4.tar.gz\
    http://downloads.sourceforge.net/faac/faac-1.28.tar.bz2\
    http://downloads.sourceforge.net/project/opencore-amr/opencore-amr/0.1.2/opencore-amr-0.1.2.tar.gz
git clone git://github.com/mstorsjo/vo-aacenc.git
git clone git://github.com/mstorsjo/vo-amrwbenc.git
git clone git://git.libav.org/libav.git libav
svn co http://ffmpegsource.googlecode.com/svn/trunk/ ffms
$HOME/x264_L-SMASH_clone.sh
cp -r . $WORK/x86
cp -r . $WORK/x64

#32bit
cd $WORK/x86
for i in ./*.gz ; do tar zxvf $i ;done
for i in ./*.bz2 ; do tar jxvf $i ; done
rm ./*.gz ./*.bz2

cd ./lame*
./configure\
    --prefix=$PREF32\
    --disable-shared\
    --enable-nasm
make clean && make && make install-strip

cd ../faac*
./configure\
    --prefix=$PREF32\
    --disable-shared\
    --without-mp4v2
make clean &% make && make install-strip

cd ../opencore*
./configure\
    --prefix=$PREF32\
    --disable-shared
make clean && make && make install-strip

cd ../vo-aacenc
autoreconf
./configure\
    --prefix=$PREF32\
    --disable-shared
make clean && make && make install-strip

cd ../vo-amrwbenc
autoreconf
./configure\
    --prefix=$PREF32\
    --disable-shared
make clean && make && make install-strip

cd ../libav
./configure\
    --prefix=$PREF32\
    --cpu=i686\
    --disable-doc\
    --disable-ffprobe\
    --enable-gpl\
    --enable-version3\
    --enable-postproc\
    --disable-network\
    --enable-w32threads\
    --enable-runtime-cpudetect\
    --enable-memalign-hack\
    --enable-libopencore-amrnb\
    --enable-libopencore-amrwb\
    --enable-libvo-aacenc\
    --enable-libvo-amrwbenc\
    --disable-encoders\
    --enable-encoder=aac,ac3,alac,vorbis,libopencore_amrnb,libvo_aacenc,libvo_amrwbenc\
    --disable-muxers\
    --disable-hwaccels\
    --disable-devices\
    --disable-protocols\
    --enable-protocol=concat,file,pipe,md5\
    --disable-debug\
    --extra-cflags=-fno-strict-aliasing
make clean && make && make install

cd ../ffms
PKG_CONFIG_PATH=${PREF32}/lib/pkgconfig/ \
./configure\
    --prefix=$PREF32
make clean && make && make install-strip

cd ../x264_L-SMASH
PKG_CONFIG_PATH=${PREF32}/lib/pkgconfig/ \
./configure\
    --qtsdk=$QTSDK\
    --enable-win32thread\
    --enable-nonfree
make clean && make
cp ./x264.exe /usr/local/bin/x264ls_x86_\
`x264 --version|grep "x264"|awk '{print $2}'|awk -F . '{print $3}'`.exe

#64bit
cd $WORK/x64
for i in ./*.gz ; do tar zxvf $i ;done
for i in ./*.bz2 ; do tar jxvf $i ; done
rm ./*.gz ./*.bz2

cd ./lame*
./configure\
    --host=$HOST64\
    --prefix=$PREF64\
    --disable-shared\
    --enable-nasm
make clean && make && make install-strip

cd ../faac*
./configure\
    --host=$HOST64\
    --prefix=$PREF64\
    --disable-shared\
    --without-mp4v2
make clean && make && make install-strip

cd ../opencore*
./configure\
    --host=$HOST64\
    --prefix=$PREF64\
    --disable-shared
make clean && make && make install-strip

cd ../vo-aacenc
autoreconf
./configure\
    --host=$HOST64\
    --prefix=$PREF64\
    --disable-shared
make clean && make && make install-strip

cd ../vo-amrwbenc
autoreconf
./configure\
    --host=$HOST64\
    --prefix=$PREF64\
    --disable-shared
make clean && make && make install-strip

cd ../libav
./configure\
    --prefix=$PREF64\
    --target-os=mingw32\
    --cross-prefix=$CROSS64\
    --cpu=x86_64\
    --arch=x86_64\
    --disable-doc\
    --disable-ffprobe\
    --enable-gpl\
    --enable-version3\
    --enable-postproc\
    --disable-network\
    --enable-w32threads\
    --enable-runtime-cpudetect\
    --enable-memalign-hack\
    --enable-libopencore-amrnb\
    --enable-libopencore-amrwb\
    --enable-libvo-aacenc\
    --enable-libvo-amrwbenc\
    --disable-encoders\
    --enable-encoder=aac,ac3,alac,vorbis,libopencore_amrnb,libvo_aacenc,libvo_amrwbenc\
    --disable-muxers\
    --disable-hwaccels\
    --disable-devices\
    --disable-protocols\
    --enable-protocol=concat,file,pipe,md5\
    --disable-debug\
    --extra-cflags=-fno-strict-aliasing
make clean && make && make install

cd ../ffms
PKG_CONFIG_PATH=${PREF64}/lib/pkgconfig/ \
./configure\
    --host=$HOST64\
    --prefix=$PREF64
make clean && make && make install-strip

cd ../x264_L-SMASH
PKG_CONFIG_PATH=${PREF64}/lib/pkgconfig/ \
./configure\
    --host=$HOST64\
    --cross-prefix=$CROSS64\
    --enable-win32thread\
    --enable-nonfree
make clean && make
cp ./x264.exe /usr/local/bin/x264ls_x64_\
`x264 --version|grep "x264"|awk '{print $2}'|awk -F . '{print $3}'`.exe

L-SMASH

最近、x264のビルダーやってる人たちの多くが採用しているパッチにmp4muxer.diffなるものがある。
このパッチ、オリジナルはVFR_maniac氏によるもので、内容はlibgpacなしでもx264でmp4出力出来る様にするというものであるが、実はそれだけではなく他にも色々と追加機能(音声やchapterのmuxとか)が盛り込まれていたりする。
色々と盛りだくさんなので、たしかに使わないよりは使ったほうがいいかもしれないが、ときどき不思議に思うのである。
「みんなよくこんなわけのわからんものを平気でホイホイ使うよなぁ…しかも自分で使うだけではなく他人にまで配布するなんて」
自分の知る限りでは、このパッチの内容(なにが出来るかとか)を把握できているビルダーは、VFR_maniac氏本人を除けば、あとはHenry氏wipple氏しかいない。JEEB氏も知っているだろうと思う人もいるかもしれないが、彼は基本的にmkv大好きな人なので、これに関しては先の2名ほど熱心ではないと思う。彼らは全てL-SMASH projectのメンバーではあるが、そこにはやはり、それなりの温度差というものが存在するのではなかろうか。

それにしても、注目されているのかいないのかよくわからないプロジェクトである。
#x264における評判は悪くないんだけどフォーラムにもIRCチャンネルにも質問しに来る人間が一人もいない。
やっぱりmkvではなくmp4だからかな?

2010年9月2日木曜日

Ubuntu奮戦記 その7

長いことご無沙汰してました。
もはや当時なんで苦労していたのかさっぱり覚えていません。
たしかパッケージに関することだったと思うんだけど…なんだっけなぁ。
checkinstallを使ってあれこれやってたはずなんだが。

忘れてしまったものは仕方がないので、このテーマはこれで終了にします。

2010年5月2日日曜日

Ubuntu奮戦記 その6 wine+AviSynth(2)

しばらく書くのをサボっていたら、どこまで書いたのか忘れてしまった。
えーと、再生環境と編集&フィルタリングは済んだから、あとはエンコードか。

Windows用のエンコーダーはx264もffmpegもmencoderもavs(AviSynth script file)に対応しているが、Linux用のバイナリは対応していない。
たとえばwindowsなら
x264 source.avs -o video.264
とやればx264でエンコード出来るが、Linuxだとこれが通用しないわけだ。
じゃあ、どうすれば良いかといえば方法は主に二つに分かれる

1.wineを使ってWindows用エンコーダーを利用する。
wineを使えばWindows用のx264もffmpegも普通に動く。
たとえばWindows用のx264.exeを$HOME/.wine/drive_c/windows/system32に突っ込んでやれば、あとは
wine x264.exe source.avs -o video.264
で、エンコードできる。
これがffmpegなら、音声もエンコードできる。
wine ffmpeg.exe -i source.avs -vcodec ffv1 -acodec pcm_s16le movie.avi
これで映像はFFV1、音声はPCMのaviになる。
Windows用のx264はx264.nlで手に入る。
ffmpegはramiro氏のAutomated Build、mencoderなら、sherpya氏なりKovensky氏なりのところにいけばいい。
わざわざMinGWを入れてクロスコンパイルする必要もないし、非常に楽である。

2.wineを使ってavsの内容を標準出力し、Linux用エンコーダーにパイプで渡す。
いくらwineを使えばWindows用バイナリが動くといっても、やはりwine上ではいまいちエンコードは遅くなる。
このためよく使われるのがこの手である。
とりあえずwindows用バイナリにはavsの読み込みだけをさせて、他形式へのエンコードはLinux用バイナリを使うわけだ。
この方法なら大して手間も変わらず、より高速にエンコードできる。
この方法で使うWindows用バイナリは、wineで動いて、標準出力出来るものなら別にffmpegでもmplayerでもなんでも良いが、一番よく使われているのはavs2yuvだろう。

avs2yuvはx264teamの総大将、pengvadoことLoren Merritt氏が、まだmplayerの開発を主にやってたころに作ったWindows用アプリケーションである。
出来ることはavsを読み込み、raw yuv、y4m、そしてHuffyuvで圧縮したaviを出力することだけだが、出力は標準出力でも行えるのがポイントである。
avs2yuv.exeを$HOME/.wine/drive_c/windows/system32にいれて
wine avs2yuv.exe source.avs -o -|x264 - --demuxer y4m -o video.264
とすれば、Linux用のx264でエンコードできる。
avs2yuvは映像のみにしか対応していないので、音声に関してはwaviかffmpegを使えばよい。
wine wavi.exe source.avs -|neroAacEnc -q 0.5 -if - -of audio.mp4

やはりLinux使うなら、エンコード用のバイナリはできるだけLinux用のものを使いたい。
そうでなければ、始めからWindows使えばよいのである。
というわけで、次回はLinux用バイナリのビルドのお話。

2010年4月4日日曜日

Ubuntu奮戦記 その5 wine+avisynth

さて、再生環境が整ったので、次はフィルタリングツールとエンコーダーである。

フィルタは非常に簡単。
wine+AviSynthで決まりだ。
launchpadのwineのPPAを登録してインストールし、wineからAviSynthをインストールすればよい。

そもそもLinuxネイティブなエンコードツール類にはまともに使えそうなモノがない。
ffmpegやmplayerでもフィルタはかけられるが、品質や数に関しては正直今ひとつだし、だいたいプレビューなしでどうやってtrimしたり細かい調整したりすればいいというのか。
え、Avidemux? うーん…
AvidemuxはWindowsでなら何度か使ったことがあるが、残念な印象しか持っていない。
残念その1:遅くて不安定
gtk+であれQtであれクロスプラットフォームなGUI一般に言えることだが、これらをWindowsで動かすととにかく遅い。これがmkvmergeGUIなら遅いだけですむが、Avidemuxは遅い上に不安定でクラッシュしまくる。
まあQtアプリもLinux上なら結構速いようだから、これは見当違いなのかもしれない。
残念その2:よいフィルタが少ない
mplayerよりはフィルタも多いが、それでも数が少ないし、品質はイマイチ。
例えばリサイザーにしてもsplineやNearestNeighborだって使いたいことがあるのに、Bilinear、Bicubic、Lanczosしかない。わざわざAviSynthのリサイザーとswscale(MPlayerResize)の2種類用意するくらいなら、もっと種類増やせよ。だいたいswscaleにだってSplineとかあるじゃない。
残念その3:muxerが変
ffmpegと同じlavf使ってるはずなのに、出力が変である。
これでエンコした動画をPSPで再生しようとすると蹴られた。同じ動画をmp4boxやffmpegでremuxすればちゃんと再生できたのに、どーなってるの?(ひょっとするとここ数ヶ月の更新で治ってるのかもしれないけど)
残念その4:処理がYV12オンリー
AviSynthのように色空間を使い分けられるか、さもなくばAviUtlのYC48のような過剰ともいえる高品質処理が出来ないのでは、結局満足出来ないのですね。

avsのエディタはとりあえずUbuntu標準のgeditを使い、プレビューはwine経由でVirtualDubを使うことにした(AvsPはwineでも動かない)。ことの発端がvim用syntax fileなんだからvimを使うのが筋なのかもしれないが、あれになれるのはなかなか難しそうなので、とりあえず保留…。
geditは結構いいと思う。notepad++ほどではないが、機能は一通り揃っているし、拡張性も高そうである。それにこれ以上の高機能を求めるなら「だったらemacs使えよ」と言われてしまうだろう。
VirtualDubはWindowsと同様サクサク動く(ただ、メニューのフォントが見にくいのが難点か)。
ためしにAviUtlもwineで動かしてみたら、一応動いた。必要なruntimeやdll(.NETとか)をインストールすれば、こちらも普通に使えるのかもしれない。今度試してみよう。

問題はcodecである。
Windows用のVCMはインストールしても使えるものと使えないものがあるようだ。
とりあえずUtVideoは使えなかった。正確には、インストールは出来たがULRG以外はVirtualDubのダイアログボックスに表示されなかった。
ffdshowはインストール出来たし、vfwも使えるようだが、それなら入力はffms2、出力はffmpegを使ったほうがいいだろう。
どうやらLinux上ではffmsやDGMPGDecのように、フィルタ自身がデコーダーを内蔵するタイプのソースフィルタ以外は使い物にならないと思った方がいいらしい。ffmsの最大の開発理由は「Linux上における安定したソースフィルタの不在」であると聞いたことがあったが、それが実感できた。

次回に続く

2010年4月3日土曜日

Ubuntu奮戦記 その4 mplayerビルド

FFmpeg is a versatile tool to encode and convert a multitude of video and audio formats. x264 encodes high-quality video superior to other popular encoders.

Although FFmpeg and x264 are available in the Ubuntu repositories, you may need to compile from source. For example, the ffmpeg-user mailing list requires that you use the latest FFmpeg svn before asking for help. Since FFmpeg and x264 are updated frequently, you may also like to have the bleeding-edge for encoding videos. Also, FFmpeg in the Ubuntu repository may not support necessary encoders, decoders, and formats.

以上、HOWTO: Install and use the latest FFmpeg and x264より引用。

前回、筆者はUbuntuレポのmplayerをガラクタと呼んだ。理由は上記のとおりである。
x264もffmpegもmplayerも開発は活発に続いており、常に機能の向上とバグフィックスが進められている。もし使用中になんらかの不都合に直面したとしても、使っているモノが新しくなければ助けを求めても鼻も引っ掛けてもらえない。
"It's outdated."
"Update your x264(,ffmpeg or mplayer)."
こんなやりとりをここ数ヶ月で何度目にしたことか。

まあ、これがGIMPとかなら、何の疑問も持たずにレポのもの使うんですがね(ヲイ

さて、mplayerのビルドである。
筆者はx264とffmpegならmsys+mingwでビルドしたことがあるが、mplayerは一度もない。
ものが単なるエンコーダーやデコーダーではなくプレーヤーであるから、必要になるツールやライブラリも多くなるであろうことは簡単に想像がつく。一体何が要るんだろ?

<JEEB>    :Chikuzen氏はもうmplayerはビルドしましたかな?
<Chikuzen>:まだ、ただいまビルドに必要なものを調査中
<JEEB>    :sudo aptitude build-dep mplayer
<JEEB>    :sudo aptitude install git-core subversion
<JEEB>    :あとはgit clone git://repo.or.cz/mplayer-built.git
<Chikuzen>:それだけ?
<JEEB>    :うん
<JEEB>    :追加であと二つくらい要るような憶えがあるけど、なんだっけ
<Chikezen>:まあいいや、とりあえずやってみる
<Chikuzen>:えーと、READMEのとおりに
<Chikuzen>:まず./enable-mt
<Chikuzen>:次に./init
<Chikuzen>:そしてmake
<Chikuzen>:エラーで止まった。autoreconfというコマンドがないと言ってる
<JEEB>    :思い出した。autoconfとlibtoolが要る
<Chikuzen>:あとよく見るとyasmもnoになってるね
<JEEB>    :要るの?
<Chikuzen>:アセンブラなしではつらいでしょ
<JEEB>    :ならsudo aptitude install autoconf libtool yasm
<Chikuzen>:ふむ、./cleanしてもう一度make
<Chikuzen>:よし、今度はエラーでないぞ
<Chikuzen>:それにしてもこれほど楽だとはなぁ、msys+mingwが馬鹿みたいだ
<JEEB>    :uau氏のブランチはmkv対応も強化されてるし、ビルド用スクリプトもあるから楽ちん
<Chikuzen>:お、ビルド終わった
<Chikuzen>:PSP用にエンコしたやつでテストしてみる
<Chikuzen>:cd ./mplayer && ./mplayer ~/Change_vs_Neo_ep02.mp4

<Chikuzen>:おお、上手くいったみたい
<JEEB>    :おめ
<Chikuzen>:thx

ここから先が長かった…

次回に続く

2010年3月31日水曜日

Ubuntu奮戦記 その3 再生環境

動画のエンコード環境構築は、まず適切な再生環境を準備することから始まる。
適切な再生環境抜きでは、成果(エンコ後の動画)に対して評価を下すことが出来ない。
目的がiPhoneやPSP等向けの携帯動画なら実機を用意して再生確認をしなければならないし、ニコニコやzoomeへの投稿であるならば、投稿前の確認はFlashPlayerコンポーネントを使用するFLVPlayer(Flavie等)で行うべきである。
例えば「AviUtl+x264gui.auoでエンコードしています。投稿前にMPCで確認した時は大丈夫だったのに、ニコニコに投稿した動画はブラウザで見ると色が滲んで変に見えます。どうしてですか?」といった質問がたまにyoutube板のエンコードスレに来ることがある。
答えは「FlashPlayerはYUV420->RGB変換の際に色差情報の補間を一切行わないから」。
YUV420で圧縮された動画には、色差情報の不足のため、色が滲んでいたりエッジがギザギザになっているものがけっこうある。しかし、それではあんまりなので、一般的な再生環境はこれに補間処理を行って情報不足を目立たなくするようになっている。しかし、FlashPlayerは(おそらく処理量を低減し、少しでも再生を軽くするため)これをしない。言ってみれば安くあげるために手を抜いている。
このため、ある程度ニコニコ投稿経験をつんだAviUtlユーザーは、UVダウンサンプリングフィルタをYUV420-lanczos2(or lanczos3)で最後にかけることで対策を行う。これはある意味AviUtlの特徴であるYC48による高品質な処理を台無しにしてしまう行為になりかねないのだが、再生環境がFlashPlayerである場合はやむを得ないのである。

と、前置きがやたら長くなってしまったが、要はUbuntuで使うプレーヤーはどれにしようかというお話である。
結論から言えば、これは最初からmplayerに決まっていた。
#x264や#ffmpegにはたまに自分の環境で上手く再生できないと相談にやってくるLinuxユーザーやmacユーザーがいる。
「上手く再生できないんだけど、どうしたらええんかいな?」
「プレーヤーは何を使ってるんだ?」
「VLC(またはTotemとかQuickTimeとか)だよ」
「mplayer使えよ」
こういったやりとりが週に一度はあるような気がする。
特にVLCはデコード時に必要な参照フレームをすっ飛ばすために映像が崩壊するバグが数年間放置されており、また字幕周りもひどいということで甚だ評判が悪い。
Linuxならmplayerが一番と皆が口を揃えて言うのだから、やはりそれが正解なのだろう。

さて、さっそくmplayerを9.10にいれようと、synapticを開いて探してみたが…
「えーと、svn20090426…なにこれ?」
あらかじめ用意されているものは、たいへん古く、使い物にならないガラクタだった。
やはり、物事は簡単にはいかないものらしい。

次回に続く

2010年3月29日月曜日

Ubuntu奮戦記 その2 *nix使えよ!?

x264の公式フォーラムであるDoom10 Forumの特徴の一つは、登録メンバーにLinuxユーザーが多いことである。
以前の公式フォーラムに指定されていたDoom9(といっても今でもこっちの方が情報は多いけど)ではLinuxやmac関連の情報は少なく、一体彼らはどこで情報を手に入れているのか不思議に思っていた。(その後判明したが、彼らの情報交換は主にIRCや各ディストロの公式フォーラムで行われていた)
だからDoom10が出来たとき、それまでDoom9ではあまり見かけたことのない名前がいろいろ出てきてLinuxでのエンコードについて語っているのを見たときはちょっと驚いたものだった。

さて、このスレッドである。
http://doom10.org/index.php?topic=180.0
LinixやBSD(たぶんmacも含まれる)においてAviSynthを使うための簡単なガイドラインといったもので、とりあえず必要なツール類と簡単なスクリプトの例、そしてvimのsyntax fileがあげられていた。
「Windows以外のOSでは、こんなことせにゃならんのか…なんだか大変そうだねぇ、素直にWindows使えばいいのに」
とか思いながら読んでいたら、昔AviSynthBlogで読んだこの記事を思い出した。
自分では使ったこともないけど、なにかの役に立つかもしれないと思い、「vimならこんなのもあるみたいよ」と書き込んだ。
そしたらお礼の言葉とともに「お前も*nixを使うべきだよ」と返事が返ってきた。
まあ、せっかく勧めてくれたことだし、気が向いたら試してみるかななんて思っていたところで、前回のような状況になった。
かくして筆者はLinux体験をすることになったのである。

とりあえずディストロはUbuntuにした。
一番簡単で使いやすいとどこかで聞いた覚えがあったからだ。
Ubuntuの公式サイトから9.10のisoをDLしてimgburnでCDに焼いて、再起動。
言語設定とキーボードを日本語にして、あとは待つこと20分程度でインストールはとりあえず終了。
「再起動する」を選んで、CDを取り出してEnter。
なぜ「とりあえず」かというと、このあと初回のアップデートに結構時間がかかるからである。
アップデートが済んだらもう一度再起動。さらにハードウェアドライバの設定でビデオカード(GF8400M GS)のドライバーをNVIDIA製のもの(185)に変更してさらに再起動。
ここまででかかった時間は約1時間といったところだった。

次回に続く

2010年3月25日木曜日

Ubuntu奮戦記 その1:香港映画の悪夢

ここ数日間Ubuntu9.10をいじっている。
慣れないことだらけで、やたら苦労している。

「一体俺は何でこんなことをしているのだろうか?」

苦闘の果て、昨日やっと一段落ついたような感触を得たので振り返ってみた。
えーと、なんだったかなぁ...
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

すべての始まりは香港映画のDVDだった。

その日筆者は暇であった。
何もすることがないので、DVDを観ることにした。
20秒ほど本棚を眺め、手に取ったのはジャッキー・チェン監督/主演の「奇跡(miracle)」だった。
たしか数年前にTSUTAYAの安売りコーナーで500円くらいで買ったものである。
ドライブにディスクを突っ込んでMPCHCを起動した。
デコーダーはMS DTV-DVD Decoder、レンダラーはEVR-custom。
インターレース処理はビデオカードにおまかせ。
そして再生を開始すると…

DVDは4:3のレターボックスで収録されていた。
スクイーズでないことにまず腹が立った。
そして時々チラチラするような妙な違和感を覚えた。
訝しがりながらMPCHCの表示を見ると、60fpsで再生されていた。
Radeonのプルダウン検出が効いていない…だと…。
再生を中止し、調査を開始した。

DVDは60iで収録されていた。HD5870は間違っていなかった。
試しにYadif(mode=1)をかけた状態でコマ送りしてみると、同じフレームが1枚、2枚…そして前後のフレームが混ざりあったような残像のあるフレームが至るところに存在していた。
あきらかにPALソースをNTSCに無茶なやり方で変換したものである。
ひどい、ひどすぎる。
元々素材は24fpsなんだから、AssumeFPS(24000,1001,true)して、3:2プルダウンかければいいだけなのに、これを作った香港のオーサリング屋は、一旦PAL用に25p変換したものをブレンド処理して60iにしやがった。
ほんと映像業界って、どこの国でも…。
まあ最近はひどいDVDは少なくなったみたいだけど、かわりにひどいBDが増えているわけで。

こんなこと考える人間はあまりいない。
筆者も初めてこのDVDを観たときは、こんなことは少しも気にならなかった。
世の中、それで済んだほうがいいのである。
どうやらここ数年の経験は、あきらかに間違った方向に筆者を導いているらしい。
しかし、いまさらこの手の経験を‌リセットするのも無理である。
よせばいいのに、「修正してやる!」という気になってしまった。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

さて、PAL->NTSCによるブレンドの修正は次のような処理を行う。

MPEG2Source("video.d2v")
#最初に上下左右の黒べたをフィールドオーダーが狂わないようにしながらcrop
Crop(left,top,right,bottom)
#次に60i->25pの修正
#なんらかの方法でBob(60fps化)
Bob()
#そしてSRestoreをかける
SRestore()
#これでブレンドはほぼ除去され、60iは25PのPALに戻される。
#今回の場合は素材は劇場用映画なのだから、これをさらに24fpsにしてやる
Audio=NicAC3Source("audio.ac3")
AudioDub(last,Audio)
AssumeFPS(24,1,true)
ResumpleAudio(48000)
return last

問題はBobになにを使うかである。
まずavisynth内蔵のBobではガタガタで論外。
Yadif(mode=1)を使ってみたが、どうにも汚い。
Yadifmod+NNEDI2でも汚い。
結局MCBobが一番よかったので、これでいくことにした。
avsをVirtualDubにセットし、ULY0で中間出力開始。
終了までにかかる時間は、えーと…約17時間ですと!?

さすがMCBob、SD未満のサイズですらこれであるorz

かくしてメインPCは占領され、筆者は再び暇になってしまった。
しかたがないのでサブノートを引っ張り出した。
半年ぶりくらいに電源を入れた。
起動したOSは、バンドルのXPsp2だった。
Windows7にすっかり慣れてしまった現在では、どうにも使う気になれなかった。
どうしたものかとしばらく天井を眺めていたら、このスレッドのことを思い出した。
http://doom10.org/index.php?topic=180.0

次回に続く

2010年3月9日火曜日

デザイン変更

ブログを書き始めて2ヶ月ほど(といっても更新はあまりしない)たって、初めてコメントが付いた。
まさか読む人がいるとは思わなかったのでびっくりした。
書いてる本人ですら三日に一度くらいしか開かないというのに...そもそもBarn(物置小屋)なんて、そんなもんでしょ。

とりあえず新着コメントの有無くらいはわかるようにしようとガジェットを追加してみた。
ついでにレイアウトもなんだか殺風景すぎる気がしたので変更(といってもBloggerのテンプレを別のものに変えただけ)。

やってみて改めて思ったが、我ながらこの手のことにはさっぱりセンスがないな...まあ、いいや。
物置小屋なんてこんなもんで十分でしょ。

2010年3月8日月曜日

ffmpegsourceのmpegsource入力

ffmpegsourceは、myrsloik氏をリーダーとして#darkholdのメンバーが開発しているffmpegのwrapperである。
lavfでdemuxし、lavcでデコードして,swscaleで色空間変換やリサイズを扱い、lavfilterでその他のフィルタを掛けることが出来るAviSynth用ソースフィルターであり、最近ではx264の入力にも使われるようになった。
ffmpegが使われているだけあって非常に多くのフォーマットやコーデックに対応しており便利なことこの上ないのだが、弱点も幾つかある。なんでもlavfのmpeg parserは問題があるのでかわりにHaali氏のparser(HaaliMediaSplitterで使われているもの)を利用することにしたのだが、これはこれでやはり問題があるらしく、しかもHaaliはソースが公開されていないため、不具合に対処しようがないというのである。

一方、AviSynthでmpeg入力とくれば、真っ先にあげられるのはneuron2氏のDGMPGDecである。
こちらのほうもしょっちゅうヘマをするが、そのたびにneuron2氏はソースに手を入れ何とかしてきたので、AviSynthユーザーは特に理由がない限り、普通はmpegソースにはこちらを使う。

これは#darkholdメンバーにしてみれば、非常に面白くない事態であろう。
なんせ、世にあふれる動画ソースは殆どがPS(DVD)かTS(放送)かm2ts(BD)であるのに、あのneuron2のツールを使わねばならないのである。
くっ、悔しい...で(ry
(なんで#darkholdがneuron2氏を嫌うのか分からない人は、#darkholdがなんなのかとか、neuron2氏の過去の言動を、CCCPのサイトやDoom9等で調べてみればいい)

てな感じのことがあって、このたび#darkholdの重鎮の一人であるTheFluff氏が自前のmpeg parserをスクラッチで書く気になったみたいだ、とJEEB氏から聞いた。
以下、某IRCのログより適当に抜粋

(JEEB) そういや、TheFluff氏は夕べdgindexのソースのTSパーサーなど読んでた
(JEEB) 結局諦めたのかwww
(JEEB) <Lord> anyway are you really sure you want to steal that code? :P
(JEEB) <TheFluff> no, it seems way too annoying
(JEEB) <TheFluff> I'd rather write a ts parsing library instead
(JEEB) <TheFluff> from scratch
(JEEB) <TheFluff> I mean, how hard can it be!?!!?!111
(JEEB) dgindexのソースを読んでみたら色々面白いものが見つかったけど、再利用出来る部分があまりなかったw
(JEEB) <TheFluff> rather than check how much data he has read and deciding to stop parsing after not encountering any headers after a certain amount of data, he gets the current time in milliseconds and aborts parsing if headers have been found for more than 5 wallclock seconds
(JEEB) ↑dgindexから
(JEEB) 5秒内でTSヘッダが見つからない→止まるw
(JEEB) どれぐらいデータが読み込めたかに関わらずw
(chikuzen_) TSならまるもプラグインのほうが速いよ
(chikuzen_) ソースも公開してるから見てみるのもいいかもね
(JEEB) ほほぉ
(JEEB) あと、日本専用のソースならねぇ・・・ 他にATSCなどなTSファイルがあるからねぇ
(JEEB) まぁ、何もないよりマシかとw
(chikuzen_) http://www.marumo.ne.jp/mpeg2/
(chikuzen_) GPLみたいなケチくさいこと言わないのがまるもさんのいいところ
(JEEB) ライセンスは?
(JEEB) 再配布の禁止
(JEEB) ↑これがあるけどねぇ
(chikuzen_) そのままではね
(JEEB) ふむ
(chikuzen_) つまりいじったものに関しては一切関知しない
(JEEB) おぉー、readme.enでちゃんと書いてある
(JEEB) まぁ、ちゃんとライセンスを書いてくれる人は嬉しいわ
(JEEB) 書いてない人は「書いてないなら、何も出きない」という法律的な理屈を理解してないかなw
(chikuzen_) LanczosResizeのオリジナルは彼だけど、うやむやのうちにavisynthオリジナルみたいになっちゃったりして
(chikuzen_) 結構腹が立ったこともあるんじゃないかな
(JEEB) ほほぉ
(chikuzen_) まあ、120fpsAVIの生みの親でもあるんだけどね
(JEEB) それは言わないことにしようw
(chikuzen_) 本職のコーデックプログラマだから、フリーのエンコーダーは書けないって前に日記に書いてたな
(JEEB) ほほぉ
(JEEB) まぁ、TheFluff氏は今他のことをやってるけど、とりあえず#darkholdで貼ってみた

数時間後

(JEEB) chikuzen_, あのMPEG-2プラグインを紹介してくれてありがとうw ソースはこんな初心者の目で見る限りでも、かなりdgindexより再利用できそうw
(chikuzen_) まあそのままは使えないだろうけど、parserなりdemuxerなりの‭参考くらいにはなるかも
(JEEB) うん

さて、どうなることやら

それにしても、草を生やすのが好きなフィンランド人である。

2010年3月2日火曜日

JM Reference Software

JM Reference Softwareが更新されたと小耳に挟んだので見に行ってみた。
http://iphome.hhi.de/suehring/tml/

おお、本当に更新されてるじゃんってことで早速DLしてビルド。

用意するもの
Microsoft VisualC++2008 ExpressEdision
WindowsSDK for Windows7 and .NET Framework3.5SP1 

手順
・JMのzipを解凍する
・中にあるjm_vc9.slnをVC++2008で開く
・"ソリューション構成"を"Release"にする
・ldecodとlencodのプロジェクトをそれぞれ”ビルド"する

これでbinフォルダの中にldecod.exeとlencod.exeができるので、あとはbinフォルダをまるごとコピーして、好きな場所に保存すればおしまい。

2010年3月1日月曜日

x264vfwの復活

前回の記事を書いた後にDoom9に行ってみたら、x264vfwのスレッドが何故か賑わっていた。
何事だろうと訝しがりつつ新着投稿を読んでみると、あらびっくり。死んだと思われていたvfwが華麗なる復活を遂げているではないですか。
これはすごいと言うしかない。

そもそもvfwの何が悪かったかといえば、いわゆる"one frame in, one frame out"の原則である。
vfwはその仕組み上、エンコード前のフレームを1枚入力すると、そのフレームをエンコードして1枚出力しない限り、次のフレームを入力することが出来ない様になっている。これでは、Bフレームのように未来を参照するフレームのエンコードが原則的に出来ないし、処理速度をあげるためにマルチスレッド化を行おうにも、1枚のフレームを複数に分割して処理することしか許されない。複数枚のフレームを一度に処理するのと違って、圧縮率が低下するは、処理速度の大幅な向上は望めないはで問題がありすぎた。
xvidやDivX5等が主流の頃は、これを何とかしようとPackedBitStreamなる、なんともややこしいハックが行われたりしていたが、それはそれで問題が合ったりして、そうこうするうちにvfwは可逆圧縮コーデック専用のような扱いになりかけていた。

今回のx264vfw-r1471は今までとは明らかに一線を画す改造である。
vfwはまず1枚のフレームをエンコーダーに渡す。
エンコーダーは入力フレームを1枚受け取ると、エンコードしないでそのフレームをキャッシュしておき、かわりに真っ黒なフレームをエンコード済のフレームとして出力する。vfwは入力したフレームが無事に出力されたと騙されて、次のフレームをエンコーダーに渡し、受け取った真っ黒なフレームをAVIとして出力する。
これを繰り返すとエンコーダーには複数枚のフレームがキャッシュされていくが、ある程度のフレーム(x264ならrc-lookaheadによるだろう)が貯まった時点で、初めてエンコーダーはエンコードを始める。複数のフレームを同時に扱えるので、Bフレームの使用もまったく問題ないし、マルチスレッドによる高速な処理も行える。そしてエンコードされたフレームは、vfwによって作られた偽物のAVIとは別の場所に、mp4やmkvとして保存される。
この仕組だと、ACMによってエンコードされた音声は偽物のAVIのほうに格納されてしまうので、従来のものよりは少し扱いづらいことにはなるが、そもそも音声は別処理して後で改めて結合するのが今時の常識であるから、それほど大した問題ではない。
バッチ処理すると複数のダミーが出来るのがウザイと思う人もいるかも知れないが、それにしたって映像だけのAVIならどんどん上書きすればいいだけだから、出来上がるダミーは結局一つで済む。

そして今回の改造の一番すごいところは、他のエンコーダーにも応用可能な点である。
この仕組みを使えばmpeg2だろうがmpeg4だろうがtheoraだろうが、すべてvfwで実装出来る。極端な話、ffmpeg vfw codec(ffdshowではない)すら可能であろうと言うことだ。

VirtualDubはすでにPhaeron(Avery Lee)氏がCLIエンコーダーとの連携機能実装に動いているため、今回のx264vfw-r1471の恩恵を受けることはそれほど大きくはないだろう。
しかし他のソフト(TMPGEnc、Premiere、Vegas、Nive、紙芝居クリエーター、CrystelEngine等)のユーザーにとってはこれは非常に素晴らしい前進と言えるのではないかな。

x264.exeでavi出力

komisar氏のサイトを眺めていたら、なにやら見たことのないnewパッチがあった。
x264_avi_out.v2.diff
名前から察するに、x264.exeでAVI出力出来るようになるパッチらしい。
面白そうなので、さっそくビルドに挑戦してみた。

パッチ自体は問題もなく当てることが出来たが、いざ出来上がったバイナリでAVI出力を試してみると、エラーが出て上手くいかない。
他のMKVやMP4は普通に出力できるのに、なんでだろうと思いながらパッチの中身を覗いてみたらなんとなく理由がわかった。
このパッチはどうやらlavfのavimuxerを使用するものらしい。
そういや自分のビルドに使ってるffmpegは、configureで--disable-muxersにしているんだった。これでは駄目なはずだわな。

つーことで、ffmpegからビルドし直してみることにした。
いままでの設定は
./configure --prefix=/mingw/x86_64-pc-mingw32 --cross-prefix=x86_64-pc-mingw32- --enable-cross-compile --target-os=mingw32 --host-cc=gcc --enable-gpl --enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --disable-devices --disable-filters --disable-encoders --disable-network --disable-muxers --disable-decoder=aac,ac3,adpcm_*,alac,als,ape,atrac?,cook,dca,dsicinaudio,dxa,eac3,flac,interplay_dpcm,mlp,mp1,mp2,mp3,mp3*,mpc?,pcm_*,qcelp,ra_*,sipr,truehd,truespeech,tta,vorbis,wavpack,wma*,twinvq --disable-demuxer=aac,ac3,pcm_*,ape,amr,ass,au,avs,dts,eac3,flac,mp3,mpc,mpc8,truehd,tta,w64,wav,wv --disable-parser=aac,ac3,dca,mlp,mpegaudio
これが
./configure --prefix=/mingw/x86_64-pc-mingw32 --cross-prefix=x86_64-pc-mingw32- --enable-cross-compile --target-os=mingw32 --host-cc=gcc --enable-gpl --enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --disable-devices --disable-filters --disable-encoders --disable-network --disable-decoder=aac,ac3,adpcm_*,alac,als,ape,atrac?,cook,dca,dsicinaudio,dxa,eac3,flac,interplay_dpcm,mlp,mp1,mp2,mp3,mp3*,mpc?,pcm_*,qcelp,ra_*,sipr,truehd,truespeech,tta,vorbis,wavpack,wma*,twinvq --disable-demuxer=aac,ac3,pcm_*,ape,amr,ass,au,avs,dts,eac3,flac,mp3,mpc,mpc8,truehd,tta,w64,wav,wv --disable-parser=aac,ac3,dca,mlp,mpegaudio --disable-muxer=ac3,adts,aiff,amr,as*,au,avm2,c*,d*,e*,f*,g*,h*,i*,m*,n*,o*,p*,r*,s*,t*,v*,w*,y*
に変った。
ただでさえ長ったらしいconfigureが、さらに長くなっちゃったよ… 。

さて、enable-muxer aviになってることを確認して、ffmpegをビルド。
お次はx264をもう一度ビルドし直し。
再度AVI出力を試してみたら、今度は無事にAVIで出力出来ました!

しかし、こんなもん、一体何に使えばいいんでしょうかね?
FLV出力以上に使い道が思い浮かばないんだよなぁ…。

2010年2月16日火曜日

SWF用DirectShowFilter その2

前回の記事に書いたSWF用DirectShowFilter(以下DSF)に、新たなる欠点を発見した。
どうもDirectShow使ってるせいか、動きが止まっている部分で、本来表示されなければいけないフレーム数よりも少ないフレーム数になってしまうことがある。

つまり、本当は全く同じ絵が5回連続で表示されるべきところが、1回だけ表示して、すぐ次の絵になってしまう、といったことが起こるのである。
一方、swf_vfpだとそのようなことは起こらない。
5フレーム同じ絵が続く場面では、きっちり5フレーム表示され、4フレームすっ飛ばしたりはしないのだ。

フレームをすっ飛ばしてしまうということは、音ズレとしてはっきりわかってしまうので、非常にまずい。特に止め絵を多用するものだと、終りのほうは悲惨なものになってしまう。

やはり信頼性はswf_vfpの方が高い。
DSFはスプライトが使われている部分の差し替え用AVI作成以外には使えないと思った方がいいようだ。

2010年2月14日日曜日

SWF用DirectShowFilter

Doom9のこのスレでSWF用DirectShowFilterなるものが紹介されていた。
SWFでDirectShowといえばMPCを思い浮かべるが、あれはただIE用FlashPlayerをそのまま使っているだけで、ブラウザ以上のことは特に何もできない。

これが本当ならすげえやってことで、さっそくDL。
http://www.medialooks.com/products/directshow_filters/flash_source.html
どうやらフリーのようだが、要登録らしい。
あと、IE用FlashPlayerを利用しているようで、こちらも必須とのこと。

さて、インストールしてみて、まずはWMP12でSWFを再生出来るか試してみた…が再生出来ない。
どうもActiveXでセキュリティに引っかかっているようだね。
IE同様、WMPでもSWFの再生はブロックがかかるのか…はじめて知ったよ。
ではこれならってことで、QonohaPlayerで試してみると…上手くいきました!
特にコマ落ちしてる様子もなく、なによりもスプライトを使っている部分もちゃんと動いてる! すごい!(何がすごいか分からない人は、SWFをAVIやMP4に変換しようとしたことのない人でしょう。経験者ならみんな驚くと思います)

さて、再生出来るなら、当然変換にも使えるはずってことで、AviUtlのDirectShowFileReaderで読み込めるか試してみると…クラッシュしたやんけ、オイ…。
ではVirtualDubならどうかとDirectShow input driverで試してみると…これもだめ。
AviSynthならどうかとDirectShowSource使って…orz
ならばこれはどうかとDSS2を使ってみると…やったぁ、読み込めた!
さっそくVirtualDubでAVIに変換…順調に行きました。

でも、なんでDSS2以外はダメなのかしら? ってことでしばらく試行錯誤してみると…どうやら音声を同時に読み込もうとするとクラッシュすることが判明。DirectShowSourceでもaudio=falseにしたら読み込めた(DSS2はもともと音声は読めないから無問題なわけね)。
そういえば、swf_vfpの履歴にmp3音声がどうこうってあったなぁ…あれと同じでPCMを使ってれば読めるのかもしれないけど、手元にPCM音源のSWFがみつからなかったので、調査は保留。
まあ、音声はいままでも別処理だったし、状況は好転したと言えますね。

さて、スプライト関連も上手く再現出来ることだし、これはswf_vfpもいよいよお役御免かなぁ…なんて思ってたところで、一つ不具合を見つけた。
どうやらレイヤーの重ね方だかアルファチャンネルの透過度の具合のせいか、色がおかしくなることがある。同じ現象はswfdrop.exeを使った場合も起こったことを思い出した。
うーん、swf_vfpなら、これは起こらないんだよなぁ…やっぱりすごいよ、まるもさん。

とりあえず、基本はやはりswf_vfp、スプライトの部分はこのDSF、どちらでもダメな場合はデスクトップキャプチャでAVIを作って、切り貼りするってことになるかな。

*今回の実験に使用したSWFは、過去に筆者がニコニコ投稿用エンコードを代理したものを使わせて頂きました。作った人、勝手に使ってごめんね。

2010年2月5日金曜日

lavf/ffms付きx264_x64ビルド

ちょっとサボっていたら、前回の更新から一週間以上経っていた。
誰も読まないチラシの裏替わりとはいえ、やはりサボるのはあまり良くないだろう。

ここ数日はx264.exe(x64)の自ビルドでlavf/ffms入力を有効にするために四苦八苦していた。
Windows&AviSynthユーザーとしては、全く要らないといってもいい機能ではあるが、やはり出来る事ならば有効にしておきたいのが人情というもの。

以下にその手順を書いておく
なお、これはr1416現在の情報なので、あとあと使えなくなっても知らない。

クロスコンパイルできるビルド環境構築は各自でやってるものとする。
参考:
http://komisar.gin.by/mingw/add/MinGW%20cross-compile%20toolchain%20(EN)/
http://zoome.jp/VFR_maniac/diary/89/
ちなみに筆者はkomisar氏のcross-mingw.gcc443.generic.20100124を使用している。
fstabは
e:/msys/mingw /mingw
e:/msys/local/ /usr/local
e:/msys/tmp /tmp1

まずpthread、zlib、bzip2はkomisar氏の配布しているものをそのまま使用しているので省略。

 yasm(0.8.0):
$ wget -c http://www.tortall.net/projects/yasm/releases/yasm-0.8.0.tar.gz
$ tar zxvf yasm-0.8.0.tar.gz
$ cd yasm-0.8.0
$ ./configure --prefix=/mingw
$ make
$ make install
$ cd ~

GPAC:
$ cvs -d:pserver:anonymous@gpac.cvs.sourceforge.net:/cvsroot/gpac login
passwordはなし
$ cvs -z3 -d:pserver:anonymous@gpac.cvs.sourceforge.net:/cvsroot/gpac co -P gpac
$ cd gpac
$ cvs update -D "2010-01-23 UTC"
$ wget -c http://pastebin.php?dl=m59b9d49c
$ mv pastebin.php@dl=m59b9d49c muken_20100123.diff
$ patch -uNp0 < muken_20100123.diff
$ ./configure --prefix=/mingw/x86_64-pc-mingw32 --cross-prefix=x86_64-pc-mingw32- --cpu=x86_64 --static- mp4box
$ make lib apps
$ make install-lib
$ cp -p ./bin/gcc/MP4Box.exe /e/mp4tools/mp4box.exe
$ cd ~
ちなみに途中であてているパッチはVFR maniac氏の最新パッチ(どうやら現在、非公開の様子)
/e/mp4toolsは各自適当に変更して欲しい。

FFMPEG(今回は2010-02-01のスナップショット):
$ wget -c http://ffmpeg.org/releases/ffmpeg-checkout-snapshot.tar.bz2
$ tar jxvf ffmpeg-checkout-snapshot.tar.bz2
$ cd ffmpeg-checkout-snapshot
ここで./libswscale/swscale_template.cの2500行目あたりを次のように書き換え
#if ARCH_X86_64 && AV_GCC_VERSION_AT_LEAST(3,4)
:: "m" (src1), "m" (dst), "g" (dstWidth), "m" (xInc_shr16), "m" (xInc_mask),
#else

#if ARCH_X86_64 && AV_GCC_VERSION_AT_LEAST(3,4)
:: "m" (src1), "m" (dst), "g" ((x86_reg)dstWidth), "m" (xInc_shr16), "m" (xInc_mask),
#else
にする(1行だけ)。
$ ./configure --prefix=/mingw/x86_64-pc-mingw32 --cross-prefix="x86_64-pc-mingw32-" --enable-cross-compile --target-os=mingw32 --host-cc=gcc --enable-gpl --enable-postproc --enable-memalign-hack --enable-runtime-cpudetect --disable-devices --disable-filters --disable-encoders --disable-muxers --disable-network --disable-decoder=aac,ac3,adpcm_*,alac,als,ape,atrac?,cook,dca,dsicinaudio,dxa,eac3,flac,interplay_dpcm,mlp,mp1,mp2,mp3,mp3*,mpc?,pcm_*,qcelp,ra_*,sipr,truehd,truespeech,tta,vorbis,wavpack,wma*,twinvq --disable-demuxer=aac,ac3,pcm_*,ape,amr,ass,au,avs,dts,eac3,flac,mp3,mpc,mpc8,truehd,tta,w64,wav,wv --disable-parser=aac,ac3,dca,mlp,mpegaudio
$ make
$ make install
$ cd ~
configure長すぎる...でもバイナリが小さくなるし、無効にしても影響のない機能はなるべく切るべきだと思う。
なお、pthreadをautostaticでビルドしておけば、--enable-pthreadsもいけるそうだが、今回はパス。

ffms(現時点では275):
$ svn checkout http://ffmpegsource.googlecode.com/svn/trunk/ ffms2
$ cd ffms2
$ PKG-CONFIG="/mingw/x86_64-pc-mingw32/bin/pkg-config.exe" ./configure --prefix=/mingw/x86_64-pc-mingw32 --host=x86_64-pc-mingw32
$ make
$ make install
$ cd ~
なおpkg-config.exeは
http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/pkg-config_0.23-3_win32.zip
glibは
http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.22/glib_2.22.3-1_win32.zip
からDLして、あらかじめ/mingw/x86_64-PC-mingw32以下にまとめてぶちこんでおくこと

x264:
$ git clone git://git.videolan.org/x264.git x264
$ cd x264
$ ./configure --cross-prefix=x86_64-pc-mingw32- --host=x86_64-pc-mingw32
$ make fprofiled VIDS="/g/for_test/soccer_4cif.y4m"
$ make install
$ cp -p /usr/local/bin/x264.exe /e/x264/mine/x264_r1416.exe
$ exit
なんか-march=core2はあまり速くならないようなので、最近はあまりつけていない
fprofiledの動画はなんでもいいらしいが、とりあえずhttp://media.xiph.org/video/derf/y4m/soccer_4cif.y4mを使っている。
mp4box同様、/e/x264/mineのあたりは各自で適当に変えること
上には書いてないが、NAL-HRDパッチとkomisar氏のlog_fileパッチはいつも当てている。

以上で終了。
筆者にIRCで丁寧に教えてくれたVFR maniac氏とJEEB氏に感謝します。

2010年1月26日火曜日

弄りたがる人達

komisar氏がGCC4.4.3の配布を始めたので4.4.2から差し替えた。
別にこれといって変わった様にも思えないし、4.4.2で何も困ってはいなかったのだが、ソフトウェアに関してはなぜか最新を使っていないと気が済まないという難儀な性格なので仕方がない。

最新といえば、MPC-HCがr1552でMPEG2のDXVAに対応したらしいので、こちらも更新してみた。
いつもどおりAlexin女史のところ(xvidvideo.ru)からr1557をDLしてインストール。
とりあえずmpeg2でも内部フィルターでDXVAは効くようになったみたいだが、ffdshowのlibavcodec使用時と比べても、CPU使用率は全く下がらない。3%~15%程度をうろうろしている。(後で気づいたが、実はこのとき使われていたデコーダーは、MPC-HCのものではなく、MS製のほうだった。MPC-HCのデコーダーではDXVAは働かなかったようである)
WMP12 & MS DTV-DVD VIDEO DECODERだと常に5%未満なんだが…DVD鑑賞には結局WMP12が一番いいみたい。
とりあえず再生開始時にフル画面で立ち上がるのをやめてくれればなぁ…どこかに設定出来るところがあるのかしら?

と、まあ、このように筆者自身色々弄り回すのが好きな人間なのであまりでかいことは言えないかもしれないが、世の中には兎角、ワケも分からず色々と弄り回して事態を悪化させるのが好きな人が多いようである。
例えば昨日の2chDTV板のx264スレの書き込み。
自分のエンコード環境はaviutlで編集しavsファイルを作りavsをaviutlに読み込ませて aviutlとavisynthを使い”x264出力(mp4/mkv)プラグイン”でmp4ファイルを作っています。
オプションは
--crf 20 --profile high --preset medium --level 4.2 --ref 3 --mixed-refs --bframes 3 --qpstep 8 --weightb --weightp 0 --trellis 0 --direct auto --subme 7 --no-fast-pskip --no-dct-decimate --partitions p8x8,b8x8,i8x8,i4x4 --8x8dct --scenecut 75 --me umh --merange 32 --aq-mode 0 --psy-rd 0:0 --no-mbtree --b-adapt 1 --threads auto --thread-input
これを見たDark_Shikari氏の反応はこのようなものだった
20:09 (Dark_Shikari) also, the non-saging post asking for settings help
20:09 (Dark_Shikari) with unbelievably bad commandline
20:09 (Dark_Shikari) smells like megui
確かにひどい設定だと思う。一体何を考えたらこんな設定になるのか意図がさっぱりつかめない。

こんなことするくらいなら、ただ単に
--preset slow --tune animation --profile high --level 4.2
としたほうが絶対にいいに決まっている。

なんでこんな設定にするのやら…多分、大昔に書かれたあやふやな情報を読んで、それを鵜呑みにしてるんだろうなぁ。
tobinaka氏はかつてサイトを閉じる際に、それまでに彼が書いた記事を削除した。
あれはやっぱり正解なんだと思う。

2010年1月23日土曜日

日記

UtVideoの梅澤氏がなにやら不具合の調査をしたいらしい。
http://umezawa.dyndns.info/wordpress/?p=1468
サンプルは少しでも多い方がいいだろうから、とりあえず適当に英訳してDoom9に投稿しておいた。
実は梅澤氏もDoom9にはレジストしているので、やろうと思えばご自分で出来るのだが、英語は苦手なのでパスとのことだ。
筆者も英語は得意でも何でもないんだけどね…tobinaka氏はどこいったんだ?

x264はとうとうr1400になった。
速いなぁ…まだlavf/ffms2のビルドの仕方、わかんないよ…。
とりあえずいつも通り、nal-hrdパッチを当ててビルドした。これもいい加減、正式にcomittしてくれないかな。
kierank氏がんばって-。

P.S. インタレエンコでCBP Bufferが変なことになってる…これは、しばらくは駄目なのかなorz

2010年1月17日日曜日

I have caught a cold.

昨日から体調が思わしくない。
どうやら風邪をひいた模様。
IRCで「風邪ひいた」と言ったら、kierank氏から「それは俺のがうつったに違いない」と言われた。
まさかイギリス人に風邪をうつされるとは...IRCって恐ろしい(を

x264_r1391用nal-hrdパッチをmuken氏が書いてくれたので、さっそくビルドし直し。
試しに寝る前にDVDを一本インタレ保持でセットしておいたが、どうやら問題はない様子。

自ビルドを公開している人の最新を幾つか見てみたが、lavf/ffms2を有効にしている人は少ない模様。
やっぱりそうだよなぁ、winの場合は、正直あんまり需要ないもんなぁ。
むしろ、gui.auoとかx264Encoderみたいなものにとっては、この変更はかなり痛いのかも。
たしかmuken氏も「これは大打撃」とか言ってたし...。

2010年1月14日木曜日

x264が久々の更新

r1376が昨年の12月15日だから、約1ヶ月ぶりか。

RIPはとりあえずニコニコ用には使えないだろうな。
IDRがなければシークが効かないのがflashplayerだから。

ffms2とlavfをenableにするにはどうすればいいのだろうか?
ffms2もffmpegも自ビルドしたことがないからさっぱりわからん。
そのうちDoom9かDoom10に解説が出るだろうから、それまでは様子見しとこう。
どのみちAviSynth使う分には関係ないし。

問題はnal-hrdのほうかな。
早く誰かパッチ書いてくれないかしら。

SWFをAVIに変換する方法

前回「ちょっと調べれば自分で出来る」と書いた。
SWFからのエンコードのことである。
書いたときはそう思っていたのだが、その後、頭の中のもう一人の自分がこうささやいた。
「本当にちょっとで済むのか?」

ちょっとで済むに決まっている。
済むだろう。
済むはずだ。
なんせSWFなんて作ったことのない筆者ですらなんとかなっているのだから。
念のために確認してみようと思い「swf mp4 変換」で検索してみた。



検索にBingなんか使ったのがまずかったのかと思い、googleでも検索してみる。



どうもちょっとでは済まないみたい。
これならいけるだろうという方法を詳しく紹介しているページは見つからなかった。

一度、やり方をまとめて書いておいた方がいいのかもしれない。

2010年1月12日火曜日

早起き

朝の4時前に目が覚めた。
SWFをMP4にして欲しいとの依頼がスレに来ていたので、1時間半程度で仕上げた。
今回の依頼も部分的にスプライトを使っているようで、swf.vfpではうまく変換出来なかった。

ニコニコが出来て2年以上が経ち、βやγの頃は少なかった手描き動画も今では大量に投稿されるようになった。
つべ板の手描き動画スレを覗いてみれば、トレス/非トレス/二次創作ではない完全なオリジナル(これは少ないみたいだけど)と、皆さん色々誘惑に耐えながら「日産10枚」とか「半年かかった」とか、なかなか大変そうなご様子である。

筆者は昔、某エロゲのプレイ動画を投稿していたことがあるのだが、シリーズ2本を完結させたところで投稿することをやめてしまった。
画面をキャプチャーしながらゲームをするという作業に嫌気がさしたのだ。
ああマンドクサ、やってらんねぇ…。

もともとプレイ動画なんてものは、手描きに比べればかかる労力は遥かに低い。多少編集に凝ってみたところでたかが知れている。ましてやアクションゲームではなくエロゲである。気を付けることなんてテキストを送るスピードをどの程度にするかくらいのものだ(あとは〇〇なシーンの修正とか…)。

そういう人間であるから、彼/彼女らの書き込みを眺めていると、その情熱には本気で感心してしまう。

キャプチャーしながらゲームをするのは嫌だったが、編集とエンコードは結構楽しめた。
特にエンコードは楽しい。
限られた容量、ビットレートのなかで、いかにしてより良い結果を叩きだすか…うん、いいねぇ。

とりあえずエンコだけならそんなに手間はかからないし、平均点くらいはもらえる程度の知識は持っているつもりなので、他人の作った動画のエンコを代わりにやるというお遊びを、かれこれ2年ほどやってきたわけだが、今回のような依頼をこなす際にいつも考えることがある。
「もし代理でエンコするような人がいなかったらこの人はどうしたのだろう?」
「そもそも自分のここ数カ月の労力の結晶を他者に委ねるということに抵抗はないのだろうか?」
「ちょっと調べれば自分で出来るだろうに…」

そう、「ちょっと調べれば」自分で出来るだろう。
でも現実にはそれが出来ない人がいるわけである。
おそらく彼ら/彼女らは、動画のエンコードという行為に楽しさをあまり感じることがないのだろう。好きでないことに取り組んだところで良い結果が生まれることは殆どない。これが受験とかならば嫌でも頑張るしかないわけだが、ましてや趣味の世界のこととなればなおのこと。

筆者は絵を描くという行為に何ら喜びを見いだすことがないため、幼少の頃から禄に落書きすらしなかった人間である。

多分、これと同じことなんだろうなぁ。

2010年1月11日月曜日

接触事故?

父親が自転車と接触事故を起こしたらしい。
話を聞いてみると、信号を左折中に直進してきた自転車が車体の左後部にぶつかった模様。
相手側(女性)には怪我もなく、自転車も壊れてはいないようなので、大事には至りそうにないが、なにやら父の「後方不注意」とかいってゴネたがっているらしい。
さて、どうなることやら。

ベネディクト戦記 エンコード設定

この前筆者がエンコした動画に「エンコ設定教えてよ」というコメントがついていたので、ここに書いておくことにする。


0.使用したものとか

エンコード素材:
DVDレコーダーによる録画(VOBファイル、19725フレーム、10分58秒)

使用ツール:
DGMPGDec 1.5.7
AviSynth 2.5.8MT(SEt)
VirtualDub 1.9.8(プレビュー用)
avs2yuv.exe
pipebuf.exe
x264.exe (rev1376/64bit)
wavi.exe
neroaacenc.exe 1.5.3.0
mp4box.exe

なお解説にあたってはファイルパスは省略

1.d2vファイルと音声ファイルの作成
DGIndex.exe -ai source.vob -o source -ia 3 -fo 0 -yr 2 -om 2 -hide -exit >null

2.avisynth scriptの作成
#ベネディクト戦記 #16 movie.avs
SetMemoryMax(1024)
SetMTMode(2,0)
LoadPlugin("DGDecode.dll")
LoadPlugin("NicAudio.dll")
LoadPlugin("YadifMod.dll")
LoadPlugin("NNEDI2.dll")
LoadPlugin("mt_masktools-25.dll")
LoadPlugin("RemoveGrainSSE2.dll")
Import("LimitedSharpenFaster.avs")
LoadPlugin("mvtools2.dll")
LoadPlugin("AddGrainC_11.dll")
#メモリリーク回避のためver.1.1を使用
LoadPlugin("Gradfun2db.dll")
Import("Gradfun2dbmod.avs")
Import("GrainFactory3.avs")

#映像、音声の読み込み
MPEG2Source("source.d2v", cpu=6) #ブロックノイズがひどいのでcpu=6
AudioDub(NicAC3Source("source T80 2_0ch 256kbps DELAY24ms.ac3", channels=2))
DelayAudio(0.024)
Normalize(volume=1.0,show=false)

#動画の開始部分の崩れた映像を1秒弱削る
Trim(25,0)
#インターレース解除
#60fps? ニコニコでは再生重過ぎ&ビットレート足りないだろjk
interp=NNEDI2(qual=3)
YadifMod(edeint=interp)

#周囲の黒ベタを全部削り、16:9にリサイズ
#アスペクト比はほんの少し狂うが、画面の大きさ&見やすさ優先
Spline36Resize(768,432,15,21,-17,-16)
#とにかくボケボケのソースなので思いっきりSharpenかけてから512x288にリサイズ
Sharpen(1.0)
LimitedSharpenFaster(dest_x=512, dest_y=288, SMode=4, LMode=4, strength=200)

#30fpsの動きの悪さをごまかす&ビットレート削減のため、ちょっと強めにモーションブラー
#ベネディクト戦記はやたら動きが激しいので、モーションブラーかけるとカッコイイ(と思う)
super=MSuper()
bw_vec=MAnalyse(super, isb=true)
fw_vec=MAnalyse(super, isb=false)
MFlowBlur(super, bw_vec, fw_vec, blur=45)

#壁や地面ののっぺり対策にディザとシルバーグレインをかける
#ただし、明部にかけるとノイズが目立ちすぎるので、中間部と暗部のみ
GradFun2dbmod(custom="GrainFactory3(g1str=10, g2str=10, g3str=0, g1shrp=50, g2sharp=50,g1size=1.4, g2size=1.1, th3=120, th4=120)
Distributor()
return last #スクリプト終了

3.音声のエンコード
とりあえずHE-AACで64kbps使っとけば、まず音質で文句はでない
wavi.exe movie.avs audio.wav
neroaacenc.exe -br 64000 -2pass -if audio.wav -of audio.aac

4.映像のエンコード
基本方針はプレミアム会員のファイルサイズ100MBをほぼ使い切る&多少のノイズは気にしないでディテール重視。
x264は非常に優秀なので、あれこれオプションをいじってもいいことは殆どない。適当に任せておけば、うまいこと良い感じに誤魔化してくれる。
pipebuf.exe avs2yuv.exe movie.avs -o video.y4m -o - : ^
x264_x64.exe - stdin y4m --pass 1 --bitrate 1182 --tune film --bframes 5 --b-pyramid normal --direct auto --weightp 0 --keyint 300 --aq-mode 2 -o null

x264_x64.exe video.y4m --pass 2 --bitrate 1182 --tune film --bframes 5 --b-pyramid normal --ref 8 --keyint 300 --direct auto --me umh --subme 10 --trellis 2 --colormatrix smpte170m
--weightp 0 --no-dct-decimate --aq-mode 2 -o video.264

5.映像と音声を結合
mp4box.exe -add video.264:fps=30000/1001 -add audio.aac -new result.mp4

以上で全行程終了
所要時間 約1時間半(Core2Quad Q9450 定格 / Windows7pro x64 / メモリ8GB)

6.最後に
筆者は、このゲームをやったことはおろか、実物を見たことすらありません(近所のゲーセンには入っていませんでした)。
仕方が無いので、画質に関しては自分の好み&視聴者受けしそうな感じになるように、適当にフィルターかけていじってます。
いままでのシリーズ16回のうち14回は自分がエンコしました。
もし変だったらごめんね、ベネディクトさん...

活動記録

10日(日)
朝っぱらからニコニコ用代理エンコを2本(依頼人は同一)
内容:作業用BGM
ソース:VC-1

始まりました

いつまで続くことやら…。