feed

2015年05月05日, 編集履歴

動画ファイルからより良いアニメーションGIFを作る

QuickTime PlayerでスクリーンキャプチャしたMOVからベターなアニメーションGIFを作る」で書いた方法よりも、より良い手法が解ったので覚え書き。

 前回の手法をかんたんにまとめると、

  1. ffmpegを使って動画を連番画像に切り出す
  2. ImageMagickのconvertコマンドで連番画像をアニメーションGIFに纏める

だった。前回の手法の問題点は、手順2で処理に時間が掛かること、動画の内容によっては色味が変化、あるいは崩れる可能性があることだった。

 今回の手法はImageMagickは用いずffmpegだけを用いる。ffmpegはv2.6以上必須。動画はffmpegが扱えるならなんでも良いと思う。

 手順:

  1. ffmpegで動画で使われている色を元に最適化されたパレット画像を生成
  2. ffmpegでパレットを元にアニメーションGIFを生成

パレット画像の生成

 パレット画像を生成するには、以下を実行する。

$ ffmpeg -i input.mov -vf palettegen -y palette.png

 -i input.movで入力動画の指定、-y palette.pngで出力するパレット画像の指定。-vf palettegenでパレット画像の生成を指定(palettegenフィルタのドキュメント)。

アニメーションGIFの生成

 パレット画像を元にアニメーションGIFを生成するには、以下を実行する。

$ ffmpeg -i input.mov -i palette.png -lavfi paletteuse -y output.gif

 入力動画と共にパレット画像も指定し、アニメーションGIFを生成する。-lavfi paletteuseでパレット画像の使用を指定(paletteuseフィルタのドキュメント)。

結果

を以下に示す。

ファイルサイズ動画・画像処理時間
入力動画148KB
ImageMagick(前回の手法)709KB約23秒
ffmpeg、パレット画像不使用293KB約2秒
ffmpeg、パレット画像使用(今回の手法)663KB約6秒

 ImageMagickを用いる手法(前回の手法)では、

