add opus compression
This commit is contained in:
		
							
								
								
									
										0
									
								
								ffmpeg-flac-downsampling.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								ffmpeg-flac-downsampling.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										0
									
								
								file-cleaning.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								file-cleaning.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
								
								
									
										309
									
								
								flac-opus-compressing.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										309
									
								
								flac-opus-compressing.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,309 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Media Library FLAC to Opus Conversion Script
 | 
				
			||||||
 | 
					# Processes multiple albums in a media library, converting all FLAC files to Opus 448kbps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if ffmpeg is installed
 | 
				
			||||||
 | 
					if ! command -v ffmpeg &> /dev/null; then
 | 
				
			||||||
 | 
					    echo "Error: ffmpeg is not installed or not in PATH"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if ffmpeg has opus encoder support
 | 
				
			||||||
 | 
					if ! ffmpeg -encoders 2>/dev/null | grep -q "libopus"; then
 | 
				
			||||||
 | 
					    echo "Error: ffmpeg does not have Opus encoder support (libopus)"
 | 
				
			||||||
 | 
					    echo "Please install ffmpeg with Opus support"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to display usage
 | 
				
			||||||
 | 
					show_usage() {
 | 
				
			||||||
 | 
					    echo "Usage: $0 [OPTIONS] <media_library_path>"
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					    echo "Options:"
 | 
				
			||||||
 | 
					    echo "  -o, --output DIR     Output directory (default: creates _opus suffix)"
 | 
				
			||||||
 | 
					    echo "  -r, --replace        Replace original files with Opus (use with caution)"
 | 
				
			||||||
 | 
					    echo "  -p, --preserve       Create Opus files alongside original FLAC files"
 | 
				
			||||||
 | 
					    echo "  -t, --test           Test mode - show what would be processed"
 | 
				
			||||||
 | 
					    echo "  -f, --force          Force re-conversion of existing Opus files"
 | 
				
			||||||
 | 
					    echo "  -b, --bitrate RATE   Opus bitrate in kbps (default: 448)"
 | 
				
			||||||
 | 
					    echo "  -h, --help           Show this help message"
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					    echo "Examples:"
 | 
				
			||||||
 | 
					    echo "  $0 /path/to/music/library"
 | 
				
			||||||
 | 
					    echo "  $0 -o /path/to/output /path/to/music/library"
 | 
				
			||||||
 | 
					    echo "  $0 --test /path/to/music/library"
 | 
				
			||||||
 | 
					    echo "  $0 --replace /path/to/music/library"
 | 
				
			||||||
 | 
					    echo "  $0 -b 384 /path/to/music/library"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Default options
 | 
				
			||||||
 | 
					OUTPUT_DIR=""
 | 
				
			||||||
 | 
					REPLACE_MODE=false
 | 
				
			||||||
 | 
					PRESERVE_MODE=false
 | 
				
			||||||
 | 
					TEST_MODE=false
 | 
				
			||||||
 | 
					FORCE_MODE=false
 | 
				
			||||||
 | 
					OPUS_BITRATE=448
 | 
				
			||||||
 | 
					PROCESSED_COUNT=0
 | 
				
			||||||
 | 
					SKIPPED_COUNT=0
 | 
				
			||||||
 | 
					ERROR_COUNT=0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Parse command line arguments
 | 
				
			||||||
 | 
					while [[ $# -gt 0 ]]; do
 | 
				
			||||||
 | 
					    case $1 in
 | 
				
			||||||
 | 
					        -o|--output)
 | 
				
			||||||
 | 
					            OUTPUT_DIR="$2"
 | 
				
			||||||
 | 
					            shift 2
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -r|--replace)
 | 
				
			||||||
 | 
					            REPLACE_MODE=true
 | 
				
			||||||
 | 
					            shift
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -p|--preserve)
 | 
				
			||||||
 | 
					            PRESERVE_MODE=true
 | 
				
			||||||
 | 
					            shift
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -t|--test)
 | 
				
			||||||
 | 
					            TEST_MODE=true
 | 
				
			||||||
 | 
					            shift
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -f|--force)
 | 
				
			||||||
 | 
					            FORCE_MODE=true
 | 
				
			||||||
 | 
					            shift
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -b|--bitrate)
 | 
				
			||||||
 | 
					            OPUS_BITRATE="$2"
 | 
				
			||||||
 | 
					            shift 2
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -h|--help)
 | 
				
			||||||
 | 
					            show_usage
 | 
				
			||||||
 | 
					            exit 0
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        -*)
 | 
				
			||||||
 | 
					            echo "Unknown option: $1"
 | 
				
			||||||
 | 
					            show_usage
 | 
				
			||||||
 | 
					            exit 1
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					        *)
 | 
				
			||||||
 | 
					            MEDIA_LIBRARY="$1"
 | 
				
			||||||
 | 
					            shift
 | 
				
			||||||
 | 
					            ;;
 | 
				
			||||||
 | 
					    esac
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Validate bitrate
 | 
				
			||||||
 | 
					if ! [[ "$OPUS_BITRATE" =~ ^[0-9]+$ ]] || [ "$OPUS_BITRATE" -lt 64 ] || [ "$OPUS_BITRATE" -gt 512 ]; then
 | 
				
			||||||
 | 
					    echo "Error: Invalid bitrate '$OPUS_BITRATE'. Must be between 64 and 512 kbps"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if media library path is provided
 | 
				
			||||||
 | 
					if [ -z "$MEDIA_LIBRARY" ]; then
 | 
				
			||||||
 | 
					    echo "Error: Media library path is required"
 | 
				
			||||||
 | 
					    show_usage
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check if media library exists
 | 
				
			||||||
 | 
					if [ ! -d "$MEDIA_LIBRARY" ]; then
 | 
				
			||||||
 | 
					    echo "Error: Media library directory '$MEDIA_LIBRARY' not found"
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Set output directory if not specified
 | 
				
			||||||
 | 
					if [ -z "$OUTPUT_DIR" ] && [ "$REPLACE_MODE" = false ]; then
 | 
				
			||||||
 | 
					    OUTPUT_DIR="${MEDIA_LIBRARY}_opus"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to check if file needs conversion
 | 
				
			||||||
 | 
					needs_conversion() {
 | 
				
			||||||
 | 
					    local input_file="$1"
 | 
				
			||||||
 | 
					    local output_file="$2"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Check if input file is readable
 | 
				
			||||||
 | 
					    if [ ! -r "$input_file" ]; then
 | 
				
			||||||
 | 
					        echo "    WARNING: File not readable: $input_file"
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # If force mode, always convert
 | 
				
			||||||
 | 
					    if [ "$FORCE_MODE" = true ]; then
 | 
				
			||||||
 | 
					        return 0
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Check if output file already exists and is newer than input
 | 
				
			||||||
 | 
					    if [ -f "$output_file" ] && [ "$output_file" -nt "$input_file" ]; then
 | 
				
			||||||
 | 
					        return 1  # No conversion needed
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return 0  # Needs conversion
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to process a single FLAC file
 | 
				
			||||||
 | 
					process_flac_file() {
 | 
				
			||||||
 | 
					    local input_file="$1"
 | 
				
			||||||
 | 
					    local relative_path="$2"
 | 
				
			||||||
 | 
					    local output_file=""
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Determine output file path
 | 
				
			||||||
 | 
					    if [ "$REPLACE_MODE" = true ]; then
 | 
				
			||||||
 | 
					        # Replace .flac with .opus in same location
 | 
				
			||||||
 | 
					        output_file="${input_file%.flac}.opus"
 | 
				
			||||||
 | 
					    elif [ "$PRESERVE_MODE" = true ]; then
 | 
				
			||||||
 | 
					        local dir=$(dirname "$input_file")
 | 
				
			||||||
 | 
					        local filename=$(basename "$input_file" .flac)
 | 
				
			||||||
 | 
					        output_file="$dir/${filename}.opus"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        # Change extension from .flac to .opus
 | 
				
			||||||
 | 
					        local opus_relative_path="${relative_path%.flac}.opus"
 | 
				
			||||||
 | 
					        output_file="$OUTPUT_DIR/$opus_relative_path"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Check if conversion is needed
 | 
				
			||||||
 | 
					    if ! needs_conversion "$input_file" "$output_file"; then
 | 
				
			||||||
 | 
					        echo "  SKIP: $relative_path (Opus file exists and is newer)"
 | 
				
			||||||
 | 
					        ((SKIPPED_COUNT++))
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if [ "$TEST_MODE" = true ]; then
 | 
				
			||||||
 | 
					        echo "  WOULD CONVERT: $relative_path → $(basename "$output_file") @ ${OPUS_BITRATE}kbps"
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Create output directory if needed
 | 
				
			||||||
 | 
					    local output_dir=$(dirname "$output_file")
 | 
				
			||||||
 | 
					    if [ ! -d "$output_dir" ]; then
 | 
				
			||||||
 | 
					        echo "    Creating directory: $output_dir"
 | 
				
			||||||
 | 
					        if ! mkdir -p "$output_dir"; then
 | 
				
			||||||
 | 
					            echo "  ✗ ERROR: Cannot create output directory: $output_dir"
 | 
				
			||||||
 | 
					            ((ERROR_COUNT++))
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Verify input file exists and is readable
 | 
				
			||||||
 | 
					    if [ ! -f "$input_file" ]; then
 | 
				
			||||||
 | 
					        echo "  ✗ ERROR: Input file not found: $input_file"
 | 
				
			||||||
 | 
					        ((ERROR_COUNT++))
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if [ ! -r "$input_file" ]; then
 | 
				
			||||||
 | 
					        echo "  ✗ ERROR: Input file not readable: $input_file"
 | 
				
			||||||
 | 
					        ((ERROR_COUNT++))
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Create temporary file for safe processing
 | 
				
			||||||
 | 
					    local temp_file="${output_file}.tmp.opus"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    echo "  CONVERTING: $relative_path → Opus ${OPUS_BITRATE}kbps"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Convert the file to Opus
 | 
				
			||||||
 | 
					    echo "    Command: ffmpeg -i \"$input_file\" -c:a libopus -b:a ${OPUS_BITRATE}k -vbr on -compression_level 10 -y \"$temp_file\""
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if ffmpeg -i "$input_file" -c:a libopus -b:a "${OPUS_BITRATE}k" -vbr on -compression_level 10 -y "$temp_file" 2>"${temp_file}.log"; then
 | 
				
			||||||
 | 
					        # Move temp file to final location
 | 
				
			||||||
 | 
					        mv "$temp_file" "$output_file"
 | 
				
			||||||
 | 
					        echo "  ✓ DONE: $(basename "$output_file")"
 | 
				
			||||||
 | 
					        rm -f "${temp_file}.log"
 | 
				
			||||||
 | 
					        ((PROCESSED_COUNT++))
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        # If replace mode, remove original FLAC file
 | 
				
			||||||
 | 
					        if [ "$REPLACE_MODE" = true ]; then
 | 
				
			||||||
 | 
					            rm "$input_file"
 | 
				
			||||||
 | 
					            echo "    Removed original: $(basename "$input_file")"
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        echo "  ✗ ERROR: Failed to convert $relative_path"
 | 
				
			||||||
 | 
					        echo "    Error log saved to: ${temp_file}.log"
 | 
				
			||||||
 | 
					        if [ -f "${temp_file}.log" ]; then
 | 
				
			||||||
 | 
					            echo "    Last few lines of error:"
 | 
				
			||||||
 | 
					            tail -n 5 "${temp_file}.log" | sed 's/^/    /'
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					        rm -f "$temp_file"
 | 
				
			||||||
 | 
					        ((ERROR_COUNT++))
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Function to process an album directory
 | 
				
			||||||
 | 
					process_album() {
 | 
				
			||||||
 | 
					    local album_dir="$1"
 | 
				
			||||||
 | 
					    local album_name=$(basename "$album_dir")
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    echo "Processing album: $album_name"
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Find all FLAC files in the album directory
 | 
				
			||||||
 | 
					    local flac_files=()
 | 
				
			||||||
 | 
					    while IFS= read -r -d '' file; do
 | 
				
			||||||
 | 
					        flac_files+=("$file")
 | 
				
			||||||
 | 
					    done < <(find "$album_dir" -name "*.flac" -type f -print0)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if [ ${#flac_files[@]} -eq 0 ]; then
 | 
				
			||||||
 | 
					        echo "  No FLAC files found in $album_name"
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    # Process each FLAC file
 | 
				
			||||||
 | 
					    for flac_file in "${flac_files[@]}"; do
 | 
				
			||||||
 | 
					        local relative_path="${flac_file#$MEDIA_LIBRARY/}"
 | 
				
			||||||
 | 
					        process_flac_file "$flac_file" "$relative_path"
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    echo ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Main processing
 | 
				
			||||||
 | 
					echo "Media Library FLAC to Opus Converter"
 | 
				
			||||||
 | 
					echo "===================================="
 | 
				
			||||||
 | 
					echo "Input:   $MEDIA_LIBRARY"
 | 
				
			||||||
 | 
					echo "Bitrate: ${OPUS_BITRATE}kbps"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$TEST_MODE" = true ]; then
 | 
				
			||||||
 | 
					    echo "Mode:    TEST MODE (no files will be modified)"
 | 
				
			||||||
 | 
					elif [ "$REPLACE_MODE" = true ]; then
 | 
				
			||||||
 | 
					    echo "Mode:    REPLACE (original FLAC files will be deleted after conversion)"
 | 
				
			||||||
 | 
					elif [ "$PRESERVE_MODE" = true ]; then
 | 
				
			||||||
 | 
					    echo "Mode:    PRESERVE (Opus files created alongside originals)"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    echo "Output:  $OUTPUT_DIR"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$FORCE_MODE" = true ]; then
 | 
				
			||||||
 | 
					    echo "Force:   Enabled (will re-convert existing Opus files)"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Find all directories that contain FLAC files (potential albums)
 | 
				
			||||||
 | 
					album_dirs=()
 | 
				
			||||||
 | 
					while IFS= read -r -d '' dir; do
 | 
				
			||||||
 | 
					    if find "$dir" -maxdepth 1 -name "*.flac" -type f | grep -q .; then
 | 
				
			||||||
 | 
					        album_dirs+=("$dir")
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					done < <(find "$MEDIA_LIBRARY" -type d -print0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ ${#album_dirs[@]} -eq 0 ]; then
 | 
				
			||||||
 | 
					    echo "No albums with FLAC files found in $MEDIA_LIBRARY"
 | 
				
			||||||
 | 
					    exit 0
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Found ${#album_dirs[@]} album(s) with FLAC files"
 | 
				
			||||||
 | 
					echo ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Process each album
 | 
				
			||||||
 | 
					for album_dir in "${album_dirs[@]}"; do
 | 
				
			||||||
 | 
					    process_album "$album_dir"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Summary
 | 
				
			||||||
 | 
					echo "Conversion Summary:"
 | 
				
			||||||
 | 
					echo "=================="
 | 
				
			||||||
 | 
					echo "Converted: $PROCESSED_COUNT files"
 | 
				
			||||||
 | 
					echo "Skipped:   $SKIPPED_COUNT files (already converted or newer)"
 | 
				
			||||||
 | 
					echo "Errors:    $ERROR_COUNT files"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ "$ERROR_COUNT" -gt 0 ]; then
 | 
				
			||||||
 | 
					    exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
		Reference in New Issue
	
	Block a user