2009年12月19日土曜日

iMovie 08 でニコニコ動画にアップロードするための動画をエンコードする設定まとめ

皆さんご存じニコニコ動画。Windows環境で動画を作ってアップするための情報はたくさんあるのですが、Mac環境用のネタが少ないので、メモしておきます。

参考にしたページは以下の通り。
http://d.hatena.ne.jp/KZE/20091106/p1

http://www.smilevideo.jp/static/www/help/#000562

http://nicowiki.com/encode.html


■環境編
Mac OS X 10.6.2 Snow Leopard
iMovie 08
QuickTime Player X (Snow Leopard付属)

iMovieは08を使用します。各所でお勧めされているiMovie HDであれば高性能でflvも扱えるらしいのですが、新しいソフトを入れて管理するのが面倒という理由により却下です。また、iMovie 09からは動画クリップごとの再生速度管理もできるらしいので、kskとかスローモーションの演出もできるためそっちのほうがお勧めです。

エンコの際にはQuickTimeを利用してエンコするため、一応QuickTimeのバージョンも載せておきました。たぶんLeopard付属のQuickTime Player 9とかでもうまくいくと思います。


■エンコ設定編
まず注意点として、私はプレミアム会員なので、以下の設定はプレミアム会員用に合わせています(ビットレート最大1000Kbps程度、ファイルサイズ最大100MB)。一般会員の方はビットレートを落とせばそのまま利用できるかと思います。

さて肝心の設定内容ですが、http://d.hatena.ne.jp/KZE/20091106/p1で解説されている内容とほとんど同じです。iMovie 08からはそのままflvを書き出すことができませんので、mpeg-4 H.264でエンコードします。具体的には以下の通り。
  1. メニューの「共有」から、「QuickTime を使用して書き出す」を選択する
    Cmd+Eの「ムービーを書き出す」では上手くエンコできませんので注意。
  2. 「書き出し」欄は「ムービーからMPEG-4」を選択する
    ここで「ムービーからQuickTimeムービー」を選択するとどんなに上手くエンコしてもニコ動側で再エンコされてしまいます。絶対に「ムービーからMPEG-4」を選択すること。
  3. 以下の画像のように設定する



    一番上のファイルフォーマットを「MP4(ISMA)」から「MP4」にしないとH.264でエンコできませんので、まず最初に変えておくこと。
    一般会員の方はムービーのデータレートをもっと落としてください。300ぐらいかな?逆に600より上げる必要はよっぽど画質が気になるか短い動画でもないかぎり無いと思います。ビットレートについては私なんぞよりもまとめWikiなどのほうが詳しいのでそちらをご覧ください。
  4. 「ストリーミング」の「ストリーミングを使用する」チェックボックスは入れない
    入れても大丈夫かどうかは未確認ですが、余計な物を入れると変なことになるのではと思い外してます。入れた方がいいのかな・・・

■仕上がり編
上記の設定でエンコしてみた結果がこちら。


特に問題なく見られていると思います。ただしエコノミー回避はしていないのでエコノミーが発動すると悲惨なことになりそうですが・・・


■FLVでエンコしたい編
FLVでエンコしたい場合や、もっと詳細な設定がしたい場合には、ffmpegXというツールを使うと良いようです。試していないのでここでは割愛します。
その他、iMovieから直接FLVでエンコできるようにする方法もあるらしいです。しかしH.264で直接アップロードできるようになった今となっては別にFLVにこだわるメリットも無いかも。

2009年12月16日水曜日

bulkloader.py を使って Google App Engine の本番サーバーから開発サーバーにデータを移す

Google App Engine SDKの開発サーバーのデータストアはtmpディレクトリにデータを保存するため、マシンを再起動するとデータの中身が全部消えてしまいます。毎回テストデータを用意するのが面倒なので、本番サーバーからデータを移してくるための方法を調べてみました。するとbulkloader.pyというユーティリティを使うと、簡単に本番サーバーのデータをダウンロードして保存し後からリストアすることができることがわかりました。ということで早速試してみます。
参考にしたのは以下のサイト。
http://code.google.com/intl/en/appengine/docs/python/tools/uploadingdata.html

※2010/01/31追記:--db_filenameオプションの使い方を掲載しました。


■前準備
app.yamlに以下の設定を追加してから、appcfg.py updateで本番デプロイを行います。
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
これだけで準備ばっちりです。余談ですが、app-engine-patchを使うと、最初からこの設定がapp.yamlに含まれています。


