Batch Convert Audio with ffmpeg

for f in *.flac; do ffmpeg -v warning -i "$f" -map_metadata 0 -b:a 192k "${f%.flac}.mp3"; done

Inspired by this StackExchange post.

For a more complete script we can use this convert.sh bash script which includes cli options for input folder, output folder and bitrate.

#!/bin/bash

# if $1 is --help then print help message
if [ "$1" == "--help" ]; then
# print some ascii music convert art
    echo "-----------------------------------------------"
    echo "FLAC to MP3 Converter"
    echo "-----------------------------------------------"
    echo "This script converts FLAC files to MP3 format using ffmpeg."
    echo "It requires ffmpeg to be installed on your system."
    echo "-----------------------------------------------"
    echo "Usage: $0 <input_folder> <output_folder> [bitrate]"
    echo "./convert.sh /path/to/flac_files /path/to/output [bitrate]"
    echo "Optional: Specify a bitrate (128, 160, 192, 256, 320) for the output files."
    echo "Example: $0 /path/to/flac_files /path/to/output 192"
    echo "Supports: Local paths and SMB shares (smb://server/share)"
    exit 0
fi

# need folder input param and output folder param
if [ "$#" -lt 2 ]; then
    echo "Error: Invalid number of arguments."
    echo "Usage: $0 <input_folder> <output_folder>"
    exit 1
fi

input_folder="$1"
output_folder="$2"

bitrate="192"
prefix=${4:-""}

# if prefix addd - to the end of it
if [ -n "$prefix" ]; then
    prefix="${prefix}-"
fi

if [ -n "$3" ]; then
    echo "Input folder: $1 Output folder: $2 Bitrate: $3 Prefix: $prefix"
else
    echo "Input folder: $1 Output folder: $2 Bitrate: $bitrate (default) Prefix: $prefix"
fi

# check for user defined bitrate
if [ "$#" -ge 3 ] && [ -n "$3" ]; then
    # check if the bitrate is a valid number
    if ! [[ "$3" =~ ^[0-9]+$ ]]; then
        echo "Error: Bitrate must be a valid number."
        exit 1
    fi
    # check if bitrate is an actual bitrate options being 128, 160, 192, 256, 320
    if [ "$3" -ne 128 ] && [ "$3" -ne 160 ] && [ "$3" -ne 192 ] && [ "$3" -ne 256 ] && [ "$3" -ne 320 ]; then
        echo "Error: Bitrate must be one of the following: 128, 160, 192, 256, 320."
        exit 1
    fi
    bitrate="$3"
fi

# create output folder if it does not exist
if [ ! -d "$output_folder" ]; then
    mkdir -p "$output_folder"
    if [ $? -ne 0 ]; then
        echo "Error: Could not create output folder: $output_folder"
        exit 1
    fi
    echo "Created output folder: $output_folder"
fi

# ehoc the full path of the input and output folders
echo "Input folder: $(cd "$input_folder" && pwd)"
echo "Output folder: $output_folder"

audio_ext="mp3"

# get the extension of the input files it could be flac or mp3 or m4a
for ext in "flac" "mp3" "m4a" "ogg"; do
    shopt -s nullglob
    files=("$input_folder"/*."$ext")
    if [ ${#files[@]} -eq 0 ]; then
        echo "No .$ext files found in $input_folder"
    else
        echo "Found ${#files[@]} .$ext files in $input_folder"
        audio_ext="$ext"
        break
    fi
    shopt -u nullglob
done

for f in "$input_folder"/*."$audio_ext"; do
  echo "Processing file: $f"
  out_file="${f##*/}"
  out_file="${out_file%.*}" # remove extension
  out_file="${out_file//./‐}" # replace dots with dashes
  out_file="${prefix}${out_file// /-}.mp3" # replace spaces with dashes
  ffmpeg -v warning -i "$f" -vn -map_metadata 0 -b:a "$bitrate"k "$output_folder/$out_file"
  if [ $? -ne 0 ]; then
    echo "Error processing file: $f"
    continue
  fi
  echo "Successfully converted ${output_folder}/$out_file"
done