$ ffmpeg -i input.mov -r 20 frames/%03d.png
$ convert -delay 5 -layers optimize frames/*.png output-imagemagick.gif

パレット画像不使用の手法では、

$ ffmpeg -i input.mov -r 20 -y output-ffmpeg-normal.gif

パレット画像使用の手法(今回の手法)では、

$ ffmpeg -i input.mov -vf fps=20,palettegen=stats_mode=diff -y palette.png
$ ffmpeg -i input.mov -i palette.png -lavfi fps=20,paletteuse -y output-ffmpeg-palette.gif

を実行した。

 前回の手法で生成したアニメーションGIFはテキストエディタのウィンドウの背景が薄青く変色してしまっているのが解る。これはまだましな方で、動画によってはもっと大きく色が崩れてしまったり、前フレームの残像が残ったりすることがある。パレット画像不使用の場合はドロップシャドウやメニューなど、半透明がからむ部分で編みかけのようになってしまっている。それらに比べて今回の手法で生成したものは、そういう画像の乱れが見られない。
 また、処理にかかった時間もパレット画像不使用に比べれば遅いものの、前回の手法の方よりは大幅に速い。出力ファイルサイズもパレット画像不使用よりは大きいが前回の手法よりは小さい、という結果になった。

おまけ(動画の切り抜き、拡大・縮小、FPSの変更)

 QuickTime Playerでスクリーンキャプチャする際、範囲選択の領域サイズが表示されないので、狙った領域サイズで収録するのが難しい。そこで、範囲選択を大きめに取って収録し、ffmpegを用いて切り抜き、縮小する方法を考える。

 切り抜きの場合、

$ ffmpeg -i input.mov -vf crop=640:480:52:0 -y output.mov

のようにする。-vf crop=640:480:52:0で切り抜きを指定(cropフィルタのドキュメント)。この指定の場合、元動画の左上を原点として(52, 0)の座標から領域サイズ640x480での切り抜きを行う。

 拡大・縮小の場合、

$ ffmpeg -i input.mov -vf scale=400:-1:flags=lanczos -y output.mov

のようにする。-vf scale=400:-1:flags=lanczosで拡大・縮小を指定(scaleフィルタのドキュメント)。

 FPSの変更は、

$ ffmpeg -i input.mov -vf fps=20 -y output.mov

のようにする(fpsフィルタのドキュメント)。

 切り抜きしつつ、縮小しつつ、FPSを指定して、パレット画像の生成をするには、

$ ffmpeg -i input.mov -vf crop=640:480:52:0,fps=20,scale=400:-1:flags=lanczos,palettegen -y palette.png

さらに、このパレット画像を使用してアニメーションGIFを生成するには、

$ ffmpeg -i input.mov -i palette.png -lavfi crop=640:480:52:0,fps=20,scale=400:-1:flags=lanczos,paletteuse -y output.gif

を実行する。

 ffmpegは引数指定が複雑で難しい。

余談

 今回の実験で使用した動画は、現在開発中の絵文字を入力するインプットメソッドの動作デモ。
 日本人的には、OS標準の日本語IMやATOK、Google日本語入力等の日本語インプットメソッドを通じて絵文字の入力はある程度容易に、いつも通りの操作で行えるが、ふだんインプットメソッドを意識しないで文字入力している層(英語圏など)はどうしているんだろうか。わざわざ文字ビューアを起動して、検索して、選択して、とやっているのか——そういうところから着想を得て現在鋭意開発中。ふだん通りの入力操作の延長上で絵文字をかんたんに入力できる環境を目指します。
 全世界の標準USインプットメソッドをこのEmoji IMで置き換えてやろうという野望を抱いています。

参考

2015年04月27日, 編集履歴

Murasaki ver. 2.3をリリースしました

 OS X用EPUBリーダMurasakiのver. 2.3をリリースしました。

 ver. 2.3は、

です。

 サイドバーメニュー上で右クリック(Control + クリック)でコンテキストメニューが出るようになりました。サイドバーからコンテンツを新しいウィンドウで開いたり、階層付きナヴィゲーションを一度にすべて展開したり折りたたんだりできるようになりました。

 EPUB内コンテンツ統合ウィンドウは、EPUB内のすべてのコンテントドキュメントを統合して一度に表示する特別なウィンドウです。コンテンツすべてを一度に選択、コピィ、印刷が行えます。ただし、統合ウィンドウではスタイルが多少崩れることがあります。今のところ横書きのみです。

 Spotlight / Quick Lookプラグインの改良は「OS XのEPUB用Spotlight/Quick Lookプラグインを作り直した」で最初から書き直したものに差し替えました。当初はMurasaki v2系には同梱しない予定でしたが、OS Xの不具合が解消されたことにより古いMac OS Xにも対応できるようになりました。

2015年04月06日, 編集履歴

迷惑メール相談センターに一年間迷惑メールを報告し続けた結果

迷惑メール相談センター」に迷惑メールを報告すると良いらしい(迷惑メールが減る)、という話を聞いたので実際にやってみた結果。

情報提供の方法

 迷惑メール相談センターに情報提供することで、その情報は以下のように使われる(「提供いただいた情報について」より引用)。

提供いただいた違反情報については、総務大臣及び消費者庁長官による違反送信者への措置、電気通信事業者による送信防止対策に活用させていただきます。

 迷惑メールの報告方法は、

である。
 私はOS XのMail.appで受信した迷惑メールを「すべてを選択」した後、コンテキストメニューから「添付ファイルとして転送」した。

 詳しい報告方法は、迷惑メール相談センターの「情報提供方法」を参照。

一年間報告し続けた結果

 一年間、受信した迷惑メールを迷惑メール相談センターに毎日報告し続けた結果が以下のグラフと表である。グラフの横軸が受信した月、縦軸が月間受信数で、集計期間は2014年4月1日から2015年3月31日である。迷惑メールの報告をし始めたのは2014年3月半ば。

迷惑メール受信数
受信月account 1の受信数account 2の受信数
2014年4月1099973
2014年5月11441148
2014年6月10161065
2014年7月1544981
2014年8月919701
2014年9月986643
2014年10月871513
2014年11月791569
2014年12月611435
2015年1月1150828
2015年2月664484
2015年3月694477

「account 1」は2014年7月に突出した受信数を見せるが、8月、9月になると6月時点と同程度、その後減少し、2015年1月の増加を除いて、その後は微増あるいは横ばいという状態。「account 2」は2014年12月までは減少傾向が、2015年1月の増加を除いて、その後は横ばい状態が見られる。
「account 1」で見られる2014年7月の増加も、両アカウントで見られる2015年1月の増加も、一時的な増加であり次月には前月程度の数に収まっているのが特徴的である。これらの時期(年初を起点とした半年スパン?)が迷惑メール送信側にとってなんらかの意味がある時期なのかもしれない。
 両アカウントとも、2014年7月、2015年1月を除いて、おおむね減少傾向が見られるのではないだろうか。集計期間の最初と最後である2014年4月と2015年3月で割合を見ると、「account 1」では約63%、「account 2」では約49%となった。

 実験に使用したふたつのメールアカウントは、十年以上前にインターネットを利用し始めた時からの、インターネットプロヴァイダから提供されたものである。これらのメールアカウントはインターネット利用開始初期のよく解ってない時期に、いろんな(いま思えば怪しげな)懸賞サイト等に登録してしまったものである。現在は(迷惑メール収集を除いて)まったく使用していない。

2015年04月04日, 編集履歴

OS XのEPUB用Spotlight/Quick Lookプラグインを作り直した

 OS XのEPUB用Spotlight/Quick Lookプラグインを作り直した。

 システム要件はとりあえずOS X 10.10以上。

 上記のバイナリィダウンロードのページからZIPをダウンロード・解凍し、所定のパスへ配置することでインストール。Spotlightプラグイン(EPUB.mdimporter)は、

Quick Lookプラグイン(EPUB.qlgenerator)は、

 プラグイン同梱版のMurasakiをインストールしている場合は、そちらが優先される可能性がある。そのときはFinderからMurasakiを選択して、コンテキストメニューの「パッケージの内容を表示」で中身を開いて、パッケージ内のLibraryフォルダを削除もしくはリネームする。

 プラグインをシステムに認識させるには、Macを再起動すると手数としては手っ取り早い。CLIが使えるならば、

$ mdimport -r /path/to/EPUB.mdimport
$ qlmanage -r

を実行する。

 この新しいプラグインをいつMurasakiに同梱するかは未定である。

 これまでMurasakiに同梱していたものと比べて、変更点は以下の通り。

Spotlightプラグイン

 EPUB仕様のヴァージョン文字列(2.0とか3.0)をメタデータとして収集し、検索対象になった。メタデータの内部項目名は「com_genjiapp_Murasaki_mdimporter_EPUB_EPUBVersion」で、表示名は「EPUB Version」および「EPUB バージョン」。たとえばターミナルで

$ mdfind "com_genjiapp_Murasaki_mdimporter_EPUB_EPUBVersion = '3.0'"

とすれば、EPUB仕様のヴァージョンが3.0のもののみが検索できる。FinderウィンドウからのSpotlight検索ならGUIで条件指定可能。

 Finderの「情報を見る」ウィンドウにEPUBのメタデータが表示されるようになった。

 「情報を見る」ウィンドウでのプレヴューは表紙画像のみ。

Quick Lookプラグイン

 各コンテントドキュメント(EPUB内部のXHTML)で指定されたスタイルをできるだけ保ちつつ、以前のものより表示品質を上げた(つもり)。コンテントドキュメントとしてXHTMLではなく画像ファイルが直接指定されているEPUBのプレヴューもできるようになった。

 Spotlight検索からのQuick Lookプレヴューは以下のような感じ。Spotlight検索でEPUBだけを対象にしたい場合は、以下の画像のようにkind:epubという条件を加えると良い。

 赤線による強調は画像処理による。画像のようにEPUB内の単語でSpotlight検索できていることが解る。

style要素のscoped属性

 Quick Lookでファイルをプレヴューさせる場合、プラグインはファイルの内容を取得・加工し、標準的な形式(画像やPDF、HTMLなど)にしてシステムに伝える必要がある。以前のものも今回のものも、EPUB内のコンテントドキュメント(多くの場合複数のXHTML)をひとつのHTMLにまとめ、システムに渡している。
 各コンテントドキュメントをひとつにまとめる処理は以下のような感じになる。

  1. EPUBのspineで指定された読み順にしたがいコンテントドキュメントを読み込む
  2. コンテントドキュメントの内容を抜き出し、div要素に詰め込む
  3. 抽出されたdivをひとつのHTMLに順に並べる

 ここで問題になるのが、各コンテントドキュメントで指定されているスタイルである。通常複数あるXHTMLコンテントドキュメントをひとつのHTMLにまとめているので、各コンテントドキュメントで指定されているスタイルが全体に影響を与えてしまう。(たとえば、本来ならば表紙ページにだけ適用されるべきスタイルがプレヴューされるHTML全体に適用される)。スタイル指定の記述を省くとまったくスタイルが当たっていない状態になるか、こちらで用意するスタイルを画一的に適用することになる。

 そこで有望視しているのが、HTML 5で追加されたstyle要素のscoped属性である。style要素にscoped属性を付けることで、そのstyle要素の親コンテナだけにスタイルを適用させることが可能になる。たとえば、

<p>...</p>
<div>
  <style scoped="scoped"> p { color: red; } </style>
  <p>...</p>
</div>

とすれば、div内のp要素だけにスタイルを適用できるようになる。
 残念ながらWebKit(HTML形式のプレヴューではWebKitが用いられる)は現在scoped属性に対応していない(確認した中ではFirefoxが対応している)が、今回のQuick Lookプラグインは各コンテントドキュメントのスタイル指定にscoped属性を付けるようにした。

 コンテントドキュメントの内容を抜き出す際、指定されているスタイル(style要素の内容とリンクされているCSSファイルの内容)をscoped属性を付けたstyle要素に入れていっしょにdivに詰め込むようにした。そうやってひとつにまとめられたHTMLは以下のような形になる。

<html>
  <body>
    <div>
      <style scoped="scoped">コンテントドキュメント1のスタイル</style>
      ...コンテントドキュメント1の内容...
    </div>

    <div>
      <style scoped="scoped">コンテントドキュメント2のスタイル</style>
      ...コンテントドキュメント2の内容...
    </div>

    <div>
      <style scoped="scoped">コンテントドキュメント3のスタイル</style>
      ...コンテントドキュメント3の内容...
    </div>
      
  </body>
</html>

 WebKitがscoped属性に対応していない現在では、各スタイル指定は各コンテントドキュメントの範囲を超えて全体に影響を及ぼす。その結果、表示に問題が出る可能性はあるが、EPUBの性質とリーディングシステムとの関係上、個別のコンテントドキュメントにあまり複雑なスタイルを当てることはあまりないはずで、これによる影響は少ないと思われる(少なくとも文字もののリフロー型では。固定レイアウト型は対象外)。
 それよりも、まったくスタイルが適用されなかったり、あるいは画一的なスタイル指定ではなく、個別のEPUBごとの雰囲気を再現する方針をとっている。将来、WebKitがscoped属性に対応すれば、スタイルの適用範囲が各コンテントドキュメントの範囲に限定されるようになるはずである。

2015年02月13日, 編集履歴

iTunesで再生中の曲にレート付けするウィジェットを作った

 OS X 10.10 Yosemiteから搭載された機能拡張(通知センターの「今日」ペインで動作する機能拡張を「ウィジェット」と呼ぶ)を用いて、iTunesで再生中の曲にレート付けをするウィジェットを作ってみた。ソースはGenjiApp/iTunes-Rating-Widgetで公開する。

Scripting Bridge

 iTunesからの情報取得や操作にはScripting Bridgeを用いた。Scripting BridgeはAppleScriptで操作可能なアプリケーションに対して、AppleScriptを用いずにObjective-Cからの操作を行うフレームワークである。

iTunesArtworkオブジェクトの謎

 Scripting Bridgeを用いてiTunesの曲情報を取得すると、アートワークはiTunesArtworkオブジェクトとして得られる(クラス名等の接頭辞iTunesは自分で設定可能)。このオブジェクトにはNSImage型のdataというプロパティがある。通常これを用いればCocoa環境で使いやすい画像オブジェクトが得られるはずである。
 アートワークがJPEG形式の場合、dataプロパティは問題なくNSImageが返すが、PNG形式だった場合、NSAppleEventDescriptorオブジェクトが返ってくるという謎の挙動を示す。仕方がないので、iTunesArtworkが持つ画像の生データrawDataプロパティを用いてNSImageを生成した。

com.apple.iTunes.playerInfoノーティフィケーション

 iTunesの再生・一時停止・曲送り・曲戻し操作の際には通知名「com.apple.iTunes.playerInfo」で通知が飛ぶ。これをNSDistributedNotificationCenterで捕まえて情報の更新を行った。

NSLevelIndicatorCellのハイライト

 NSLevelIndicatorを使うとiTunesのような星を用いたレート付けのGUIが作れる。しかし素のままで使うと、値が0のときに表示が何もなくなって解りづらい。レート付けの操作中、つまりハイライト時にはドットが表示されるので、NSLevelIndicatorCellをサブクラス化し、- (BOOL)isHighlightedが常にYESを返すようにしておいた。

コンテナアプリケーション

 機能拡張はそれ単体では開発・配布を行うことができず、主となるアプリケーションが必要になる。これをコンテナアプリケーションと呼び、コンテナアプリケーションに内包する形で機能拡張を開発・配布することになる。
 今回はそれは主眼ではないので、適当にシステム環境設定の機能拡張ペインを開くだけのものにした。システム環境設定の各ペインの実体は「/System/Library/PreferencePanes/」以下にあるので、目的のペインのURLを作成し、NSWorkspaceopenURL:メソッドで開いてやれば良い。