■使用方法
本番サーバーからローカルにデータをダンプするときは以下のコマンドを実行します。
bulkloader.py --dump --kind=<kind> --url=http://<appname>.appspot.com/remote_api --filename=<data-filename>
たとえば私のアプリからhon_heroという名前のModelのデータをダンプしたいときには、
bulkloader.py --dump --kind=hon_hero --url=http://akisutesama.appspot.com/remote_api --filename=hon_hero.dump
などとするとうまくいきます。

ダンプしたデータを本番サーバーにリストアするときは以下のコマンドを実行します。
bulkloader.py --restore --kind=<kind> --url=http://<appname>.appspot.com/remote_api --filename=<data-filename>
--dumpが--restoreになっただけです。本番障害でデータが失われたときにリストアするためのコマンドなので、実行すると本番サーバーのデータがすべてダンプした地点のデータに置き換えられます。ご利用の際には細心の注意を!

ダンプしたデータをローカルサーバーに入れるときは以下のコマンドを実行します。
bulkloader.py --restore --kind=<kind> --url=http://localhost:8080/remote_api --filename=<data-filename> --app_id=<appname>
本番だけではなくてローカルサーバーにもリストアができます。ローカルサーバーにリストアする際の注意点として、
  • dev_appserver.pyでアプリケーションが動いている必要があります。
  • --urlオプションをローカルホストに書き直す必要があります。
  • --app_idオプションで、自分のアプリケーションのapp_idを指定してやる必要があります。
これでローカルテストがだいぶ楽になりました。

同様にして、本番からデータをダンプしてローカルに入れるだけでなく、ローカルからデータをダンプして本番に入れることもできます。新しく実装した箇所に最初からデータを入れたい場合などに使えると思います。


■log, progress, resultを賢く使う
bulkloader.pyを実行すると、デフォルトでは以下のような名前のファイルが自動的に生成されると思います。
bulkloader-log-20091211_145622.log
bulkloader-progress-20091211_145622.sql3
bulkloader-result-20091211_145622.sql3
これらはそれぞれ「ログファイル」「現在どのエンティティまでダンプされたかを格納するデータベース」「実際にダンプした内容を格納するデータベース」となっており、上手く使えば2回目以降のダンプ実行時間を劇的に短くすることができます。

ログファイルを指定する際には--log_fileオプションを、データベースを指定する際には--db_filenameと--result_db_filenameを、それぞれ指定してください。たとえば、以下のようなシェルスクリプトを用意しておくと便利です。
#!/bin/sh

# 前回の実行結果が残っているとエラーになる(上書きしてくれない)ので、まずいったん消す
if [ -e hon_hero.dump ]; then
rm hon_hero.dump
fi
# bulkloader.pyを実行する
# db_filenameとresult_db_filenameは一緒のファイルを指定してもかまいません。
# (その場合は、一つのsqlite3データベースに一緒に格納されます)
# db_filenameとresult_db_filenameは、db_fileやresult_db_fileのように短縮して書いても動作するみたいです
bulkloader.py --dump \
--url=http://akisutesama.appspot.com/remote_api \
--kind=hon_hero \
--filename=hon_hero.dump \
--log_file=bulkloader-log-hon_hero.log \
--db_file=bulkloader-progress-hon_hero.sql3 \
--result_db_file=bulkloader-progress-hon_hero.sql3
こうすることで、2回目以降はbulkloader-progress-hon_hero.sql3の中身とリモートのdatastoreの中身を比較して、追加更新のあったもののみをダウンロードし、それ以外はローカルに保存してあるデータベースの中身を利用するので、劇的に処理が速くなります。結果はこちら。
[INFO    ] Connecting to akisutesama.appspot.com/remote_api

[INFO ] Have 2610 entities, 2610 previously transferred
[INFO ] 2610 entities (974 bytes) transferred in 0.4 seconds
1回目のロードには130秒かかったのですが、2回目はすべてローカルに保存されているデータを使ったので、なんと0.4秒で済んでいます。

こうしてダンプしたデータをローカルサーバーでリストアするときは、たとえば以下のようなシェルスクリプトを使います。
#!/bin/sh

# --db_fileと--result_db_fileには先ほどのダンプ時に指定したものとは別のファイルが必要になります
# (先ほどのデータベースはappspot.com用として設定されるので、localhostで使用するとエラーになってしまいます)
# --db_fileと--result_db_fileには特別な名前としてskipを指定することができます
# この名前を使用するとデータベースへの書き込み/読み込みを行いません
bulkloader.py --restore \
--url=http://localhost:8000/remote_api \
--app_id=akisutesama \
--kind=hon_hero \
--filename=hon_hero.dump \
--log_file=bulkloader-log-restore.log \
--db_file=skip \
--result_db_file=skip


