ffmpeg で mp4 を mp3 に変換する(サムネイル埋め込み版)

[ffmpeg で mp4 を mp3 に変換する](http://qiita.com/miyagi389/items/6de37c1393a19c93046a) に、下記の機能を追加。
* mp4の特定フレームの映像をmp3のサムネイル(アートワーク)として埋め込む。

サムネイル(アートワーク)の切り出しには、ffmpegを使用した。

サムネイル(アートワーク)の埋め込みには、[eyed3](http://eyed3.nicfit.net/) を使用した。
eyed3はmp3のタグ情報を編集できるツール。今回はpythonスクリプト内から使用した。CLIもある。python3非対応なのでpython2.7が必要。


# 動作環境
* Mac OS X 10.10
* [homebrew](http://mxcl.github.com/homebrew/) 0.9.5
* ffmpeg 2.7.1
* python 2.7
    * [eyed3 0.7.8](http://eyed3.nicfit.net/)

## インストール
```bash
# ffmpeg
brew install ffmpeg --with-tools

# eyed3
pip install eyed3==0.7.8
```

# 変換スクリプト
```py:ffmpeg_conv_mp3.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
# system requirement
    * python 2.7

# install
    $ brew install ffmpeg --with-tools
    $ pip install eyed3==0.7.8
"""

import argparse
import eyed3
from eyed3.id3.frames import ImageFrame
from os import getcwd, path, system, remove
import sys

FFMPEG_MP42MP3_CMD = (
    u'ffmpeg'
    u' -y'
    u' -loglevel warning'
    u' -i "{src_file}"'
    u' -acodec libmp3lame'
    u' -ab 256k'
    u' "{dest_file}"'
)
FFMPEG_THUMBNAIL_CMD = (
    u'ffmpeg'
    u' -y'
    u' -loglevel warning'
    u' -i "{src_file}"'
    u' -ss 5'
    u' -vframes 1'
    u' -f image2'
    u' "{dest_file}"'
)


def rename_filename_ext(src_file, rename_ext, dest_directory):
    name, ext = path.splitext(path.basename(src_file))
    return (name, path.join(dest_directory, name + rename_ext))


def main(src_files, dest_directory):
    for src_file in src_files:
        src_file = path.abspath(src_file).decode('utf-8')
        dest = path.abspath(dest_directory).decode('utf-8')

        title, dest_mp3_file = rename_filename_ext(src_file, u'.mp3', dest)
        title, dest_png_file = rename_filename_ext(src_file, u'.png', dest)

        # mp4 -> mp3 encode
        ffmpeg_cmd = FFMPEG_MP42MP3_CMD.format(
            src_file=src_file,
            dest_file=dest_mp3_file
        )
        print(u'{0} -> {1}'.format(src_file, dest_mp3_file))
        system(ffmpeg_cmd.encode(sys.stdin.encoding))

        # mp4からサムネイル画像を切り出す
        ffmpeg_cmd = FFMPEG_THUMBNAIL_CMD.format(
            src_file=src_file,
            dest_file=dest_png_file
        )
        system(ffmpeg_cmd.encode(sys.stdin.encoding))

        # サムネイル画像をmp3ファイルに埋め込む
        f = eyed3.load(dest_mp3_file)
        if f.tag is None:
            f.initTag()
        f.tag.title = title
        with open(dest_png_file, 'rb') as dest_png:
            f.tag.images.set(
                ImageFrame.FRONT_COVER,
                dest_png.read(),
                'image/png'
            )
        f.tag.save(encoding='utf-8')

        if path.exists(dest_png_file):
            remove(dest_png_file)


def parse_args():
    parser = argparse.ArgumentParser(
        description=u'ffmpeg で mp4 を mp3 に変換(サムネイル埋め込み版)'
    )
    parser.add_argument(
        'source_files',
        metavar='source_file',
        nargs='+',
        help='source files'
    )
    parser.add_argument(
        '--dest',
        metavar='destination_directory',
        nargs='?',
        default=getcwd(),
        help='destination directory (default: current directory)'
    )
    return parser.parse_args()


if __name__ == '__main__':
    args = parse_args()
    main(args.source_files, args.dest)
```

```bash
chmod +x ffmpeg_conv_mp3.py
```

# 使い方
"./mp4/in/" ディレクトリ下の "*.mp4" をmp3にエンコードして、"./mp4/out/" ディレクトリに出力する。

```bash
ffmpeg_conv_mp3.py ./mp4/in/*.mp4 --dest ./mp4/out/
```