Skip to content

Instantly share code, notes, and snippets.

@yszheda
Created March 16, 2026 07:23
Show Gist options
  • Select an option

  • Save yszheda/763564e5bb5ce74517e7f0bb3386f151 to your computer and use it in GitHub Desktop.

Select an option

Save yszheda/763564e5bb5ce74517e7f0bb3386f151 to your computer and use it in GitHub Desktop.
Convert wav to flac
#!/usr/bin/env python3
import os
import subprocess
import sys
import argparse
# Default configuration
DEFAULT_COMPRESSION_LEVEL = 8 # 0-8, 8 is maximum
DEFAULT_LOG_NAME = "conversion_log_py.txt"
def parse_args():
"""Parse command line arguments"""
parser = argparse.ArgumentParser(
description="Batch convert WAV files to FLAC using ffmpeg"
)
parser.add_argument(
"--base-dir",
"-d",
default=os.getcwd(),
help=f'Base directory to search for WAV files (default: current directory "{os.getcwd()}")',
)
parser.add_argument(
"--log-file",
"-l",
help=f"Path to log file (default: {{base-dir}}/{DEFAULT_LOG_NAME})",
)
parser.add_argument(
"--compression-level",
"-c",
type=int,
default=DEFAULT_COMPRESSION_LEVEL,
choices=range(0, 9),
help=f"FLAC compression level 0-8 (default: {DEFAULT_COMPRESSION_LEVEL})",
)
return parser.parse_args()
def get_file_size(file_path):
"""Get file size in bytes"""
try:
return os.path.getsize(file_path)
except:
return 0
def convert_wav_to_flac(wav_path, flac_path, compression_level):
"""Convert WAV to FLAC using ffmpeg"""
cmd = [
"ffmpeg",
"-i",
wav_path,
"-c:a",
"flac",
"-compression_level",
str(compression_level),
"-y",
"-v",
"error",
flac_path,
]
result = subprocess.run(cmd, capture_output=True, text=True)
return (
result.returncode == 0
and os.path.exists(flac_path)
and os.path.getsize(flac_path) > 0
)
def main():
args = parse_args()
base_dir = os.path.abspath(args.base_dir)
if args.log_file:
log_file = os.path.abspath(args.log_file)
else:
log_file = os.path.join(base_dir, DEFAULT_LOG_NAME)
compression_level = args.compression_level
with open(log_file, "w", encoding="utf-8") as log:
log.write(
f"Starting WAV to FLAC conversion - {os.popen('date').read().strip()}\n"
)
log.write(f"Base directory: {base_dir}\n")
log.write(f"Compression level: {compression_level}\n\n")
# Find all WAV files
wav_files = []
for root, dirs, files in os.walk(base_dir):
for file in files:
if file.lower().endswith(".wav"):
wav_path = os.path.join(root, file)
wav_files.append(wav_path)
total_files = len(wav_files)
print(f"Found {total_files} WAV files to convert")
log.write(f"Found {total_files} WAV files\n\n")
print("-" * 50)
converted = 0
failed = 0
original_total = 0
compressed_total = 0
for idx, wav_path in enumerate(wav_files, 1):
# Create flac path
file_dir = os.path.dirname(wav_path)
file_name = os.path.basename(wav_path)
flac_name = os.path.splitext(file_name)[0] + ".flac"
flac_path = os.path.join(file_dir, flac_name)
print(
f"[{idx}/{total_files}] Converting: {os.path.relpath(wav_path, base_dir)}"
)
log.write(f"[{idx}/{total_files}] Converting: {wav_path}\n")
log.write(f" Output: {flac_path}\n")
original_size = get_file_size(wav_path)
original_total += original_size
if convert_wav_to_flac(wav_path, flac_path, compression_level):
compressed_size = get_file_size(flac_path)
compressed_total += compressed_size
# Delete original
try:
os.remove(wav_path)
print(f" [OK] Success - Original WAV deleted")
log.write(f" [OK] Success - Original deleted\n")
converted += 1
except Exception as e:
print(f" [WARN] Converted OK but failed to delete original: {e}")
log.write(f" [WARN] Converted OK but failed to delete original: {e}\n")
converted += 1
else:
print(f" [FAIL] FAILED to convert")
log.write(f" [FAIL] FAILED to convert\n")
failed += 1
# Get free space
try:
if os.name == "nt":
# Windows - get free space on the drive containing base_dir
import ctypes
# Get the drive letter from base_dir
drive = os.path.splitdrive(base_dir)[0] + "\\"
free_bytes = ctypes.c_ulonglong(0)
ctypes.windll.kernel32.GetDiskFreeSpaceExW(
ctypes.c_wchar_p(drive), None, None, ctypes.byref(free_bytes)
)
free_gb = free_bytes.value / (1024**3)
print(f" Free space left: {free_gb:.1f} GB")
except:
pass
log.write("\n")
sys.stdout.flush()
print("-" * 50)
print(f"Conversion completed:")
print(f" Success: {converted} files")
print(f" Failed: {failed} files")
log.write("\n" + "-" * 50 + "\n")
log.write(f"Conversion completed:\n")
log.write(f" Success: {converted} files\n")
log.write(f" Failed: {failed} files\n\n")
if converted > 0:
original_gb = original_total / (1024**3)
compressed_gb = compressed_total / (1024**3)
saved_gb = (original_total - compressed_total) / (1024**3)
saved_percent = (
(original_total - compressed_total) * 100 / original_total
if original_total > 0
else 0
)
print(f"\nSpace summary:")
print(f" Original total: {original_gb:.2f} GB")
print(f" Compressed total: {compressed_gb:.2f} GB")
print(f" Space saved: {saved_gb:.2f} GB ({saved_percent:.1f}%)")
log.write(f"Space summary:\n")
log.write(f" Original total: {original_gb:.2f} GB\n")
log.write(f" Compressed total: {compressed_gb:.2f} GB\n")
log.write(f" Space saved: {saved_gb:.2f} GB ({saved_percent:.1f}%)\n")
log.write(f"\nConversion finished at {os.popen('date').read().strip()}\n")
if __name__ == "__main__":
main()
#!/bin/bash
# Batch convert WAV to FLAC with ffmpeg
# Correct handling for filenames with spaces
# Convert one by one and delete original after success
# Default configuration
DEFAULT_COMPRESSION_LEVEL=8 # 0-8, 8 is maximum
DEFAULT_LOG_NAME="conversion_log.txt"
# Parse command line arguments
BASE_DIR=""
LOG_FILE=""
COMPRESSION_LEVEL="$DEFAULT_COMPRESSION_LEVEL"
while [[ $# -gt 0 ]]; do
case "$1" in
-d|--base-dir)
BASE_DIR="$2"
shift 2
;;
-l|--log-file)
LOG_FILE="$2"
shift 2
;;
-c|--compression-level)
COMPRESSION_LEVEL="$2"
shift 2
;;
-h|--help)
echo "Usage: $0 [OPTIONS]"
echo "Batch convert WAV files to FLAC using ffmpeg"
echo ""
echo "Options:"
echo " -d, --base-dir PATH Base directory to search for WAV files (default: current directory)"
echo " -l, --log-file PATH Path to log file (default: {base-dir}/$DEFAULT_LOG_NAME)"
echo " -c, --compression-level 0-8 FLAC compression level (default: $DEFAULT_COMPRESSION_LEVEL)"
echo " -h, --help Show this help message"
exit 0
;;
*)
echo "Unknown option: $1" >&2
echo "Use $0 --help for usage" >&2
exit 1
;;
esac
done
# Set defaults if not provided
if [[ -z "$BASE_DIR" ]]; then
BASE_DIR="$(pwd)"
fi
if [[ -z "$LOG_FILE" ]]; then
LOG_FILE="$BASE_DIR/$DEFAULT_LOG_NAME"
fi
echo "Starting WAV to FLAC conversion - $(date)" > "$LOG_FILE"
echo "Base directory: $BASE_DIR" >> "$LOG_FILE"
echo "Compression level: $COMPRESSION_LEVEL" >> "$LOG_FILE"
# Count files first
TOTAL_FILES=$(find "$BASE_DIR" -name "*.wav" -type f | wc -l)
echo "Found $TOTAL_FILES WAV files" >> "$LOG_FILE"
echo "Found $TOTAL_FILES WAV files to convert"
echo "----------------------------------------"
CONVERTED=0
FAILED=0
ORIGINAL_TOTAL=0
COMPRESSED_TOTAL=0
# Use find with -print0 and properly read null-separated output
find "$BASE_DIR" -name "*.wav" -type f -print0 | while IFS= read -r -d '' WAV_FILE; do
# Create output FLAC path (same directory, .wav -> .flac)
FLAC_FILE="${WAV_FILE%.wav}.flac"
CONV_NUM=$((CONVERTED + FAILED + 1))
echo "[$CONV_NUM/$TOTAL_FILES] Converting: $WAV_FILE"
echo "Converting: $WAV_FILE -> $FLAC_FILE" >> "$LOG_FILE"
# Get original file size (handle both GNU and BSD stat)
ORIGINAL_SIZE=$(stat -c%s "$WAV_FILE" 2>/dev/null || stat -f%z "$WAV_FILE")
ORIGINAL_TOTAL=$((ORIGINAL_TOTAL + ORIGINAL_SIZE))
# Convert WAV to FLAC
ffmpeg -i "$WAV_FILE" -c:a flac -compression_level "$COMPRESSION_LEVEL" -y -v error "$FLAC_FILE"
if [ $? -eq 0 ] && [ -f "$FLAC_FILE" ] && [ -s "$FLAC_FILE" ]; then
COMPRESSED_SIZE=$(stat -c%s "$FLAC_FILE" 2>/dev/null || stat -f%z "$FLAC_FILE")
COMPRESSED_TOTAL=$((COMPRESSED_TOTAL + COMPRESSED_SIZE))
# Delete original WAV to save space
rm -f "$WAV_FILE"
if [ $? -eq 0 ]; then
echo "✓ Success - Original WAV deleted" >> "$LOG_FILE"
echo "✓ Success - Original WAV deleted"
CONVERTED=$((CONVERTED + 1))
else
echo "⚠ Converted OK but failed to delete original" >> "$LOG_FILE"
echo "⚠ Converted OK but failed to delete original"
CONVERTED=$((CONVERTED + 1))
fi
else
echo "✗ FAILED to convert $WAV_FILE" | tee -a "$LOG_FILE"
FAILED=$((FAILED + 1))
fi
# Show free space - get the mount point from base_dir
MOUNT_POINT=$(df "$BASE_DIR" | tail -1 | awk '{print $1}')
FREE_SPACE=$(df -h "$MOUNT_POINT" | tail -1 | awk '{print $4}')
echo "Free space left: $FREE_SPACE"
echo "" >> "$LOG_FILE"
done
echo "----------------------------------------" | tee -a "$LOG_FILE"
echo "Conversion completed:" | tee -a "$LOG_FILE"
echo " Success: $CONVERTED files" | tee -a "$LOG_FILE"
echo " Failed: $FAILED files" | tee -a "$LOG_FILE"
# Calculate total savings if bc is available
if [ $CONVERTED -gt 0 ] && command -v bc >/dev/null 2>&1; then
ORIGINAL_GB=$(echo "scale=2; $ORIGINAL_TOTAL / 1024 / 1024 / 1024" | bc)
COMPRESSED_GB=$(echo "scale=2; $COMPRESSED_TOTAL / 1024 / 1024 / 1024" | bc)
SAVED_GB=$(echo "scale=2; ($ORIGINAL_TOTAL - $COMPRESSED_TOTAL) / 1024 / 1024 / 1024" | bc)
SAVED_PERCENT=$(echo "scale=1; ($ORIGINAL_TOTAL - $COMPRESSED_TOTAL) * 100 / $ORIGINAL_TOTAL" | bc)
echo "" | tee -a "$LOG_FILE"
echo "Space summary:" | tee -a "$LOG_FILE"
echo " Original total: $ORIGINAL_GB GB" | tee -a "$LOG_FILE"
echo " Compressed total: $COMPRESSED_GB GB" | tee -a "$LOG_FILE"
echo " Space saved: $SAVED_GB GB ($SAVED_PERCENT%)" | tee -a "$LOG_FILE"
elif [ $CONVERTED -gt 0 ]; then
ORIGINAL_GB=$((ORIGINAL_TOTAL / 1024 / 1024 / 1024))
COMPRESSED_GB=$((COMPRESSED_TOTAL / 1024 / 1024 / 1024))
SAVED_GB=$(((ORIGINAL_TOTAL - COMPRESSED_TOTAL) / 1024 / 1024 / 1024))
echo "" | tee -a "$LOG_FILE"
echo "Space summary (approx):" | tee -a "$LOG_FILE"
echo " Original total: ~$ORIGINAL_GB GB" | tee -a "$LOG_FILE"
echo " Compressed total: ~$COMPRESSED_GB GB" | tee -a "$LOG_FILE"
echo " Space saved: ~$SAVED_GB GB" | tee -a "$LOG_FILE"
fi
echo "" >> "$LOG_FILE"
echo "Conversion finished at $(date)" >> "$LOG_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment