銀月の符号

Python 使い見習いの日記・雑記

ffmpeg コマンドをつかって flv から音を取り出す

[ffmepg -i flvファイル名 -acodec copy 出力ファイル名] と何度も打つのが手間だったのでスクリプトをちょっと書いてみた。そんな日のこと。

flv 動画ファイルから音声をそのまま取り出してくれるスクリプトのつもり。引数を与えないで起動するとカレントディレクトリのファイルすべてを処理対象とする。引数を与えるとこれを処理対象ファイル名とする。対象ファイルの拡張子を確認し .flv でなければ無視する。中身の音声は劣化させないようにコーデックの変換をせずそのまま取り出す。そして .mp3 の拡張子で保存。ホントに mp3 かどうかはとりあえず無視。手持ちの flv 動画の音声は軒並み mp3 だから。

たしか、 ffmpeg は動画、音声のコーデックになにが使われているのか調べることくらいできたはず。その結果を出力ファイルの拡張子に反映させるのを今後の課題に。ffmpegAPI を直接たたかないとダメかもしれないけどそれはそれで Python/C API を初めて目的持って使ういい機会になりそう。実は足し算引き算する程度の C モジュールしか書いたことないからまじめに取り組んでみたい。ついでにもう忘れている C 言語の復習にもなりそうだし。

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
u"""ffmpeg を使って flv から 音声 を取り出す。"""
import optparse
import os
import subprocess
import sys


def get_audio_stream(org, dst):
    u"""
    ffmpeg フロントエンドを使用して動画ファイルから音声を取り出す
    """
    command = [
                ur'ffmpeg.exe',
                u'-i',
                org,
                u'-acodec',
                u'copy',
                dst,
                ]
    # TODO: 文字エンコーディング cp932 の決めうちをやめよう
    #       Windows 以外でも動くのだから
    command = [s.encode('cp932') for s in command]
    retcode = subprocess.call(
            command,
            )
    return retcode


def main():
    usage = u'%prog [flv1, flv2, flv3, ...]'
    version = u'0.3'
    parser = optparse.OptionParser(usage=usage, version=version)
    options, args = parser.parse_args()
    # 引数があればそれを処理対象とする。
    # なければカレントのファイルすべてが対象
    if args:
        # TODO: 文字エンコーディングの決めうち止め
        flv_list = [unicode(arg, 'cp932') for arg in args]
    else:
        flv_list = os.listdir(u'.')
    for flv in flv_list:
        # ファイルが実在しなければ無視
        if not os.path.isfile(flv):
            sys.stderr.write(u'%s: ファイルが見つかりません' % flv)
            continue
        # 拡張子 が flv でなければ無視
        if not flv.endswith(u'.flv'):
            sys.stderr.write(u"%s': 拡張子が .flv ではないので無視します\n" % flv)
            continue
        # 音声取り出し
        mp3 = flv.replace(u'.flv', u'.mp3')
        retcode = get_audio_stream(flv, mp3)
        if retcode:
            sys.stderr.write(u'%s: 取り出しできませんでした。 :%s' % (flv, retcode))


if __name__ == '__main__':
    main()