ページ

2015-04-23

PowerShellからRazorテンプレートエンジンを使ってみた

以前のCottleの記事で書いた通り、去年の7月(!)にPowerShellとRazorの話をしたのですが、資料をアップロードしました。上げてなかったのは、Cottleの記事に書いた通り、向いてなくね、と思ったからなのですが、Razorだからこそうれしいケースがなくもなさそうだったので、とりあえず資料を上げるだけ上げることにしました。



その中使っていたスクリプトがこちら。


DynamicViewBagがModelってナニソレって感じなんですが、このRazorEngineは、Modelクラスを作って渡すことを想定されているので、クラスを作るのが大変なPowerShellからはまっとうな呼び方をするのが難しかったのです。いわば抜け穴。これを探してたのは、LTしませんかと現場で言われてから発表までの話なので、もうちょっと頑張ればいい方法があるかもしれませんが、がんばってません。ASP.NET MVC屋的に気持ち悪いだけで、名前がアレなのを除けば、PowerShellとのつなぎという意味ではそれほど悪くないかなとも思っていますが、このまま行くか頑張って直すかは使われる皆様の判断にお任せします。

ちなみにおすすめはC#からRazorEngineを使う、です。

追記
RazorEngineのソースを見たところ、当時読んでたソースとだいぶ変わっているようです。もしかすると、こんなややこしい呼び方は要らないかもしれません。もし動かないとかあれば、RazorEngineのソースをご確認ください。

追記2
altriveさんが、ModelにPSCustomObjectを渡す例を書いてくれました。一度コンパイルするといいらしいです。要ちぇっく。
https://gist.github.com/altrive/2f048e4c78398c055090

2015-04-16

Python + PyAV/Pillowでテスト用動画を生成する

動画を触っていると、テスト用の動画が欲しくなるのだけど、そこらを撮るとセキュリティやプライバシーが心配だし、かといってWebで探すのも好みのサイズや長さじゃないしで、自分で適当に動画作れるのが一番じゃね?ということで、さらっと作る方法を試してみた。

いくつか試して実際にできたのが、Pillowで画像を生成し、PyAVというffmpeg/avconvのライブラリlibavのPythonラッパーで動画化するという方法。ちなみに試してたのはUbuntu 14.04。

準備

依存ライブラリインストール

sudo apt-get install libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev
Pillowに必要なパッケージが他にあったかも。

Pythonライブラリのインストール

pip install Pillow
pip install av
pipはvirtualenv下のやつを使うのがいいと思う。requirements.txt作れって?

すると、こんなスクリプトで生成できる。drawのところをちょいちょい変えたり、backgroundの色を調整したりすればいいかな。

けっこうローレベルな触りかたをしてしまった…

PyAVはimageにto_string()を呼んでくるのだけど、Pillowにはないので、tobytesを呼ばせるHackをしてある。

ちなみに、以下の感じでも目標が達成できることは後でわかった。なお音入り。avconvでもtestsrcはできるけど、sineはない。
ffmpeg -y -filter_complex testsrc=size=1280x720:rate=ntsc -filter_complex sine=f=440 /tmp/hoge.avi

2015-04-15

画面を動画キャプチャするツールScreenCaptureWrapperを公開

デスクトップ画面を範囲選択して動画キャプチャするツール「ScreenCaptureWrapper」をリリースしました。

https://github.com/sunnyone/ScreenCaptureWrapper/releases よりダウンロード可能です。

と、こう書くとなんだか大変なことをしているように見えますが、単なるffmpegのラッパーなので、お好きな場所からffmpegをダウンロードするか、自分でビルドしておく必要があります。

最近のffmpegであれば、映像だけに関してはgdigrabという機能を使えるので単体でOKですが、音声が必要な場合、screen-capture-recorder DirectShowフィルタが必要です。

まぁ座標選択のUIがついていたりと、スクリーンキャプチャ用のUIになっていますが、config.ymlに書かれた引数テンプレートを展開して実行しているだけなので、恐らく別のビデオソースから読み取って出力するなんてことも可能だと思います。

出力は「後処理が前提ならやっぱHuffyuvじゃね?」ってことで今時Huffyuv / PCMになっていますが、好きにコマンドラインオプションを取り替えてもらえばいいです。(2015/5/13追記:0.0.2でwebmを足してみました。)

画面キャプチャするツールなんて山ほどあるんじゃないかと思いますが、「ウォーターマークが入ったりフォーマットに制限があったりややこしい→ffmpegでできるんじゃね?→できるじゃん→コマンドラインで座標指定するのめんどくさ」という流れでこれが登場しました。

ということで、 機会があればどうぞお使いください。

ライブラリ紹介

例によってC#のWPFアプリですが、使っているライブラリの紹介です。

Caliburn.Micro

MVVMフレームワークです。デフォルトでは、同じ名前のViewとViewModelを自動でバインドしたり、TextBoxやButtonのx:NameとViewModelのプロパティをバインドしてくれたりと、いろいろ自動な感じで動くライブラリです。とまぁそのあたりはかつてのRailsのscaffoldみたいに釣り的意味合いのおまけで、基本的には、メッセージングの仕組みだとか、このライブラリのありがたさはそういった枠組みの部分でしょう。このくらいの規模でも、さらっと書けるようになるし、入れといてもいいかなという感じです。

オブジェクトが必要になると、解決して引いてくるstyleなので(この観点ではサービスロケータって言うのかな?)、DIコンテナフレームワークを併せて使うほうが便利だと思います。サンプルではMEFの例がありました。自分だったらあと1個ウィンドウが来たらAutofacと連携させます(手元には実際にそうやったプロジェクトがある)。

YamlDotNet

.NETのYAMLシリアライザ・デシリアライザです。プリセットのUI作るのが面倒だったので、ymlに持っているので使っています。まぁ、普通な感じです。この手のファイルはJSONでいいかなと思っていたのですが、コメント書けないしWindowsパスはエスケープしなきゃいけないしでイマイチなので、YAMLは現実的かなと思います。

Cottle

前の記事で使ったテンプレートエンジン。コマンドライン引数の展開に使っています。


作っていまさら、ffmpegのラッパーならLinuxでも同じ仕組みでいけそうだし(実際x11grabがある)、もうちょっとクロスで行ける造りにすればよかったなぁと思ったりもしますが、そうしたら一晩でできなそうなので、まぁよかったのかなという感じです。

2015-04-07

シェルスクリプトでゲームパッドのボタン入力をキー入力に変換する

ステップオーバーやステップインなどの作業はF7, F8などにバインドされていることが多いが、IDEによって異なるので、Windowsではゲームパッド/ジョイスティックのボタン入力にバインドしていた。Ubuntuでも同じようなことがしたいなぁと思ってやってみた。最終的なキーの対応は、こんな感じ。


パッケージのインストール

ツールが入っている「joystick」パッケージと、GUIで確認できる「jstest-gtk」パッケージをインストールする。
# apt-get install joystick jstest-gtk
これで、jstest-gtkコマンドが使えるようになるので、GUIで見ながら動作するかどうかを確認する。マッピング変更もできるらしい。jstest /dev/input/js0 などとすると、コマンドラインでも確認できる。

普通の使い方

さらに「xserver-xorg-input-joystick」パッケージをインストールし、Xを再起動すると、スティックがマウスカーソルに、ボタンがマウスボタンのように使えるようになる。Xの設定やら、xbindkeysの設定などすればそれはそれで良い感じで使えると思う。が、今回は消した。

シェルスクリプトで処理する

ただ、Xの入力に変換すると、どこのインプットデバイスから来たのかなど設定が面倒そうなので、(cf. Multiple keyboards)今回はシンプルにシェルスクリプトと先ほどのjstestコマンド、それからキー操作がコマンドでできるxdotoolコマンドでやることにした。

jstest --event /dev/input/js0 とすると、以下の感じで1行1イベントで飛んでくる。type 1がボタンのイベントで、numberがボタンの番号、valueがpress/releaseを意味している。type 2は軸の動作。

releaseだけ見ておけば使える感じになったので、こうなった。

sedにはバッファしない-uオプションを忘れないようにしないと、流れてこなくなる。

Pythonで処理する(おまけ)

jaraco.inputで一応できたけど、余計なイベントが飛んでくる感じだったので、もう少し気合を入れて実装しないといけなそうだった。今回は、コマンド実行するだけなのでシェルスクリプトで行くことにした。なお、pipでインストールできるjaraco.input 1.0.1はバグっていて、コンストラクタの処理を肩代わりしないといけないのに注意。最新版はもう少し頑張っている模様。

2015-04-03

Ubuntu 14.04でLogicool TrackMan Marbleを左利き設定で使う

たまにやってくる右手の指の付け根の痛みが来たので、緩和策を打つべくトラックボールを買ってきた。機種は、Logicool TrackMan Marble

普通に右利き用としてはそこそこ機能するのだけど、左手で使いたいので、左手用に設定する。

Xの設定

 /usr/share/X11/xorg.conf.d/20-trackman.conf
Section "InputClass"
  Identifier "Marble Mouse"
  Driver "evdev"
  MatchProduct "Logitech USB Trackball"
  MatchDevicePath "/dev/input/event*"
  MatchIsPointer "yes"
  Option "ButtonMapping" "3 2 1 4 5 6 7 8 9"
  Option "EmulateWheel" "true"
  Option "EmulateWheelButton" "9"
  Option "YAxisMapping" "4 5"
  Option "XAxisMapping" "6 7"
