プログラム作成

任意のMP3ファイルを設定して、その音声ファイルを再生しながら画面中央にその音声のオーディオビジュアライザーを表示するMP4動画ファイルを作成するPythonスクリプトを作成してください。 またArgumentParserモジュールを使用し、以下の項目をカスタマイズ可能としてください

回答

MP3ファイルから音声ビジュアライザー付きの動画を作成するスクリプトを作成します。

import argparse
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import librosa
import moviepy.editor as mpe
from pathlib import Path
import cv2
import tempfile

def create_audio_visualizer(
    mp3_path,
    output_path="audio.mp4",
    video_size=(1280, 720),
    viz_size=(1080, 520),
    bg_color="black",
    viz_color="red",
    loop_count=1
):
    # Load audio file
    y, sr = librosa.load(mp3_path)

    # Calculate duration
    duration = librosa.get_duration(y=y, sr=sr)

    # Set up the figure
    fig, ax = plt.subplots(figsize=(video_size[0]/100, video_size[1]/100), facecolor=bg_color)
    ax.set_facecolor(bg_color)

    # Calculate visualization area
    viz_left = (video_size[0] - viz_size[0]) / 2
    viz_bottom = (video_size[1] - viz_size[1]) / 2

    # Set axis limits and remove ticks
    ax.set_xlim(0, viz_size[0])
    ax.set_ylim(0, viz_size[1])
    ax.set_xticks([])
    ax.set_yticks([])

    # Number of bars in visualization
    n_bars = 50
    bars = ax.bar(
        np.linspace(0, viz_size[0], n_bars),
        np.zeros(n_bars),
        width=viz_size[0]/(n_bars*1.5),
        color=viz_color
    )

    # Frame update function
    def update(frame):
        # Calculate time in audio
        time = (frame / 30) % duration
        start_idx = int(time * sr)
        end_idx = start_idx + sr // 30

        if end_idx <= len(y):
            # Get audio chunk and calculate FFT
            chunk = y[start_idx:end_idx]
            fft = np.abs(np.fft.fft(chunk))
            fft = fft[:len(fft)//2]

            # Scale FFT values
            fft = fft / np.max(fft) * viz_size[1]

            # Update bar heights
            for bar, val in zip(bars, np.interp(np.linspace(0, len(fft), n_bars), np.arange(len(fft)), fft)):
                bar.set_height(val)

        return bars

    # Create animation
    total_frames = int(duration * 30 * loop_count)
    anim = FuncAnimation(
        fig,
        update,
        frames=total_frames,
        interval=1000/30,
        blit=True
    )

    # Save animation to temporary file
    with tempfile.NamedTemporaryFile(suffix='.mp4', delete=False) as temp_video:
        temp_video_path = temp_video.name
        anim.save(temp_video_path, writer='ffmpeg', fps=30)

    # Combine with audio
    video = mpe.VideoFileClip(temp_video_path)
    audio = mpe.AudioFileClip(mp3_path)

    if loop_count > 1:
        audio = audio.loop(loop_count)

    final_video = video.set_audio(audio)
    final_video.write_videofile(output_path, codec='libx264', audio_codec='aac')

    # Clean up
    plt.close()
    video.close()
    audio.close()
    Path(temp_video_path).unlink()

def main():
    parser = argparse.ArgumentParser(description='Create audio visualizer video from MP3')
    parser.add_argument('mp3_path', help='Path to input MP3 file')
    parser.add_argument('--output', default='audio.mp4', help='Output MP4 file path')
    parser.add_argument('--video-width', type=int, default=1280, help='Video width in pixels')
    parser.add_argument('--video-height', type=int, default=720, help='Video height in pixels')
    parser.add_argument('--viz-width', type=int, default=1080, help='Visualizer width in pixels')
    parser.add_argument('--viz-height', type=int, default=520, help='Visualizer height in pixels')
    parser.add_argument('--bg-color', default='black', help='Background color')
    parser.add_argument('--viz-color', default='red', help='Visualizer color')
    parser.add_argument('--loop-count', type=int, default=1, help='Number of times to loop the audio')

    args = parser.parse_args()

    create_audio_visualizer(
        args.mp3_path,
        args.output,
        (args.video_width, args.video_height),
        (args.viz_width, args.viz_height),
        args.bg_color,
        args.viz_color,
        args.loop_count
    )

if __name__ == '__main__':
    main()

このスクリプトを使用するには、以下のPythonパッケージが必要です:

pip install numpy matplotlib librosa moviepy opencv-python

スクリプトの主な機能:

  1. MP3ファイルから音声データを読み込み
  2. FFTを使用して周波数スペクトルを計算
  3. matplotlibを使用してビジュアライザーのアニメーションを作成
  4. 音声と映像を組み合わせてMP4ファイルを出力

使用例: