LinguaStream / src /audio /extractor.py
Maaz1's picture
new upload
952467c
"""
Audio extraction utilities for the video translator application.
"""
import os
import subprocess
from pathlib import Path
from src.utils.logger import get_logger
from config import OUTPUT_DIR, FFMPEG_AUDIO_PARAMS
logger = get_logger(__name__)
def extract_audio(video_path):
"""
Extract audio from video file using ffmpeg.
Args:
video_path (str): Path to the input video file
Returns:
Path: Path to the extracted audio file
Raises:
Exception: If audio extraction fails
"""
try:
video_path = Path(video_path)
logger.info(f"Extracting audio from video: {video_path}")
# Create output filename based on input filename
video_name = video_path.stem
audio_path = OUTPUT_DIR / f"{video_name}_audio.{FFMPEG_AUDIO_PARAMS['format']}"
# Use ffmpeg to extract audio
cmd = [
'ffmpeg',
'-i', str(video_path),
'-vn', # No video
'-acodec', FFMPEG_AUDIO_PARAMS['codec'],
'-ar', str(FFMPEG_AUDIO_PARAMS['sample_rate']),
'-ac', str(FFMPEG_AUDIO_PARAMS['channels']),
'-y', # Overwrite output file
str(audio_path)
]
logger.debug(f"Running command: {' '.join(cmd)}")
process = subprocess.run(cmd, capture_output=True, text=True)
if process.returncode != 0:
error_message = f"Audio extraction failed: {process.stderr}"
logger.error(error_message)
raise Exception(error_message)
logger.info(f"Audio extraction successful: {audio_path}")
return audio_path
except Exception as e:
logger.error(f"Audio extraction failed: {str(e)}", exc_info=True)
raise Exception(f"Audio extraction failed: {str(e)}")
def get_video_duration(video_path):
"""
Get the duration of a video file in seconds.
Args:
video_path (str): Path to the video file
Returns:
float: Duration in seconds
Raises:
Exception: If duration extraction fails
"""
try:
video_path = Path(video_path)
logger.info(f"Getting duration for video: {video_path}")
cmd = [
'ffprobe',
'-v', 'error',
'-show_entries', 'format=duration',
'-of', 'default=noprint_wrappers=1:nokey=1',
str(video_path)
]
process = subprocess.run(cmd, capture_output=True, text=True)
if process.returncode != 0 or not process.stdout.strip():
error_message = f"Failed to get video duration: {process.stderr}"
logger.error(error_message)
raise Exception(error_message)
duration = float(process.stdout.strip())
logger.info(f"Video duration: {duration} seconds")
return duration
except Exception as e:
logger.error(f"Failed to get video duration: {str(e)}", exc_info=True)
raise Exception(f"Failed to get video duration: {str(e)}")
def create_silent_audio(duration, output_path=None):
"""
Create a silent audio file with the specified duration.
Args:
duration (float): Duration in seconds
output_path (str, optional): Path to save the silent audio file
Returns:
Path: Path to the silent audio file
Raises:
Exception: If silent audio creation fails
"""
try:
if output_path is None:
output_path = OUTPUT_DIR / f"silent_{int(duration)}s.wav"
else:
output_path = Path(output_path)
logger.info(f"Creating silent audio track of {duration} seconds")
cmd = [
'ffmpeg',
'-f', 'lavfi',
'-i', f'anullsrc=r={FFMPEG_AUDIO_PARAMS["sample_rate"]}:cl=stereo',
'-t', str(duration),
'-q:a', '0',
'-y',
str(output_path)
]
logger.debug(f"Running command: {' '.join(cmd)}")
process = subprocess.run(cmd, capture_output=True, text=True)
if process.returncode != 0:
error_message = f"Silent audio creation failed: {process.stderr}"
logger.error(error_message)
raise Exception(error_message)
logger.info(f"Silent audio created: {output_path}")
return output_path
except Exception as e:
logger.error(f"Failed to create silent audio: {str(e)}", exc_info=True)
raise Exception(f"Failed to create silent audio: {str(e)}")