EndSection

最初のほうはこのマウスにマッチさせる設定。

Option "ButtonMapping"は、1 2 3 4 5 6 7 8 9の物理ボタンを、どのボタンとして割り振るかという設定。今回は3と1、すなわちleft clickとright clickを交換する。
元のボタンは、1=左ボタン(大)、3=右ボタン(大)、8=左ボタン(小)、9=右ボタン(小)。詳しくはArch Wikiを参照。

EmulateWheel以下は、「9」すなわち右ボタン(小)を押しながらボールを操作することによって、上下左右のスクロールをできるようにする設定。

設定の確認

これが効いていることの確認。

xinput listでデバイスを探しだす。
$ xinput list
⎡ Virtual core pointer                     id=2 [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer               id=4 [slave  pointer  (2)]
⎜   ↳ Logitech Unifying Device. Wireless PID:402d id=11 [slave  pointer  (2)]
⎜   ↳ Logitech USB Trackball                   id=12 [slave  pointer  (2)]
⎣ Virtual core keyboard                    id=3 [master keyboard (2)]
    ↳ Virtual core XTEST keyboard              id=5 [slave  keyboard (3)]
    ↳ Power Button                             id=6 [slave  keyboard (3)]
    ↳ Video Bus                                id=7 [slave  keyboard (3)]
    ↳ Power Button                             id=8 [slave  keyboard (3)]
    ↳ USB Keyboard                             id=9 [slave  keyboard (3)]
    ↳ USB Keyboard                             id=10 [slave  keyboard (3)]
    ↳ Eee PC WMI hotkeys                       id=13 [slave  keyboard (3)]

id=12だとわかる。あとはxinput get-button-mapで確認する。
$ xinput get-button-map 12
3 2 1 4 5 6 7 8 9 
3と1が入れ替わっていることがわかる。

ちなみに、xinputには他の機能もある。set-button-mapにすれば一時的に設定を変えることも可能だし、list-propsで詳しい情報を得ることも可能だ。
$ xinput list-props 12
Device 'Logitech USB Trackball':
 Device Enabled (143): 1
 Coordinate Transformation Matrix (145): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
 Device Accel Profile (275): 0
 Device Accel Constant Deceleration (276): 1.000000
 Device Accel Adaptive Deceleration (277): 1.000000
 Device Accel Velocity Scaling (278): 10.000000
 Device Product ID (264): 1133, 50184
 Device Node (265): "/dev/input/event16"
 Evdev Axis Inversion (279): 0, 0
 Evdev Axes Swap (281): 0
 Axis Labels (282): "Rel X" (153), "Rel Y" (154)
 Button Labels (283): "Button Left" (146), "Button Middle" (147), "Button Right" (148), "Button Wheel Up" (149), "Button Wheel Down" (150), "Button Horiz Wheel Left" (151), "Button Horiz Wheel Right" (152), "Button Side" (268), "Button Extra" (269)
 Evdev Middle Button Emulation (284): 0
 Evdev Middle Button Timeout (285): 50
 Evdev Third Button Emulation (286): 0
 Evdev Third Button Emulation Timeout (287): 1000
 Evdev Third Button Emulation Button (288): 3
 Evdev Third Button Emulation Threshold (289): 20
 Evdev Wheel Emulation (290): 1
 Evdev Wheel Emulation Axes (291): 6, 7, 4, 5
 Evdev Wheel Emulation Inertia (292): 10
 Evdev Wheel Emulation Timeout (293): 200
 Evdev Wheel Emulation Button (294): 9
 Evdev Drag Lock Buttons (295): 0

GNOMEの左手設定の罠

上記のget-button-mapで、以下のように1と3が入れ替わっていないことがある。
$ xinput get-button-map 12
1 2 3 4 5 6 7 8 9 
1と3以外なら変更が効く、大変に腹立たしい状況。

こんなことがないか検索したところ、mouse - X11/Gnome/TrackPoint: custom button mapping not working - Super Userという記事に情報があったので、期待を膨らませて実行するも変わらず。
$ gsettings set org.gnome.settings-daemon.plugins.mouse active false

だいぶ悩んだが、「マウスとタッチパッド」設定の「左利き」に関係があるだろうと思い、変更してgsettings list-recursivelyのdiffを取ってみると、org.cinnamonなんちゃらというキーが変わっていることに気付き、まさかと思って探してみるとgnomeをcinnamonに変えただけのキーが存在したので、以下を実行して解決。
$ gsettings set org.cinnamon.settings-daemon.plugins.mouse active false
悲しい結末だった。