2023-08-10

image-diredでmp3カバー画像を表示する

前回ImageMagickがサポートしている画像形式をできるだけ登録したので、いろんな画像ファイルを眺めては悦に入っていたのですが、音楽ディレクトリを見たときにmp3ファイルにサムネイルが表示されないことに気が付きました。mp3ファイルにはアルバムのカバー画像(アルバムアート?)が埋め込まれているケースが多いので、表示しようと思えば出来ないことはないはずです。少し調べてみたらffmpegを使って取り出せることが分かったので試してみました。

まずはimage-converter-add-handler関数を使ってmp3やm4aのときにffmpegを使うようにしてみました。

;; image-mode等で表示する方法

(defun my-image-convert-ffmpeg (source format)
  (image-converter--convert 'ffmpeg source format))

(image-converter-add-handler "mp3" #'my-image-convert-ffmpeg)
(image-converter-add-handler "m4a" #'my-image-convert-ffmpeg)

これだけで、mp3ファイルをEmacsで開いてからimage-modeを立ち上げるとカバー画像が表示されます。

しかしこれだけではimage-diredでサムネイルが表示されません。image-diredはimage-converterとはまた別の仕組みでサムネイルを生成していたのでした。こちらはImageMagickとGraphicsMagickのみ考慮されていてffmpegは対応していません。また、画像形式によってプログラムやオプションを変える仕組みもありません。なので、advice-addを使ってサムネイル生成関数の挙動を無理矢理変更することで実現しました。

;; image-diredでサムネイルを表示する方法

(defun my-image-dired-create-thumb-1-around (orig-func
                                             original-file thumbnail-file)
  (if (member (file-name-extension original-file) '("mp3" "m4a"))

      ;; ffmpegを使うように一時的に変数を書き替えてから実行
      (let ((image-dired-cmd-create-thumbnail-program "ffmpeg")
            (image-dired-cmd-create-thumbnail-options
             '("-i" "%f"
               "-vf" "scale=%w:%h:force_original_aspect_ratio=decrease"
               "%t")))
        (funcall orig-func original-file thumbnail-file))

    ;; 通常通りに実行
    (funcall orig-func original-file thumbnail-file)))

(advice-add 'image-dired-create-thumb-1 :around #'my-image-dired-create-thumb-1-around)

するとこんな感じでdired内にカバー画像が表示できました。

mp3やm4aファイルのカバー画像をDired内に表示した例
図1: mp3やm4aファイルのカバー画像をDired内に表示した例