"""
概要: Whisperとpydubを使用して、オーディオファイルを文節単位で指定された最大サイズに分割するスクリプトです。
詳細説明:
このスクリプトは、入力されたオーディオファイルをWhisperモデルで文字起こしし、得られた文節(セグメント)情報に基づいて音声を分割します。
各分割チャンクが指定された最大サイズ(MB)を超えないように、文節の区切りを考慮してファイルを生成します。
コマンドライン引数を使用することで、入力ファイル、出力ディレクトリ、Whisperモデルサイズ、各チャンクの最大サイズ、
出力フォーマット、ビットレート、Whisperの言語設定をカスタマイズできます。
関連リンク: :doc:`split_audio_usage`
"""
import os
import sys
# ライブラリチェック用の関数(インポート時に勝手に終了させないため)
[ドキュメント]
def check_dependencies():
"""必要なライブラリがインストールされているか確認する。"""
missing = []
for lib in ["pydub", "whisper"]:
try:
__import__(lib)
except ImportError:
missing.append(lib)
if missing:
print(f"Error: Missing libraries: {', '.join(missing)}")
print("pip install whisper pydub PyAudio")
return False
return True
# 依存関係があればインポート(この段階では実行しない)
try:
import whisper
from pydub import AudioSegment
except ImportError:
pass
[ドキュメント]
def get_estimated_size_bytes(segment, bitrate):
"""
オーディオセグメントの推定ファイルサイズ(バイト単位)を計算します。
:param segment: AudioSegment: 対象のセグメント。
:param bitrate: str: ビットレート(例: '128k')。
:returns: int: 推定バイト数。
"""
seconds = len(segment) / 1000.0
kbps = int(bitrate.replace("k", ""))
return int(kbps * 1000 / 8 * seconds)
[ドキュメント]
def run_split(input_file, output_dir, model_size, max_size_mb, output_format, bitrate, language):
"""
メインの分割処理を実行する関数。
"""
if not os.path.isfile(input_file):
print(f"エラー: ファイルが見つかりません: {input_file}")
return False
# ===== Whisper文字起こし =====
print("Whisperで文節を考慮してセグメント分割中...")
model = whisper.load_model(model_size)
result = model.transcribe(input_file, verbose=True, language=language)
segments = result["segments"]
# ===== 音声の読み込み =====
ext = os.path.splitext(input_file)[1].lower().lstrip(".")
audio = AudioSegment.from_file(input_file, format=ext)
# ===== 出力ディレクトリ作成 =====
os.makedirs(output_dir, exist_ok=True)
# ===== 分割・保存 =====
current_chunk = AudioSegment.empty()
current_size = 0
chunk_index = 0
for seg in segments:
start_ms = int(seg["start"] * 1000)
end_ms = int(seg["end"] * 1000)
segment_audio = audio[start_ms:end_ms]
est_size = get_estimated_size_bytes(segment_audio, bitrate)
if current_size + est_size > max_size_mb * 1024 * 1024:
out_path = os.path.join(output_dir, f"chunk_{chunk_index:03}.{output_format}")
print(f"> 保存: {out_path}")
current_chunk.export(out_path, format=output_format, bitrate=bitrate)
chunk_index += 1
current_chunk = segment_audio
current_size = est_size
else:
current_chunk += segment_audio
current_size += est_size
if len(current_chunk) > 0:
out_path = os.path.join(output_dir, f"chunk_{chunk_index:03}.{output_format}")
print(f"> 保存: {out_path}")
current_chunk.export(out_path, format=output_format, bitrate=bitrate)
return True
[ドキュメント]
def main():
"""コマンドライン実行時のエントリポイント。"""
if not check_dependencies():
sys.exit(1)
# デフォルト設定
params = {
"input_file": "your_audio.mp3",
"output_dir": "split_audio",
"model_size": "small",
"max_size_mb": 150,
"output_format": "mp3",
"bitrate": "128k",
"language": "ja"
}
# 引数の解析(sys.argvの安全な処理)
argv = sys.argv
if len(argv) > 1: params["input_file"] = argv[1]
if len(argv) > 2: params["output_dir"] = argv[2]
if len(argv) > 3: params["model_size"] = argv[3]
if len(argv) > 4: params["max_size_mb"] = int(argv[4])
if len(argv) > 5: params["output_format"] = argv[5]
if len(argv) > 6: params["bitrate"] = argv[6]
success = run_split(**params)
if not success:
sys.exit(1)
print("✅ 文節を考慮して分割保存しました。")
# --- 実行ガード ---
if __name__ == "__main__":
main()