Instantly share code, notes, and snippets.
Last active
November 21, 2024 03:50
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save psiborg/8199b7e2eb503d44ed0aef15a5c4c9bf to your computer and use it in GitHub Desktop.
Clean FLAC and MP3 tags
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# ============================================================================ | |
# clean-tags.sh | |
# | |
# Author: Jim Ing | |
# Date: 2024-11-19 | |
# | |
# Description: This script processes audio files (.mp3 and .flac) to remove | |
# specified metadata tags, displays metadata before and after | |
# cleaning, and saves the cleaned files in a designated output | |
# directory. | |
# Command-Line Options: | |
# --dry-run: Simulates processing without modifying any files. | |
# --output-dir DIR: Specifies a custom output directory. | |
# --keywords "keyword1 keyword2": Custom keywords for metadata filtering. | |
# ============================================================================ | |
# Define constants | |
DEFAULT_KEYWORDS="pmedia p.m.e.d.i.a k2nblog" | |
OUTPUT_DIR="cleaned" | |
# Flag to check if it's the first iteration | |
first=true | |
# Initialize counters for the summary report | |
processed_count=0 | |
skipped_count=0 | |
error_count=0 | |
# Dry run mode flag | |
dry_run=false | |
# List of metadata tags to be cleared from audio files | |
metadata_tags=( | |
"artists" | |
"barcode" | |
"catalog #" | |
"catalog number" | |
"comment" | |
"compilation" | |
"copyright" | |
"credits" | |
"encoded_by" | |
"encoded-by" | |
"encoder" | |
"encodersettings" | |
"grouping" | |
"info" | |
"isrc" | |
"itunesadvisory" | |
"label" | |
"lyrics-eng" | |
"organization" | |
"performer" | |
"pmedia" | |
"provider" | |
"publisher" | |
"releasecountry" | |
"source" | |
"tbpm" | |
"text" | |
"thnx" | |
"tit3" | |
"tlen" | |
"tmed" | |
"toly" | |
"tope" | |
"tpe4" | |
"trsn" | |
"tsrc" | |
"upload" | |
"uploader" | |
"work" | |
"wwwaudiofile" | |
"wwwaudiosource" | |
) | |
# Function to check prerequisites | |
check_prerequisites() { | |
command -v ffmpeg >/dev/null || { echo "Error: ffmpeg is not installed."; exit 1; } | |
command -v ffprobe >/dev/null || { echo "Error: ffprobe is not installed."; exit 1; } | |
} | |
# Function to create output directory | |
create_output_dir() { | |
if [ ! -d "$OUTPUT_DIR" ]; then | |
mkdir "$OUTPUT_DIR" | |
echo "Directory '$OUTPUT_DIR' created." | |
else | |
echo "Directory '$OUTPUT_DIR' already exists." | |
fi | |
} | |
# Function to process a single file | |
process_file() { | |
local file="$1" | |
echo "Processing file ($((processed_count + skipped_count + error_count + 1))/$total_files): $file" | |
# Display input metadata | |
echo "---[ Input Metadata ]---------------------------------------------------------" | |
for keyword in "${keyword_array[@]}"; do | |
ffprobe -i "$file" -show_entries format_tags -v quiet | grep -i "$keyword" | |
done | |
echo "------------------------------------------------------------------------------" | |
if $dry_run; then | |
echo "Dry run: Skipping metadata removal for $file." | |
((skipped_count++)) | |
return | |
fi | |
# Prepare metadata clearing arguments | |
local clear_metadata_args=() | |
for tag in "${metadata_tags[@]}"; do | |
clear_metadata_args+=("-metadata" "$tag=") | |
done | |
# Remove metadata and save cleaned file | |
if ffmpeg -i "$file" "${clear_metadata_args[@]}" -codec copy "$OUTPUT_DIR/$file" -loglevel warning; then | |
((processed_count++)) | |
echo "---[ Output Metadata ]--------------------------------------------------------" | |
ffprobe -i "$OUTPUT_DIR/$file" -show_entries format_tags -v quiet -print_format flat | |
echo "------------------------------------------------------------------------------" | |
else | |
echo "Error processing file: $file" | |
((error_count++)) | |
fi | |
} | |
# Function to display summary report | |
display_summary() { | |
echo | |
echo "------------------------------[ Summary Report ]------------------------------" | |
echo "Total files found: $total_files" | |
echo "Files processed: $processed_count" | |
echo "Files skipped: $skipped_count" | |
echo "Errors: $error_count" | |
echo "------------------------------------------------------------------------------" | |
} | |
# Parse command-line arguments | |
while [[ "$#" -gt 0 ]]; do | |
case $1 in | |
--dry-run) dry_run=true; shift ;; | |
--output-dir) OUTPUT_DIR="$2"; shift 2 ;; | |
--keywords) DEFAULT_KEYWORDS="$2"; shift 2 ;; | |
*) echo "Unknown option: $1"; exit 1 ;; | |
esac | |
done | |
# Parse keywords into an array | |
IFS=' ' read -r -a keyword_array <<< "${DEFAULT_KEYWORDS}" | |
# Start script execution | |
check_prerequisites | |
# Count total files for progress reporting | |
files=(*.mp3 *.flac) | |
total_files=0 | |
for file in "${files[@]}"; do | |
if [ -f "$file" ]; then | |
((total_files++)) | |
fi | |
done | |
if [ "$total_files" -eq 0 ]; then | |
echo "No .mp3 or .flac files found in the current directory." | |
exit 0 | |
fi | |
# Create the output directory | |
create_output_dir | |
# Process each file | |
for file in "${files[@]}"; do | |
if [ -f "$file" ]; then | |
process_file "$file" | |
# Ask the user whether to continue after processing the first file | |
if [ "$first" = true ]; then | |
first=false | |
read -p "Please review the above output. Do you want to continue (y/n)? " user_input | |
if [ "$user_input" != "y" ]; then | |
echo "Exiting..." | |
break | |
else | |
echo "Continuing..." | |
fi | |
fi | |
fi | |
done | |
# Display summary report | |
display_summary | |
# TODO: Replace original files with cleaned files |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment