Nick021402 commited on
Commit
f71b19d
·
verified ·
1 Parent(s): 6b10d56

Create audio.utils.py

Browse files
Files changed (1) hide show
  1. audio.utils.py +110 -0
audio.utils.py ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # audio_utils.py - Audio processing utilities
2
+ import logging
3
+ from typing import List, Optional
4
+ import os
5
+ import tempfile
6
+ from pydub import AudioSegment
7
+ from pydub.utils import which
8
+
9
+ logger = logging.getLogger(__name__)
10
+
11
+ class AudioProcessor:
12
+ def __init__(self):
13
+ self._check_dependencies()
14
+
15
+ def _check_dependencies(self):
16
+ """Check if required audio processing tools are available."""
17
+ # Check for ffmpeg
18
+ if not which("ffmpeg"):
19
+ logger.warning("ffmpeg not found. Some audio operations may fail.")
20
+
21
+ def merge_and_convert_to_mp3(
22
+ self,
23
+ audio_files: List[str],
24
+ output_path: str
25
+ ) -> Optional[str]:
26
+ """
27
+ Merge multiple audio files and convert to MP3.
28
+
29
+ Args:
30
+ audio_files: List of paths to audio files to merge
31
+ output_path: Path for the output MP3 file
32
+
33
+ Returns:
34
+ Path to the merged MP3 file, or None if failed
35
+ """
36
+ try:
37
+ if not audio_files:
38
+ logger.error("No audio files to merge")
39
+ return None
40
+
41
+ logger.info(f"Merging {len(audio_files)} audio files...")
42
+
43
+ # Start with empty audio
44
+ merged_audio = AudioSegment.empty()
45
+
46
+ for i, audio_file in enumerate(audio_files):
47
+ if not os.path.exists(audio_file):
48
+ logger.warning(f"Audio file not found: {audio_file}")
49
+ continue
50
+
51
+ try:
52
+ # Load audio segment
53
+ segment = AudioSegment.from_wav(audio_file)
54
+
55
+ # Add a small pause between segments (500ms)
56
+ if i > 0:
57
+ pause = AudioSegment.silent(duration=500)
58
+ merged_audio += pause
59
+
60
+ # Add the segment
61
+ merged_audio += segment
62
+
63
+ logger.info(f"Added segment {i+1}/{len(audio_files)}")
64
+
65
+ except Exception as e:
66
+ logger.error(f"Failed to process audio file {audio_file}: {e}")
67
+ continue
68
+
69
+ if len(merged_audio) == 0:
70
+ logger.error("No audio content to export")
71
+ return None
72
+
73
+ # Normalize audio levels
74
+ merged_audio = self._normalize_audio(merged_audio)
75
+
76
+ # Export as MP3
77
+ logger.info(f"Exporting to MP3: {output_path}")
78
+ merged_audio.export(
79
+ output_path,
80
+ format="mp3",
81
+ bitrate="128k",
82
+ parameters=["-q:a", "2"] # Good quality
83
+ )
84
+
85
+ # Verify the file was created
86
+ if os.path.exists(output_path) and os.path.getsize(output_path) > 0:
87
+ duration = len(merged_audio) / 1000.0 # Convert to seconds
88
+ logger.info(f"Successfully created MP3: {duration:.1f} seconds")
89
+ return output_path
90
+ else:
91
+ logger.error("Failed to create MP3 file")
92
+ return None
93
+
94
+ except Exception as e:
95
+ logger.error(f"Failed to merge audio files: {e}")
96
+ return None
97
+
98
+ def _normalize_audio(self, audio: AudioSegment) -> AudioSegment:
99
+ """Normalize audio levels."""
100
+ try:
101
+ # Apply some basic audio processing
102
+ # Normalize to -6dB to avoid clipping
103
+ target_dBFS = -6.0
104
+ change_in_dBFS = target_dBFS - audio.dBFS
105
+ normalized_audio = audio.apply_gain(change_in_dBFS)
106
+
107
+ return normalized_audio
108
+ except Exception as e:
109
+ logger.warning(f"Failed to normalize audio: {e}")
110
+ return audio