-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaudio_compressor.py
More file actions
executable file
·235 lines (198 loc) · 8.77 KB
/
audio_compressor.py
File metadata and controls
executable file
·235 lines (198 loc) · 8.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#!/usr/bin/env python3
"""
Audio File Size Reducer
Copyright (c) 2025 Danztee
MIT License - see LICENSE file for details
This script provides various methods to reduce audio file sizes:
1. Convert to different formats (MP3, AAC, OGG)
2. Adjust bitrate
3. Change sample rate
4. Convert to mono
5. Trim audio length
Requirements:
- pydub (for audio processing)
- ffmpeg (system dependency)
"""
import os
import sys
import argparse
from pathlib import Path
from typing import Optional, Tuple
try:
from pydub import AudioSegment
from pydub.utils import which
except ImportError:
print("Error: pydub is required. Install it with: pip install pydub")
sys.exit(1)
class AudioCompressor:
def __init__(self):
# Check if ffmpeg is available
if not which("ffmpeg"):
print("Warning: ffmpeg not found. Please install ffmpeg for better audio processing.")
print("On macOS: brew install ffmpeg")
print("On Ubuntu: sudo apt-get install ffmpeg")
print("On Windows: Download from https://ffmpeg.org/download.html")
def get_file_size_mb(self, file_path: str) -> float:
"""Get file size in MB"""
return os.path.getsize(file_path) / (1024 * 1024)
def compress_audio(self,
input_path: str,
output_path: str,
format: str = "mp3",
bitrate: str = "128k",
sample_rate: int = 22050,
channels: int = 2,
start_time: Optional[int] = None,
end_time: Optional[int] = None) -> Tuple[float, float]:
"""
Compress audio file with specified parameters
Args:
input_path: Path to input audio file
output_path: Path for output compressed file
format: Output format (mp3, aac, ogg, wav)
bitrate: Audio bitrate (e.g., "64k", "128k", "192k")
sample_rate: Sample rate in Hz
channels: Number of channels (1 for mono, 2 for stereo)
start_time: Start time in milliseconds (for trimming)
end_time: End time in milliseconds (for trimming)
Returns:
Tuple of (original_size_mb, compressed_size_mb)
"""
print(f"Loading audio file: {input_path}")
audio = AudioSegment.from_file(input_path)
original_size = self.get_file_size_mb(input_path)
print(f"Original file size: {original_size:.2f} MB")
# Trim audio if specified
if start_time is not None or end_time is not None:
start_ms = start_time if start_time is not None else 0
end_ms = end_time if end_time is not None else len(audio)
audio = audio[start_ms:end_ms]
print(f"Trimmed audio from {start_ms}ms to {end_ms}ms")
# Convert to mono if requested
if channels == 1:
audio = audio.set_channels(1)
print("Converted to mono")
# Resample if needed
if sample_rate != audio.frame_rate:
audio = audio.set_frame_rate(sample_rate)
print(f"Resampled to {sample_rate} Hz")
# Export with compression
print(f"Exporting to {format.upper()} format with {bitrate} bitrate...")
if format.lower() == "mp3":
audio.export(output_path, format="mp3", bitrate=bitrate)
elif format.lower() == "aac":
audio.export(output_path, format="aac", bitrate=bitrate)
elif format.lower() == "ogg":
audio.export(output_path, format="ogg", bitrate=bitrate)
elif format.lower() == "wav":
audio.export(output_path, format="wav")
else:
raise ValueError(f"Unsupported format: {format}")
compressed_size = self.get_file_size_mb(output_path)
compression_ratio = (1 - compressed_size / original_size) * 100
print(f"Compressed file size: {compressed_size:.2f} MB")
print(f"Compression ratio: {compression_ratio:.1f}%")
return original_size, compressed_size
def batch_compress(self,
input_dir: str,
output_dir: str,
format: str = "mp3",
bitrate: str = "128k",
sample_rate: int = 22050,
channels: int = 2) -> None:
"""
Compress all audio files in a directory
Args:
input_dir: Directory containing audio files
output_dir: Directory for compressed files
format: Output format
bitrate: Audio bitrate
sample_rate: Sample rate in Hz
channels: Number of channels
"""
input_path = Path(input_dir)
output_path = Path(output_dir)
if not input_path.exists():
print(f"Error: Input directory {input_dir} does not exist")
return
output_path.mkdir(exist_ok=True)
# Supported audio formats
audio_extensions = {'.mp3', '.wav', '.flac', '.aac', '.ogg', '.m4a', '.wma'}
total_original_size = 0
total_compressed_size = 0
for file_path in input_path.iterdir():
if file_path.is_file() and file_path.suffix.lower() in audio_extensions:
print(f"\nProcessing: {file_path.name}")
output_file = output_path / f"{file_path.stem}.{format}"
try:
original_size, compressed_size = self.compress_audio(
str(file_path),
str(output_file),
format=format,
bitrate=bitrate,
sample_rate=sample_rate,
channels=channels
)
total_original_size += original_size
total_compressed_size += compressed_size
except Exception as e:
print(f"Error processing {file_path.name}: {e}")
if total_original_size > 0:
total_compression_ratio = (1 - total_compressed_size / total_original_size) * 100
print(f"\nBatch compression complete!")
print(f"Total original size: {total_original_size:.2f} MB")
print(f"Total compressed size: {total_compressed_size:.2f} MB")
print(f"Total compression ratio: {total_compression_ratio:.1f}%")
def main():
parser = argparse.ArgumentParser(description="Audio File Size Reducer")
parser.add_argument("input", help="Input audio file or directory")
parser.add_argument("-o", "--output", help="Output file or directory")
parser.add_argument("-f", "--format", default="mp3",
choices=["mp3", "aac", "ogg", "wav"],
help="Output format (default: mp3)")
parser.add_argument("-b", "--bitrate", default="128k",
help="Audio bitrate (default: 128k)")
parser.add_argument("-r", "--sample-rate", type=int, default=22050,
help="Sample rate in Hz (default: 22050)")
parser.add_argument("-c", "--channels", type=int, default=2, choices=[1, 2],
help="Number of channels (default: 2)")
parser.add_argument("--start-time", type=int, help="Start time in milliseconds")
parser.add_argument("--end-time", type=int, help="End time in milliseconds")
parser.add_argument("--batch", action="store_true",
help="Process all audio files in directory")
args = parser.parse_args()
compressor = AudioCompressor()
if args.batch or os.path.isdir(args.input):
# Batch processing
output_dir = args.output or f"{args.input}_compressed"
compressor.batch_compress(
args.input,
output_dir,
format=args.format,
bitrate=args.bitrate,
sample_rate=args.sample_rate,
channels=args.channels
)
else:
# Single file processing
if not args.output:
input_path = Path(args.input)
output_path = input_path.parent / f"{input_path.stem}_compressed.{args.format}"
else:
output_path = args.output
try:
compressor.compress_audio(
args.input,
str(output_path),
format=args.format,
bitrate=args.bitrate,
sample_rate=args.sample_rate,
channels=args.channels,
start_time=args.start_time,
end_time=args.end_time
)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == "__main__":
main()