Skip to content

Instantly share code, notes, and snippets.

@degarashi
Last active February 6, 2017 16:26
Show Gist options
  • Save degarashi/ce35dff85156fee974e4070b7672072a to your computer and use it in GitHub Desktop.
Save degarashi/ce35dff85156fee974e4070b7672072a to your computer and use it in GitHub Desktop.
FFMpegを使って指定ディレクトリの動画ファイルから音声部分を一括抽出
# coding: utf-8
# FFMpegを使って指定ディレクトリの動画ファイルから音声部分を一括抽出するプログラム
# ------------------: 使い方:---------------------------
# python3 extract_audio.py (ディレクトリのパス) (抽出対処の拡張子 mp4など) [remove]
# removeをつけると抽出した後に元ファイルを削除する
import glob
import shlex
import subprocess
import re
import os
import sys
class UnknownError(BaseException):
"""FFMpegからの出力が解析できなかった時などの不明なエラー"""
def __init__(self, fn):
self.fn = fn
def __str__(self):
return "UnknownError: while reading file=" + self.fn
class UnknownFormat(BaseException):
"""FFMpegから返されたフォーマット文字列が未知だった時など"""
def __init__(self, fn, fmt):
self.fn = fn
self.fmt = fmt
def __str__(self):
return "UnknownFormat: while reading file=" + self.fn + ", format=" + self.fmt
# FFMpegが出力したストリーム情報から音声フォーマット文字列の抽出
re0 = re.compile(r"Stream\s+#\d:\d.*\s+Audio:\s+(\w+)(,|\s)")
# ファイルパスから拡張子の直前までを取り出す
re1 = re.compile(r"([/\\\w\s]+)\.")
# FFMpegのバイナリ名
FFMpeg = "ffmpeg"
param = sys.argv
if len(param)<3:
# 引数足りない時は呼び出し例を表示して終了
print("usage: python3 extract_audio.py path(ex. ./Directory) extension(ex. mp4) [remove]")
quit()
param_dir = param[1]
param_ext = param[2]
param_rem = True if len(param)>=4 and param[3].lower()=="remove" else False
# 音声フォーマットとコンテナの対応表。必要に応じて追加する
FormatToContainer = {
"aac": "m4a",
"vorbis": "ogg"
}
# 相対パスを絶対パスへ変換
if(not os.path.isabs(param_dir)):
param_dir = os.path.abspath(param_dir)
param_dir = os.path.join(param_dir, "*." + param_ext)
files = glob.glob(param_dir)
for fn in files:
ret = subprocess.Popen([FFMpeg, "-i", fn], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# FFMpegにファイルを入力しただけだとstderrに詳細が返ってくる
s = ""
for line in ret.stderr:
s += line.decode()
# 返って来た文字列から音声フォーマットを特定し、対応するコンテナ形式を取得
fmtstr = re0.search(s)
if fmtstr:
fmt = fmtstr.group(1).lower()
if fmt in FormatToContainer:
container = FormatToContainer[fmt]
else:
# 対応するコンテナ形式がマップに登録されておらぬ
raise UnknownFormat(fn, fmt)
else:
# 音声フォーマットがわからぬ
raise UnknownError(fn)
# 出力先パスに拡張子を付加してFFMpegへ突っ込む
m = re1.search(fn)
output = fn[m.start(1):m.end(1)] + "." + container
cmd = FFMpeg + ' -i "' + fn + '" -vn -acodec copy "' + output + '"'
subprocess.call(shlex.split(cmd))
# Removeフラグが指定されていればここでファイルを削除
if param_rem:
os.remove(fn)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment