実行例
まず、結論からいってこのような出力を得られる
lMusic 交響曲 | perl -lne 'system "exif $_ "' | nkf -w | ~/Python_instance/exif2name_time.py
1:33:13
---------
0:07:39 交響曲第25番ト短調.wav
0:07:40 交響曲第40番ト短調.wav
0:06:36 交響曲第40番ハ短調.wav
0:13:00 Dvorak交響曲第9番_新世界より_第4楽章.wav
0:19:25 チャイコフスキー_交響曲第6番_ロ短調_悲愴_第1楽章.wav
0:35:53 メニューイン指揮ドヴォルザーク交響曲第8番.wav
0:03:00 メンデルスゾーン_交響曲3番_スコットランド_序曲_フィンガルの洞窟.wav
解説
概要としては lMusic でHDD内のwavファイルを絞り込みそれをプレイリストとして見立て
る。それにsoxなどのplayを繋げば該当するwavが全て聞けるわけだが、終わるまでにどの
程度の時間が掛かるのか気になるところだ。
ファイルから再生時間を得るにはexiftoolがお手軽だ。cygwinでは/usr/bin/exif として
インストールしたか、或いはプリインストールされていた。Linuxならaptなどでインストー
ルすることになる。
exifは1つのファイルに対して[[File Name:filename], .., [Duration:0:03:00]]のよう
な連想配列を思わせる出力をする。ここでは0:03:00のような時間を合計するのに適した
pythonを使って処理する。時間を取り扱うdatetimeが最初から入っているから手軽という
意味で適しているだろう。
lMusic
これは前回紹介した関数で、引数を1つ与えるとwavファイル名からgrepしてフルパスを出力する。
lMusic () {
if [[ $# -eq 0 ]]
then
cd f:/Music_Movie > /dev/null
ls -v -F --color=auto **/*wav
cd $OLDPWD > /dev/null
return
fi
ls -v -F --color=auto f:/Music_Movie/**/*wav | grep --color -P "$1"
}
perl
ワンライナーでexifにフルパスを繋ぐ。"exif $_"と処理の形が露出するので分かりやすい。
exif
-h から抜粋すると「exiftool - Read and write meta information in files」である。
今回は再生時間を抜き出すには大げさな道具である。pythonコードはこれの出力処理といっ
ても過言ではない。nkfを使っているのは何故かexiftoolの標準出力がshift-jisで漢字が
文字化けするからその対策。cygwinのみ化ける。Linuxの方では化けなかった。つまり、
utf-8からshift-jisの間で壊れるファイル名の場合にはエラーが出るだろう。
なおオプションで演奏時間とファイル名だけ抜き出すと今回2倍以上の高速化ができる。
python script
#!/usr/bin/env python3
import sys
import datetime
exif_out = sys.stdin
name = []
play_time = []
total_time = datetime.timedelta(0, 0, 0)
def total_timer(time_form):
"""time_form sample is (0:02:18, 0:01:23) """
td = datetime.timedelta(0)
time_hms = [[int(time) for time in times.split(':')]
for times in time_form]
duration = sum([datetime.timedelta(hours=h, minutes=m, seconds=s)
for h, m, s in time_hms], td)
return duration
for line in exif_out:
key_and_value = [ l.strip() for l in line.partition(':')]
if key_and_value[0] == "File Name":
name.append(key_and_value[2])
if key_and_value[0] == "Duration":
play_time.append(key_and_value[2])
duration = total_timer(play_time)
print("{0}".format(duration))
print("-" * 9)
for (name, play_time) in zip(name, play_time):
print("{0:>9} {1:<}".format(play_time, name))
標準入力を受け取るためにsysを、時間を処理するためにdatetimeをインポートする。
次の段落ではグローバル変数の宣言と初期化をする。
さらに次の段落ではtotal_timer関数を定義し、これの引数はhhss型の文字列を1つの
要素として持つリストである。返り値は合計時間で数字型だ。datetime.timedeltaの中は
数字型なのでintを使う。
for段落は標準入力を処理する。文字列メソッドpartitionは引数にマッチする最初の1つ
で分解するので、Durationの右側の0:02:18のような時間表示がそのまま受け取れる。
最後の2つの段落は出力部分である。前者は総合時間を書き出し、後者はプレイ時間とファ
イル名を書き出す。左端から9つの固定長レコードを時間のために割き、左寄せと右寄せ
と上下関係で総合時間とそれぞれの時間を差別化しながら"---------"で時間表示区分と
いうまとまりを作った。
環境
python --version ; uname
Python 3.4.3
CYGWIN_NT-6.0