とある科学の備忘録

とある科学の備忘録

CやPythonのプログラミング、Arduino等を使った電子工作をメインに書いています。また、木製CNCやドローンの自作製作記も更新中です。たまに機械学習とかもやってます。

【Python】サブフォルダも含めてwavファイルをmp3等に変換

この記事の内容

以前は、音声のフォーマット(拡張子)を一括変換する場合、「Any Video Converter」というアプリを使っていましたが、変換が完了する度に毎度表示される広告がうっとうしくなり、自分でプログラムを書こうと決めました。


ということで、今回は音声ファイルの拡張子を一括で変換するスクリプトです。
wav→oggファイル、wav↔mp3、wma↔mp3ファイルなどに変換できます。


必要なライブラリ

このスクリプトではffmpegを使って拡張子変換を行っています。よって、事前にffmpegをインストールしておく必要があります。


ffmpegのインストール方法は以下を参考にしてください。
shizenkarasuzon.hatenablog.com

pip環境があれば、以下のコマンドを叩いてもインストールできます。

pip install ffmpeg-python


他にも、globというフォルダ管理ライブラリや、subprocessというライブラリを使用しますが、こちらは標準でインストールされています。

もし入っていなかったら

pip install glob

のようなコマンドを実行してください。


スクリプト

以下、WAVファイルとMP3ファイルをOGGファイルに変換するプログラムです。

変換後は、前のファイル(WAVとMP3)は削除されます。
(↓のプログラムで、os.remove()関数の部分を削除すれば、元データの削除は行われなくなります)

# -*- coding: utf-8 -*-

import glob
import os
import subprocess

name_lists2 = glob.glob("./**", recursive=True)
print("the number of music files: " + str(len(name_lists2)))

cmd1 = "ffmpeg -i \""
cmd2 = "\" -vn -ac 2 -ar 44100 -ab 128k -acodec libvorbis -f ogg \""
cmd3 = "\""
root = os.path.abspath("./") + "/"


for i in name_lists2:
    print(i)
    if "wav" in i:
        i2 = root + i
        path2 = i2.replace("wav", "ogg")
        print(cmd1 + i2 + cmd2 + path2 + cmd3)
        subprocess.call(cmd1 + i2 + cmd2 + path2 + cmd3)
        os.remove(i2)


    elif "mp3" in i:
        i2 = root + i
        path2 = i2.replace("mp3", "ogg")
        print(cmd1 + i2 + cmd2 + path2 + cmd3)
        subprocess.call(cmd1 + i2 + cmd2 + path2 + cmd3)
        os.remove(i2)

    else:
        print(" ##### NO FILE ##### -> " + i)

print("--------- FINISH RENDERING !!----------")

 

解説

subprocess.call() 関数は、コマンドをプロンプトで実行するのと同じ役割を果たします。
17.1. subprocess --- サブプロセス管理 — Python 2.7.16 ドキュメント


またffpmegで音声データを変換するには、以下のようなコマンドを実行します。

ffmpeg -i "input.wav" -vn -ac 2 -ar 44100 -ab 128k -acodec libvorbis -f ogg "output.ogg"

上のコマンドだと、「input.wav」を「output.ogg」に変換します。


このインプットとアウトプットのファイル名をfor文を使って変更することで、複数のファイルを変換することができます。


では、インプットのファイル名はどうやって取得するのか?
答えは glob.glob() 関数です。

name_lists = glob.glob("./**", recursive=True)

と書くと、name_lists にはサブフォルダを含めてすべてのファイル名のリストが保存されます。