Spaces:
Running
Running
| """ | |
| 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)}") | |