■注意点
appspot.com以外のサーバー(たとえばlocalhostなど)からデータをdumpしたりrestoreしたりする際には、必ず--app_idオプションを指定する必要があります。これを忘れていて詰まりました><

もし特定の条件を満たすデータのみをダウンロードしたいという場合などは、設定ファイルをPythonで書く必要がありますが、appcfg.py download_dataを使うと良いと思います。

2009年12月13日日曜日

Highcharts.js を使ってみた


最近IDEA*IDEAさんで取り上げられていたHighcharts.jsを試してみましたので、躓いた点などをメモしておきます。


■公式サイト
http://www.highcharts.com/
ダウンロード、更新履歴はこちらから見られます。ライセンスもこちらに記載があります。
個人利用、教育目的の利用、および非営利組織での利用については無料ですが、商用利用の際にはライセンスの購入(1サイト$80、複数サイト$360)が必要になるので注意です。


■公式リファレンス
http://www.highcharts.com/ref/
おそらく全部JSで実装されているのだと思いますが、凄いクオリティ高いです・・・


■実際に導入してみて躓いたポイント
以下、すべてバージョン1.0.2(2009/12/09)での気づきです。
グラフを描画する領域のサイズは、CSSでは定義できない、直接style属性に書く必要がある
たとえばCSSを使って、
<style>#chart_area {width:800px; height:400px;}</style>
<div id="chart_area" ></div>
のようにしても描画時に無視され、高さが0になります。必ず直接style属性を用いて
<div id="chart_area" style="width:800px; height:400px;"></div>
のように書く必要があります。

Zoom機能を使う際、画面のスクロールが発生すると選択領域がバグる
Mac OS X 10.6上のFirefox3.5.6とSafari4.0.4にて再現。他のブラウザは未チェックです。論より証拠、こちらのページを開いて、少し画面全体を下にスクロールしてから、チャートを縦にドラッグしてY軸ズームしようとしてみてください。まぁ、ひどいバグなのですぐに直るとは思いますが。

seriesに与えるデータは、必ずX軸方向の昇順にソートされている必要がある
特にxAxisにdatetimeを指定しているときが危険です。たとえばこのようなデータはNGです。
series: [{
name: 'Plague Rider',
data: [[Date.UTC(2009, 12, 4), 57.4],
[Date.UTC(2009, 12, 3), 57.6],
[Date.UTC(2009, 12, 2), 59.1]]
}]
かならずこのようにソートしなければなりません。
series: [{
name: 'Plague Rider',
data: [[Date.UTC(2009, 12, 2), 59.1],
[Date.UTC(2009, 12, 3), 57.6],
[Date.UTC(2009, 12, 4), 57.4]]
}]
ソートされていないと、チャートにマウスカーソルを合わせてもラベルが表示されなくなります。気づきにくいバグでした。

seriesに与えるデータにnullがあると、0として扱われる
そのため、たとえば12月1日は100、12月2日は110、12月3日はデータが分からないのでnull・・・とすると、12月3日のところだけいきなり0になってグラフが滅茶苦茶になります。回避方法としてはxAxisのtypeをdatetimeにするか、yAxisのminを自分で計算して指定してください。

xAxisのtypeがdatetimeのとき、連続していないデータがあるとsplineは使用できない(lineは使用できる)
原因は不明です。たぶんバグじゃないだろうかと思ってますが、公式のxAxisのtypeがdatetimeなサンプルを見てもsplineではなくてlineを使っているのでひょっとしたら仕様かもしれません。

■まとめ
公開されたのがつい先月の末ということで、まだちょっとBuggyな感じです。また、エラーメッセージがまともに表示されないため、JSファイルのどこでエラーになっているかはわかっても原因が何か分からないなど、デバッグが結構大変です。しかしながらデザイン美麗で機能豊富、カスタマイズも容易と、一通り優れた点は持ち合わせていると思います。PrototypeやjQueryなど他の外部ライブラリに依存しないのも良い点です。$80なら支払ってもよいのでは?


■Google Charts APIとの比較
やはり気になるのはGoogle Charts APIと比べてどちらが使えるかでしょう。ちょっと調べてみました。ただしGoogle Charts APIについては実際に試したことがないのであくまで公式ページのドキュメントを見て気づいた点のみです。間違っていたらごめんなさい。
Highcharts.jsの優れている点
  • 美麗なデザイン
  • ズームや特定データの一時消去、ラベル表示など、対話性に優れたUI
  • 単体のJSファイルなので外部のサーバに依存しない
  • Ajax対応が容易

Google Charts APIの優れている点
  • より多数のグラフに対応(レーダーチャートや地図など)
  • 商用利用でも完全に無料