動画の音声を抜き出してエフェクトや音量調整を行いたい時や、質の良い録音と映像を組み合わせたい時、あるいは別のBGMに入れ替えたい時はありませんか?
今回は動画に別の音声を入れ替える(上書きする)ことが可能な「動画音声入れ替えツール」を紹介したいと思います。
同様のことができるフリーソフトは数多く存在しますが、いずれも多機能がゆえ操作が複雑で、使い方を理解するのに時間が掛かるのが現状です。
本ツールは、音声の入れ替えだけに特化しているため操作がシンプルで、入れ替え元のファイルはオーディオファイルだけでなく、動画ファイルを指定することも可能です。
サクッと音声を入れ替えたい場合、もしくは自作したい場合は、是非この記事を参考にしてください。
自作ツールを作るためのポイントと今後公開予定の自作ツール一覧を「【実践】Pythonで事務処理向け自作ツールを作ろう!」で紹介していますので、併せてご覧ください。
動画音声入れ替えツールの概要と使い方
今回紹介する動画音声入れ替えツールは、指定した動画の音声を別の音声に入れ替えることが可能です。
- 指定した動画ファイルの音声を、別の音声と入れ替えた動画を作成します。
- 入れ替え元のファイルは音声ファイル(aac形式)と動画ファイルのどちらも指定可能です。
- 入力フォルダ、出力ファルダに入力した内容は保持され、次回起動時に復元されます。
画面項目 | 説明 |
---|---|
入力動画ファイル | 音声を置き換えたい動画ファイルのパスを指定 |
画像抽出ファイル | 置き換え元の音声ファイル、または動画ファイルのパスを指定 ※動画ファイルを指定した場合、動画ファイルから音声を抽出 |
出力動画ファイル | 音声を置き換えた動画ファイルの出力パスを指定 |
入力動画の音声を上書きする | 音声の入れ替え処理を実行 |
動画の音声を入れ替える
- 入力ファイル欄に、音声を置き換えたい動画ファイルを指定する。
- 音声抽出ファイル欄に、置き換え元の音声ファイル(aac形式)又は動画ファイルを指定する。
- 「入力動画の音声を上書きする」ボタンをクリックする
プログラムのダウンロードと動作環境の設定
事前に、Pythonのインストールが必要です。既に構築済みの方は読み飛ばしてください。詳細は下記の個別記事をご確認ください。
自作ツールのためのポータブルPython開発・実行環境を作ろう! | プログラム実行時に必要 |
WinPython環境に ffmpeg を入れよう! | プログラム実行時に必要 |
WinPythonにVSCode Portable版を入れよう! | プログラム修正時に必要 |
Python 環境に下記のライブラリをインストールします。 command.bat を実行後、下記のコマンドを実行します。
pip install customtkinter
pip install tkinterdnd2
pip install Pillow
動画音声入れ替えツールと共通パッケージの2つをダウンロードし、2つのフォルダが同一階層になるように解凍します。
動画音声入れ替えツール
実行方法
次の手順で実行してください。
- WinPython のインストールフォルダ内にある command.bat を実行
- ダウンロードしたプログラムファイルをコピーした場所にカレントディレクトリを移動
- Python main.py を実行
Python main.py
しばらくすると下記の画面が表示されます。初回起動時は入力欄が空白ですが、次回以降は直前に入力した値が画面に復元されます。
動画音声入れ替えツールで画像と音声の抽出、または動画の作成ボタンをクリックすると、コンソール画面にffmpeg が出力する処理過程が表示されます。
動画音声入れ替えツールの仕様
プログラムの構成
main.py の中で画面の表示と動画音声入れ替えボタンのイベント処理を記述しています。イベント処理の中で直接音声入れ替え処理を記述しても良いのですが、再利用しやすいよう audio_replace.py に処理をまとめています。
モジュール名 | 役割 |
---|---|
main.py | 画面の表示とボタンクリックのイベント処理 |
audio_replace.py | 動画の音声を、指定した音声ファイル(又は動画ファイルの音声)で書き換える |
create_ui.py | UI定義ファイルを読み込んで画面にウィジェットを表示 |
customtkinter | ファイル選択やフォルダ選択、ドラッグ&ドロップを実現するための補助 |
appconfig.py | 画面に入力された値をJson形式のファイルに保存/読込する |
ソースコード
main.py
画面のボタンが押されたら func 関数を呼び出すようになっています。
誤って元のファイルを上書きする事故を防ぐため、func関数の中で入力ファイル(input_video)と出力ファイル( output_video)をチェックし、ファイル名が等しい場合は警告を出して処理をスキップするようにしています。
import os
import sys
sys.path.append(os.path.join(os.path. dirname(__file__), '../libs'))
from create_ui import CreateUI
from audio_replace import AudioReplacer
# ボタンが押された時の処理
def func(param):
input_video = param["input_file"]
input_audio = param["audio_file"]
output_video = param["output_save"]
if input_video == output_video:
ui.widgets["err_message"].configure(text="入力ファイルと同じ場所に、同じ名前で出力できません。")
return
ar = AudioReplacer()
ar.overwrite_audio_from_video(input_video,input_audio,output_video)
# インスタンス生成
ui = CreateUI(func)
# 画面の表示
ui.show()
audio_replace.py
このファイルには、AudioReplacer クラスが含まれています。AudioReplacer は動画の音声を入れ替えるクラスで、動画から音声の抽出する機能と、動画の音声を入れ替える機能を持っています。
メソッド | 説明 |
---|---|
__init__() | コンストラクタでは引数を使いません。 |
overwrite_audio_from_video( input_video, #動画入力ファイルのパス audio_file, # 置き換えるオーディオ or 動画ファイルパス output_video, # 出力動画ファイルパス ) | audio_file には aac 形式の音声ファイル、または 動画ファイルを指定します。 動画ファイルを指定した場合、自動的に動画から音声ファイルを aac 形式で抽出し、それを使用します。 |
overwrite_audio( input_video, #動画入力ファイルのパス audio_file, # 置き換えるオーディオ output_video, # 出力動画ファイルパス ) | overwrite_audio_from_video と同じですが、audio_file には 音声ファイルしか指定できません。 |
extract_audio( input_video, #動画入力ファイルのパス output_video, # 出力動画ファイルパス format, # 音声ファイルのフォーマット(初期値=aac) ) | 動画から音声を指定されたフォーマットで抽出します。音声ファイルには ffmpeg が扱えるフォーマットを指定できます。 |
import subprocess
import os
import shutil
import tempfile
class AudioReplacer:
def overwrite_audio_from_video(self, input_video, input_audio ,output_video):
"""
動画のオーディオトラックを指定された動画ファイルの音声で置き換えます。
Args:
input_video (str): 入力動画ファイルパス
audio_file (str): 置き換えるオーディオファイルパス
output_video (str): 出力動画ファイルパス
"""
# 入力と出力が全く同じなら、なにもしない
if input_video != output_video:
audio_ext = os.path.splitext(input_audio)[1].lower()
if audio_ext not in [".mp3",".wav",".ogg",".aac",".wma",".m4a",".ac3",".flac"]:
with tempfile.NamedTemporaryFile(suffix=".aac", delete=False) as temp_audio:
# 音声を一時ファイルにコピー
self.extract_audio(input_audio,temp_audio.name)
input_audio = temp_audio.name
self.overwrite_audio(input_video,input_audio,output_video)
# 一時ファイルを削除
if os.path.isfile(temp_audio.name):
os.remove(temp_audio.name)
def overwrite_audio(self, input_video, input_audio ,output_video):
"""
動画のオーディオトラックを指定されたオーディオファイルで置き換えます。
Args:
input_video (str): 入力動画ファイルパス
audio_file (str): 置き換えるオーディオファイルパス
output_video (str): 出力動画ファイルパス
"""
# 入力と出力が全く同じなら、なにもしない
if input_video != output_video:
# ffmpegコマンドを作成
# -i: 入力ファイル
# -c:v copy: ビデオストリームをコピー
# -map 0:v:0: 入力動画の最初のビデオストリームを選択
# -map 1:a:0: 入力オーディオの最初のオーディオストリームを選択
# -y: 既にファイルがあれば上書き
command = f'ffmpeg -i "{input_video}" -i "{input_audio}" -c:v copy -map 0:v:0 -map 1:a:0 -y "{output_video}"'
subprocess.call(command, shell=True)
def extract_audio(self, input_video,output_audio,format="aac"):
"""
動画から音声を指定されたフォーマットで抽出します。
Args:
input_video (str): 入力動画ファイルパス
output_audio (str): 出力オーディオファイルパス
format (str): 音声フォーマット(初期値=aac)
"""
# ffmpegコマンドを作成
# -i: 入力ファイル
# -c:a {format} : オーディオストリームを指定したフォーマットでコピー
# -y: 既にファイルがあれば上書き
command = f'ffmpeg -i "{input_video}" -c:a {format} -y "{output_audio}"'
subprocess.call(command, shell=True)
本クラスを直接使用する場合は、下記のサンプルを参考にしてください。
from audio_replace import AudioReplacer
ar = AudioReplacer()
# 動画の音声を入れ替える。(input_audio が動画の場合、音声を抽出する)
ar.overwrite_audio_from_video(input_video,input_audio,output_video)
# 動画の音声を入れ替える
ar.overwrite_audio(self, input_video, input_audio ,output_video):
# 動画から音声を抽出する
ar.extract_audio(self, input_video,output_audio,format="aac"):
design.txt
title:動画音声入れ替えツール
mode:light
max:1024,620
size:600,320
min:600,320
input_file:入力動画ファイル,ファイル選択
audio_file:音声抽出ファイル,ファイル選択
output_save:出力動画ファイル,ファイル選択
err_message:
replace_button:入力動画の音声を上書きする
design.txt の記述方法については、下記の記事で詳しく解説しています。
まとめ
今回は、「動画音声入れ替えツール」について、使い方から環境構築に至るまでの手順、仕様について紹介しました。
画面はファイル名の入力とボタンだけのシンプルな構成であるため、ノンコーディングでUI画面が簡単に作成できるCureateUIクラスを使いました。
ffmpeg は機能が多いため使い方が難しいですが、今回の様に機能別にクラスや関数にしておくことで、だれでも簡単に使えるようになります。
本記事で紹介するソースは基本的な部分のみになるので、皆さんのニーズにあわせて改造の上、ご利用いただければ幸いです。
コメント