File size: 6,878 Bytes
bcb3d72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Audio Converter

This script scans a directory for audio files and converts them to WAV format.
It only processes audio files and skips all other file types.

Usage:
    python audio_converter.py --input_dir /path/to/audio/files --output_dir /path/to/output
"""

import os
import sys
import argparse
from pathlib import Path
from typing import List, Tuple
import subprocess


def print_info(message):
    print(f"INFO: {message}")

def print_error(message):
    print(f"ERROR: {message}")

def print_debug(message):
    if VERBOSE:
        print(f"DEBUG: {message}")

VERBOSE = False

# Audio formats that can be converted
AUDIO_FORMATS = {
    '.mp3', '.m4a', '.aac', '.flac', '.ogg', '.wma', '.aiff', '.ape', '.opus'
}


def check_dependencies() -> bool:
    """
    Check if required dependencies are installed.
    
    Returns:
        bool: True if dependencies are met, False otherwise
    """
    # Check for ffmpeg
    try:
        subprocess.run(
            ["ffmpeg", "-version"], 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE
        )
        print_info("ffmpeg is installed.")
        return True
    except FileNotFoundError:
        print_error("ffmpeg is not installed. Please install it before running this script.")
        return False


def scan_directory(directory: str) -> Tuple[List[Path], List[Path]]:
    """
    Scan directory for audio files.
    
    Args:
        directory: Path to the directory to scan
        
    Returns:
        Tuple containing lists of audio files and files to skip
    """
    audio_files = []
    skip_files = []
    
    dir_path = Path(directory)
    if not dir_path.exists():
        raise FileNotFoundError(f"Directory not found: {directory}")
    
    for file_path in dir_path.glob('**/*'):
        if file_path.is_file():
            file_ext = file_path.suffix.lower()
            
            if file_ext in AUDIO_FORMATS:
                audio_files.append(file_path)
            elif file_ext == '.wav':
                # Skip existing WAV files
                print_debug(f"Skipping existing WAV file: {file_path}")
                skip_files.append(file_path)
            else:
                # Skip non-audio files
                print_debug(f"Skipping non-audio file: {file_path}")
                skip_files.append(file_path)
    
    print_info(f"Found {len(audio_files)} audio files to convert")
    print_info(f"Skipping {len(skip_files)} files (WAV or non-audio)")
    
    return audio_files, skip_files


def convert_audio_to_wav(input_file: Path, output_file: Path) -> bool:
    """
    Convert audio file to WAV format using ffmpeg.
    
    Args:
        input_file: Path to input audio file
        output_file: Path to output WAV file
        
    Returns:
        bool: True if conversion was successful, False otherwise
    """
    try:
        # Ensure output directory exists
        output_file.parent.mkdir(parents=True, exist_ok=True)
        
        cmd = [
            "ffmpeg",
            "-y",  # Overwrite output file if it exists
            "-i", str(input_file),  # Input file
            "-acodec", "pcm_s16le",  # Output codec (16-bit PCM)
            "-ar", "44100",  # Sample rate (44.1kHz)
            "-ac", "1",  # Mono audio (1 channel)
            str(output_file)  # Output file
        ]
        
        process = subprocess.run(
            cmd,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE
        )
        
        if process.returncode != 0:
            print_error(f"Error converting {input_file}: {process.stderr.decode()}")
            return False
            
        print_info(f"Successfully converted {input_file} to WAV")
        return True
        
    except Exception as e:
        print_error(f"Error converting {input_file}: {str(e)}")
        return False


def process_files(audio_files: List[Path], input_dir: str, output_dir: str, 
                  preserve_structure: bool = True) -> Tuple[int, int]:
    """
    Process all identified audio files for conversion.
    
    Args:
        audio_files: List of audio files to convert
        input_dir: Input directory path 
        output_dir: Output directory path

    Returns:
        Tuple of successful conversions, failed conversions
    """
    input_base = Path(input_dir)
    output_base = Path(output_dir)
    
    success_count = 0
    failure_count = 0
    
    # Process audio files
    for audio_file in audio_files:
        if preserve_structure:
            rel_path = audio_file.relative_to(input_base)
            output_file = output_base / rel_path.with_suffix('.wav')
        else:
          
            output_file = output_base / f"{audio_file.stem}.wav"
        
        if convert_audio_to_wav(audio_file, output_file):
            success_count += 1
        else:
            failure_count += 1
    
    return success_count, failure_count


def parse_arguments() -> argparse.Namespace:
    """Parse command-line arguments."""
    parser = argparse.ArgumentParser(description="Convert audio files to WAV format")
    parser.add_argument('--input_dir', type=str, required=True, 
                        help='Directory containing files to convert')
    parser.add_argument('--output_dir', type=str, required=True, 
                        help='Directory for output WAV files')
    parser.add_argument('--flat', action='store_true',
                        help='Don\'t preserve directory structure')
    parser.add_argument('--verbose', '-v', action='store_true',
                        help='Enable verbose output')
    
    return parser.parse_args()


def main():
    """Main function to run the script."""
    global VERBOSE
    
    try:
        args = parse_arguments()
        
        VERBOSE = args.verbose
        
        print_info(f"Input directory: {args.input_dir}")
        print_info(f"Output directory: {args.output_dir}")
        
        if not check_dependencies():
            print_error("Missing dependencies. Please install required packages.")
            sys.exit(1)
        
        # Create output directory if it doesn't exist
        os.makedirs(args.output_dir, exist_ok=True)
        
        audio_files, skip_files = scan_directory(args.input_dir)
        
        # Process files
        preserve_structure = not args.flat
        success_count, failure_count = process_files(
            audio_files, 
            args.input_dir, 
            args.output_dir, 
            preserve_structure
        )
        
        # Print summary
        print_info(f"Conversion complete!")
        print_info(f"Successfully converted: {success_count} files")
        print_info(f"Failed conversions: {failure_count} files")
        
    except Exception as e:
        print_error(f"Error during execution: {str(e)}")
        sys.exit(1)


if __name__ == "__main__":
    main()