blog.katsuma.tv
2011年を振り返る
執筆
今年の目標、というかここ1,2年の目標で「本にモノを書いて自分が得た知見、考えをもとに価値を提供する」みたいなものをずっと考えていました。それがひょんな所からかなって、Web+DB PRESS vol.66で記事を書かせていただきました。
今回の記事の後も技評の稲尾さんとは仲良くさせていただいているので、今後もいろいろ僕なりのものを提供し続けられればな、と思っています。
仕事
仕事については、全体として良くも悪くも個人的にはスカっとできない感じがずっと続いていたと思います。。
一方で、震災の時にやった「限られた食材で工夫」の話だったり、ここ最近のいろいろ責任が増えた中でリリースしたものだったり(割といい数字が出た)を振り返ると、やっぱり自分は追い込まれてる時のほうがいい結果が出やすいのかなぁと感じています。縛りのある中の方がパフォーマンスが出やすいというか。
どんな時でもお前なんとかしろよ、な話ではあるかと思いますが、2012年は縛りをいい感じに自分でうまく設定して、パフォーマンスを上げていきたいですね。
プライベート
gem初めて作ったのはいい経験でした。
同じように、最近YouTube絡みのコードも書きました。
それぞれニッチなとこを狙ったものではありますが、自分も日常的に使うものになってるし、音楽に絡むコードを書く楽しさはこれらのコードを書くことを通じて再確認したので、来年もこんな感じのコードは書き続けたいな、と。
2012年
仕事でもっと圧倒的な結果を出したいですね!!!!1 それを元にして自分の知見だったり考えだったりをもっと外に広げたい、サービス開発エンジニアとしてはこれはやっぱり一番強く思っています。あと、仕事以外では、デバイス絡みでなんか作りたいと思っています。思っているというか構想はあるので、少しづつそれも実現していきたいですね。(最近また復活してきましたが)blogももっと書きますぞ!
と、いうわけで来年もよろしくお願いします!
YouTubeの音声をiTunesに転送する
年の瀬になんかちゃっちゃと作りたかったので、単機能musicalみたいなtaifuというスクリプトを書きました。
これは何?
YouTubeでかっこういい動画を見つけたときに、iTunesで音だけでも聴きたい!な時は割とあるかと思いますが、それを実現するスクリプトです。実行権限を追加して
taifu http://www.youtube.com/watch?v=KPWfBfFFrwsx
で、wavデータを標準のエンコーダ設定でエンコードして何事もなかったようにiTunesに追加します。(要VLC.app)
タグ情報はどうなってるの?
「TAIFU_NAME」「TAIFU_ARTIST」「TAIFU_ALBUM」の名前でタグ付けされているので、iTunes上から「TAIFU」で検索したら追加された曲が見つかるはずです。あとは自分の好みのタグ情報に更新ください。オプションで渡すことも考えたけど、iTunes上で編集したほうが楽だったのでやめました。
「あーこれいつでも聴いていたいな〜」なものを見つけたとき、ご利用ください!
WEB+DB PRESS vol.66に寄稿しました
Webエンジニアの教科書的存在であるWEB+DB PRESSですが、本日12/23に発売のvol.66でのクックパッド特集で寄稿させていただきました。
第三章「ユーザを向いたものづくり」が僕の担当です。サービス開発の進め方について余すこと無くクックパッドでのプロセスを全部まとめています。ユーザを徹底的に向いた開発手法について興味のある方は是非一読ください。
僕以外の記事もインフラ、開発基盤、スマートフォン開発、DevOpsと多岐に渡る分野の内容になっていて、かなり面白い内容になっていると思います。
読もう! WEB+DB PRESS!
rb-appscriptを利用してwavデータを自動的にiTunesにタグ情報付きでエンコード、ライブラリに追加
musical 0.0.2リリース
musicalの0.0.2をリリースしました。(インストールなんかの細かい話はこちら)
リッピングしたwavデータを自動的にiTunesのエンコード設定(mp3/AAC/Appleロスレス...)に従ってエンコードし、アーティスト名とDVDタイトル名を与えることでタグ情報付きでライブラリに追加します。たとえばDVDをドライブに入れた状態で、次のように実行します。
musical --title "TOUR あいのわ" --artist ハナレグミ
そうすると、
- チャプタごとにvobでリッピング
- wavに変換
- iTunesライブラリにwavを追加
- エンコード設定に従ってタグ付きでエンコード
の順に処理がすすみ、最終的にはiTunesのライブラリにこのように取り込まれます。
各チャプタのタイトルは今は自動にタグ付けする仕組みはないので、そこは自前で編集を。ここもうまく自動化したいのですが、DVD自身にはトラック情報を持っていないので、amazonなりから情報をうまく吸い出すなりいい方法を模索してます。
--title, --artistを与えない場合は、それぞれ「LIVE」「ARTIST」の名前でタグ付けされます。また、半角スペースを挟む情報の場合(上の例だと、「TOUR あいのわ」)は、「"」と「"」で囲って渡してあげます。
rubyからiTunesを操作
iTunesを操作する処理については、rb-appscriptを利用しています。rb-appscriptは、AppleEventをブリッジしてrubyから扱えるようにしたライブラリで、AppleScriptに対応したアプリケーションは、全て制御することができます。
一見、すごく便利で万能すぎるように思えるんですけど、ドキュメントが全くないのが辛いとこ。(単純にファイルをライブラリに追加するだけでも相当苦労しました。) 基本的に、method_missingで実装されているので、APIを把握してないと何も開発できません。。最初は、AppleScriptのAPIをdeveloper.apple.comからAPIを探しまくってたのですが、全然見つからなくて途方に暮れてたら意外にも手元にすでに存在してました。
「アプリケーション」「ユーティリティ」から「Appleスクリプトエディタ」を起動し、「ウィンドウ」>「ライブラリ」から「iTunes」を選択すると、AppleScript用のAPIが表示されます。(ちなみに裏技的に、Appleスクリプトエディタのアイコンに、iTunesのアイコンをD&Dしてもこのライブラリウィンドウは起動します。すごい使いづらいですけど。。)
これを元に、上で述べたファイルを追加+エンコードの基本的な操作をまとめるとこんなかんじになります。
見てわかる通り、割と直感的な操作が可能になっていると思います。基本的にはgetで情報を取得、setで更新し、このときにAppleEventが発行されています。(なので、できるだけget/setの数は減らすほうがイベント発行の節約になって、パフォーマンスが上がる)
また、普段irbやpryなんかで簡単な操作をしているときに、APIを確認するまでもなく、ざっとプロパティを確認することくらいはもうちょっと手軽な方法で確認できます。ASDictionaryをインストールしておくと、各オブジェクトに対してhelpメソッドを利用できます。たとえば、現在iTunes上で選択中のトラック、current_trackには次のようなプロパティが存在することを確認できます。
$ pry
[1] pry(main)> require 'appscript'
=> true
[2] pry(main)> include Appscript
=> Object
[3] pry(main)> its = app("iTunes.app")
=> app("/Applications/iTunes.app")
[4] pry(main)> its.current_track
=> app("/Applications/iTunes.app").current_track
[5] pry(main)> its.current_track.help
==============================================================================
Help (-t)
Reference: app("/Applications/iTunes.app").current_track
------------------------------------------------------------------------------
Description of reference
Property: current_track (r/o) : track -- the current targeted track
Terminology for track class
Class: track -- playable audio source
Plural:
tracks
Inherits from:
item (in iTunes Suite)
Properties:
container (r/o) : reference -- the container of the item
id_ (r/o) : integer -- the id of the item
index (r/o) : integer -- The index of the item in internal application order.
name : unicode_text -- the name of the item
persistent_ID (r/o) : string -- the id of the item as a hexidecimal string. This id does not change over time.
album : unicode_text -- the album name of the track
album_artist : unicode_text -- the album artist of the track
album_rating : integer -- the rating of the album for this track (0 to 100)
album_rating_kind (r/o) : :user / :computed -- the rating kind of the album rating for this track
artist : unicode_text -- the artist/source of the track
bit_rate (r/o) : integer -- the bit rate of the track (in kbps)
bookmark : short_float -- the bookmark time of the track in seconds
bookmarkable : boolean -- is the playback position for this track remembered?
bpm : integer -- the tempo of this track in beats per minute
category : unicode_text -- the category of the track
comment : unicode_text -- freeform notes about the track
compilation : boolean -- is this track from a compilation album?
composer : unicode_text -- the composer of the track
database_ID (r/o) : integer -- the common, unique ID for this track. If two tracks in different playlists have the same database ID, they are sharing the same data.
date_added (r/o) : date -- the date the track was added to the playlist
description : unicode_text -- the description of the track
disc_count : integer -- the total number of discs in the source album
disc_number : integer -- the index of the disc containing this track on the source album
duration (r/o) : short_float -- the length of the track in seconds
enabled : boolean -- is this track checked for playback?
episode_ID : unicode_text -- the episode ID of the track
episode_number : integer -- the episode number of the track
EQ : unicode_text -- the name of the EQ preset of the track
finish : short_float -- the stop time of the track in seconds
gapless : boolean -- is this track from a gapless album?
genre : unicode_text -- the music/audio genre (category) of the track
grouping : unicode_text -- the grouping (piece) of the track. Generally used to denote movements within a classical work.
kind (r/o) : unicode_text -- a text description of the track
long_description : unicode_text
lyrics : unicode_text -- the lyrics of the track
modification_date (r/o) : date -- the modification date of the content of this track
played_count : integer -- number of times this track has been played
played_date : date -- the date and time this track was last played
podcast (r/o) : boolean -- is this track a podcast episode?
rating : integer -- the rating of this track (0 to 100)
rating_kind (r/o) : :user / :computed -- the rating kind of this track
release_date (r/o) : date -- the release date of this track
sample_rate (r/o) : integer -- the sample rate of the track (in Hz)
season_number : integer -- the season number of the track
shufflable : boolean -- is this track included when shuffling?
skipped_count : integer -- number of times this track has been skipped
skipped_date : date -- the date and time this track was last skipped
show : unicode_text -- the show name of the track
sort_album : unicode_text -- override string to use for the track when sorting by album
sort_artist : unicode_text -- override string to use for the track when sorting by artist
sort_album_artist : unicode_text -- override string to use for the track when sorting by album artist
sort_name : unicode_text -- override string to use for the track when sorting by name
sort_composer : unicode_text -- override string to use for the track when sorting by composer
sort_show : unicode_text -- override string to use for the track when sorting by show name
size (r/o) : integer -- the size of the track (in bytes)
start : short_float -- the start time of the track in seconds
time (r/o) : unicode_text -- the length of the track in MM:SS format
track_count : integer -- the total number of tracks on the source album
track_number : integer -- the index of the track on the source album
unplayed : boolean -- is this track unplayed?
video_kind : :none / :movie / :music_video / :TV_show -- kind of video track
volume_adjustment : integer -- relative volume adjustment of the track (-100% to 100%)
year : integer -- the year the track was recorded/released
Elements:
artworks -- by index
==============================================================================
=> app("/Applications/iTunes.app").current_track
実際は、さきほどのAppleスクリプトエディタのヘルプ情報から引っ張ってきて表示しているだけですが、都度手元で確認できるのは便利です。ざっとAPI全体を眺めて把握した上で、手元で動かしながら動作を確認するのが開発を進める方法として良さそうです。
今後の予定
当面、次の内容くらいはどうにかしたいです。
- iTunesのライブラリに追加したとき、変換前のwavファイルをライブラリ上から削除
- 副音声の扱いを制御
- テストを追加
- トラック名を自動追加
あとrb-appscriptめちゃめちゃ可能性を感じるので、こいつでもうちょっと遊んでみたいですね。API見ているだけでムフムフします。。!
Homebrewでffmpegインストール時の"ERROR: libmp3lame >= 3.98.3 not found"を回避
前のエントリで「libmp3lameあたりでコケる」と言ったのですが、そのときの対応方法のメモ。
ERROR: libmp3lame >= 3.98.3 not found
brew install ffmpegしたときのエラーはlibmp3lameが3.98.3以上のものが見つからないというエラーでした。ところが、
$ lame --version LAME 64bits version 3.99.1 (http://lame.sf.net) Copyright (c) 1999-2011 by The LAME Project Copyright (c) 1999,2000,2001 by Mark Taylor Copyright (c) 1998 by Michael Cheng Copyright (c) 1995,1996,1997 by Michael Hipp: mpglib This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this program. If not, see <http://www.gnu.org/licenses/>.
と、なっているので、lame本体は3.99.1の最新のものがインストールされているようです。要はこいつが認識されていないよう。
最初は、(他の)ライブラリのインストールが失敗していて、正しく認識されないことを疑ったのですが、どうもそうではなさそう。
そもそもどのバージョンとして認識されているのか
インストールされていないことは無さそうなので、一体どのバージョンがインストールされていると見なされているんだろう、、途方に暮れつつも共有ライブラリのバージョンの確認方法がそもそもよくわかりません。。。とりあえず、libmp3lameのインストールされている場所を確認してみます。
$ locate libmp3lame /usr/lib/libmp3lame.dylib /usr/local/Cellar/lame/3.99.1/lib/libmp3lame.0.dylib /usr/local/Cellar/lame/3.99.1/lib/libmp3lame.a /usr/local/Cellar/lame/3.99.1/lib/libmp3lame.dylib /usr/local/lib/libmp3lame.0.dylib /usr/local/lib/libmp3lame.a /usr/local/lib/libmp3lame.dylib
なんかいっぱい出てきました。下の/usr/local/lib以下のものは、実際はそれぞれ/usr/local/Cellar/lame/3.99.1/以下のシンボリックリンクになっているようですが、一番上のものが何やら疑わしいです。普通、バージョン情報なんかは文字列として埋め込まれている可能性が高いので、stringsで覗いてみると
$ strings /usr/lib/libmp3lame.dylib | less l3_side->main_data_begin: %i , 3DNow! Warning: many decoders cannot handle free format bitrates >320 kbps (see documentation) xr^3/4 3.97 LAME3.97 http://www.mp3dev.org/ 32bits mpg123: Bogus region length (%d) mpg123: Can't rewind stream by %d bits! 333333? ...
むむむ。LAME3.97とすごい怪しいバージョン番号ぽいものが見えます。。。! では、他のファイルはどうなのかと思い、/usr/local/lib以下のものを調べてみると
$ strings /usr/local/libmp3lame.dylib | less Error: can't allocate VbrFrames buffer strange error flushing buffer ... Error: MAX_HEADER_BUF too small in bitstream.c Internal buffer inconsistency. flushbits <> ResvSize bit reservoir error: ... This is a fatal error. It has several possible causes: 90%% LAME compiled with buggy version of gcc using advanced optimizations 9%% Your system is overclocked 1%% bug in LAME encoding library LAME %s version %s (%s) LAME version %s (%s) ... INTERNAL ERROR IN VBR NEW CODE (986), please send bug report INTERNAL ERROR IN VBR NEW CODE (1313), please send bug report maxbits=%d usedbits=%d 3.99.1 L3.99r http://lame.sf.net ...
おおお、やはりlameのバージョンである3.99.1という文字列が確認できます。やはりこの/usr/local/lib以下のものよりも優先して/usr/lib以下の低いバージョンの共有ライブラリが参照されているようです。試しに、この低い方のものを削除して、brew install ffmpegしなおしてみると
$ brew install --use-gcc ffmpeg ==> Downloading http://ffmpeg.org/releases/ffmpeg-0.8.6.tar.bz2 File already downloaded in /Users/katsuma/Library/Caches/Homebrew ==> ./configure --prefix=/usr/local/Cellar/ffmpeg/0.8.6 --enable-shared --enable-gpl --enable-version3 --enable-nonfree --enable-hardcoded-tables --cc= ==> make install /usr/local/Cellar/ffmpeg/0.8.6: 97 files, 55M, built in 5.7 minutes
ビンゴ!やはり低いバージョンのものが邪魔をしていたようです。。。!どういう経路でこの古いバージョンのlibmp3lameが入ってきたのか謎ですが、何かのアプリケーションをインストールしたときに一緒に入って、アプリケーションのアンインストール時に削除されないまま残ったのかもしれません(謎)
まとめ
ライブラリのバージョン依存でインストールに困ったときは、とりあえず
- locateで該当対象のファイルパスのリストを洗い出し
- stringsでバージョン確認
な感じでしょうか。ただ、このstringsで確認するあたりが正当法じゃない感じがする。。のですが、もっといいバージョン確認方法があればぜひ教えていただきたいです。
MacOSXでIPアドレスを迷わず1秒で即答する
ifconfigでもちろん取れるけど、情報量多すぎるのでIPアドレスがどこに書かれてるか探してしまうCUI素人としては、極限まで情報量削ってもっと便利にしたい。と、いうことでこんなのを最近使ってます。
これをパスが通った場所に「i」という名前のファイルで置いて実行すると、IPアドレスだけ表示されて、かつクリップボードにも入るのですぐに利用できる状態になる。
手元で開発した内容をディレクターや他のメンバーと共有するときに、自分のIP教えてブラウザで直接見てもらうことがかなり多いんですけど、「i」「Enter」で共有できるようになったことで、めちゃめちゃコスト下がってかなり便利!
DVDデータをチャプタ毎にリッピング/wav変換するLionに対応したgem 'musical'
musicalというgemを作りました。
これは何?
「Mac OSXでライブDVDをmp3ファイルに変換」にも書いたのですが、僕はアーティストのライブDVDを買って思う存分鑑賞した後は、mp3/AACに変換してiTunes/iPhoneで聴くという楽しみ方をよくしています。 ところが、この変換の際に肝である0SExというソフトがMac OSX 10.7(Lion)になってから動かなくなりました。理由は明確で、0SExはPPC用にビルドされたバイナリなのでRosetta上では動作していたのですが、LionになってRosettaが取り除かれてしまったことで動作しなくなりました。Rosettaの代用品も存在せず、途方に暮れていたのですが、既存のソフトウェアの組み合わせでなんとかできることがわかったので、自分が使いやすい形にmusicalというgemの形でまとめてみました。
musicalができることが単純で、
- チャプタごとのリッピング
- チャプタごとのwavファイルの変換
- (オプションとして)タイトル/チャプタ情報の出力
だけです。個人的には2.のwavの変換を行ったあとに、iTunesにD&DでAACに変換を行っているので、ここまでの処理を行おうか迷ったのですが、利用する音声フォーマットは個々人に任せたほうがいいと思ったので、wav変換までで止めています。
(2011.11.27 追記) 0.0.2でiTunesの設定に従ってエンコード、ライブラリ追加まで行えるようにしました
インストール
必要ソフトウェアのインストール
musicalはバックエンドでdvdbackup, ffmpegを利用しているので、これらをインストールしておきます。homebrewでインストールできます(後述しますが、ちょっと罠があります)。
brew install dvdbackup brew install ffmpeg
gemのインストール
毎度おなじみの
gem install musical
で、OKです。
利用方法
一番シンプルなのは、DVDドライブにDVDを入れた状態で
musical
だけで、カレントディレクトリにチャプタ毎にwavファイルができあがります。
wavはいらない!リッピングだけでいいんだけど
musical --ignore-convert-sound
で、リッピングだけ行い、wavへの変換は行いません。
保存する場所を変更したいんだけど
musical --output=save/to/path --title=DVD_title
--output, --titleオプションを利用できます。オプションについては--helpでご確認ください。
musical --infoが何も表示されないんだけど
DVDにプロテクトがかかっているので、Fairmountなどを使って、ディスクイメージとしてマウントすれば大丈夫です。
ライブラリのインストール時の注意
dvdbackup
brew installで簡単にいく。。と思いきや、依存パッケージのlibdvdreadのインストールでコケました。これは単純にURLが変更になっていたので、
brew edit libdvdread
して、
@@ -3,7 +3,7 @@ require 'formula' class Libdvdread < Formula homepage 'http://www.dtek.chalmers.se/groups/dvd/' # Official site is down; use a mirror. - url 'http://www.mplayerhq.hu/MPlayer/releases/dvdnav/libdvdread-4.1.3.tar.bz2' + url 'http://www.mplayerhq.hu/MPlayer/releases/dvdnav-old/libdvdread-4.1.3.tar.bz2' md5 '6dc068d442c85a3cdd5ad3da75f6c6e8' depends_on 'libdvdcss' => :optional
こんなかんじで編集した後、brew install libdvdreadしなおしたら大丈夫です。
ちなみにこの内容は(人生初の)pull requestを送ってみたので、もしかしたら今後は取り込まれるかもしれませんね。
(2011.11.11追記) pull requestは取り込まれたので、brew updateしたらformulaを編集しなくてもインストールできると思います。
ffmpeg
これもbrew installで簡単にいく。。と思いきや、最新のXcodeでgccが無くなった + pod2manの実行権限がなぜか無くなっていたことでかなりハマりました。あらかじめgccをインストールしなおした上で、こんなかんじでインストール可能です。
# 関連するものを含めて、一度アンインストール brew uninstall --force `brew deps ffmpeg` # なぜか実行権限無くなっていたので再設定 sudo chmod +x /usr/bin/pod2man # gccの利用を指定 brew install --use-gcc ffmpeg
基本的にこれでいけるはずなんですけど、依存関係上一緒にインストールされるlibxvid, libmp3lameあたりでコケた場合(実際、別のLionのマシンで試したらコケた)は、最悪これらのインストールをスキップしても大丈夫です。brew edit ffmpegで
depends_on 'yasm' => :build
...
#depends_on 'lame' => :optional
...
#depends_on 'xvid' => :optional
...
#args << "--enable-libmp3lame" if Formula.factory('lame').installed?
...
#args << "--enable-libxvid" if Formula.factory('xvid').installed?
こんなかんじでコメントアウトたらビルドも通り、動作が確認できました。
最後に
当然ながら、本gemは著作権違反の手助けをするためのものではありません。自身の責任の元、ご利用ください。
このBlogは白金台のとある企業に勤めるWeb屋がLLネタや情報技術について直感で思ったことを何も考えず発信するサイトです。コメントはOpenID経由で直接いただくか、Trackback、SBM、メールなどでお待ちしています。