2026-04-22 21:52:09 -04:00

153 lines
6.2 KiB
Python

"""CLI interface for audio extraction operations"""
from pathlib import Path
import tempfile
from audio_extractor.extractor import AudioExtractor
class AudioExtractorCLI:
"""Command-line interface for audio extraction"""
def __init__(self):
self.extractor = AudioExtractor()
def extract_audio(self, target: str, output: str) -> None:
"""
Extract audio from video file(s).
Args:
target: Path to video file or folder containing video files
output: Output folder path for extracted audio files
"""
target_path = Path(target)
output_path = Path(output)
if not target_path.exists():
raise FileNotFoundError(f"Target not found: {target}")
# Create output directory if it doesn't exist
output_path.mkdir(parents=True, exist_ok=True)
if target_path.is_file():
# Single file
print(f"Extracting audio from: {target_path}")
self.extractor.extract_audio_from_file(target_path, output_path)
elif target_path.is_dir():
# Directory - process all video files
video_files = self.extractor.find_video_files(target_path)
if not video_files:
print(f"No video files found in: {target_path}")
return
print(f"Found {len(video_files)} video file(s)")
for i, video_file in enumerate(video_files, 1):
print(f"[{i}/{len(video_files)}] Extracting audio from: {video_file.name}")
try:
self.extractor.extract_audio_from_file(video_file, output_path)
except Exception as e:
print(f" Error processing {video_file.name}: {e}")
else:
raise ValueError(f"Invalid target: {target}")
def add_audio_tracks(self, target: str, input_folder: str, output: str, title: str = None) -> None:
"""
Add audio tracks to video files.
Args:
target: Path to folder containing audio files
input_folder: Path to folder containing video files
output: Output folder for processed video files
title: Title/name for the added audio tracks (applied to all added tracks)
"""
audio_folder = Path(target)
video_folder = Path(input_folder)
output_folder = Path(output)
if not audio_folder.exists():
raise FileNotFoundError(f"Audio folder not found: {target}")
if not video_folder.exists():
raise FileNotFoundError(f"Video folder not found: {input_folder}")
# Create output directory if it doesn't exist
output_folder.mkdir(parents=True, exist_ok=True)
# Find all audio files
audio_files = self.extractor.find_audio_files(audio_folder)
if not audio_files:
print(f"No audio files found in: {audio_folder}")
return
print(f"Found {len(audio_files)} audio file(s)")
# Group audio files by matching video
videos_with_audio = {}
# Process each audio file
for audio_file in audio_files:
try:
# Find matching video file
video_file = self.extractor.find_matching_video(audio_file, video_folder)
video_stem = video_file.stem
if video_stem not in videos_with_audio:
videos_with_audio[video_stem] = {
'video': video_file,
'audio_files': []
}
videos_with_audio[video_stem]['audio_files'].append(audio_file)
except FileNotFoundError as e:
print(f"⚠ Skipped: {e}")
if not videos_with_audio:
print("No matching video files found for audio files")
return
print(f"Found {len(videos_with_audio)} video(s) to process\n")
# Process each video with its audio files
for idx, (video_stem, data) in enumerate(videos_with_audio.items(), 1):
video_file = data['video']
audio_files_to_add = data['audio_files']
print(f"[{idx}/{len(videos_with_audio)}] Processing: {video_file.name}")
try:
# Copy original video to output
video_ext = video_file.suffix
output_video = output_folder / f"{video_stem}{video_ext}"
print(f" → Copying original video...")
self.extractor.copy_file(video_file, output_video)
# Process each audio file
for audio_idx, audio_file in enumerate(audio_files_to_add):
# For multiple audio files, use temp file for intermediate versions
if len(audio_files_to_add) > 1 and audio_idx < len(audio_files_to_add) - 1:
# Use temp file for intermediate processing
temp_dir = Path(tempfile.gettempdir())
working_video = temp_dir / f"{video_stem}_processing_{audio_idx}{video_ext}"
else:
# Use final output file
working_video = output_folder / f"{video_stem}_new{video_ext}"
# Determine input file (original copy for first audio, or previous output)
if audio_idx == 0:
input_video = output_video
else:
# Use the previous output as input
prev_output = temp_dir / f"{video_stem}_processing_{audio_idx - 1}{video_ext}" if audio_idx > 0 else output_video
input_video = prev_output if prev_output.exists() else output_video
print(f" ↳ Adding audio: {audio_file.name}")
self.extractor.add_audio_to_video(
input_video,
audio_file,
working_video,
track_title=title
)
except Exception as e:
print(f" ✗ Error: {e}")