BASH script to remove Infrasound from Media
Infrasound BASH script remover for double blind study proposal.
SH
remove_low_freq.sh
#!/bin/bash
# Remove infrasound frequencies below hearing threshold (default 100Hz)
# Non-destructive: video streams copied, audio filtered with minimal artifacts
set -e
# Default values
CUTOFF=100
OUTPUT_SUFFIX="_filtered"
usage() {
echo "Usage: $0 [-c cutoff_hz] [-o output_file] input_file"
echo ""
echo "Supported formats: wav, mp3, flac, aac, m4a, mp4, mts, mkv, avi, mov"
echo ""
echo "Options:"
echo " -c Cutoff frequency in Hz (default: 100)"
echo " -o Output file (default: input${OUTPUT_SUFFIX}.ext)"
echo ""
echo "Example:"
echo " $0 video.mp4"
echo " $0 -c 80 recording.mts"
echo " $0 -c 100 -o clean.mp4 noisy.mp4"
exit 1
}
# Parse arguments
while getopts "c:o:h" opt; do
case $opt in
c) CUTOFF="$OPTARG" ;;
o) OUTPUT="$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
# Check for input file
if [[ -z "$1" ]]; then
echo "Error: No input file specified"
usage
fi
INPUT="$1"
if [[ ! -f "$INPUT" ]]; then
echo "Error: File '$INPUT' not found"
exit 1
fi
# Get file extension (lowercase)
EXTENSION="${INPUT##*.}"
EXTENSION_LOWER=$(echo "$EXTENSION" | tr '[:upper:]' '[:lower:]')
# Generate output filename if not specified
if [[ -z "$OUTPUT" ]]; then
BASENAME="${INPUT%.*}"
# MTS files output to MP4 for better compatibility
if [[ "$EXTENSION_LOWER" == "mts" ]]; then
OUTPUT="${BASENAME}${OUTPUT_SUFFIX}.mp4"
else
OUTPUT="${BASENAME}${OUTPUT_SUFFIX}.${EXTENSION}"
fi
fi
# Determine if input is video or audio-only
case "$EXTENSION_LOWER" in
mp4|mts|m2ts|mkv|avi|mov|webm|wmv|flv)
IS_VIDEO=true
;;
*)
IS_VIDEO=false
;;
esac
echo "Input: $INPUT"
echo "Output: $OUTPUT"
echo "Cutoff: ${CUTOFF}Hz (removing infrasound below this)"
echo "Type: $([ "$IS_VIDEO" = true ] && echo "Video (stream copy)" || echo "Audio")"
echo ""
# Build ffmpeg command
# High-pass filter settings:
# - f=${CUTOFF}: cutoff frequency
# - poles=2: 12dB/octave rolloff (gentle, preserves transients)
# - width_type=q, width=0.707: Butterworth response (maximally flat passband)
AUDIO_FILTER="highpass=f=${CUTOFF}:poles=2:width_type=q:width=0.707"
if [[ "$IS_VIDEO" == true ]]; then
# Video file: copy video stream, only filter audio
# Detect output format for audio codec selection
OUT_EXT="${OUTPUT##*.}"
OUT_EXT_LOWER=$(echo "$OUT_EXT" | tr '[:upper:]' '[:lower:]')
case "$OUT_EXT_LOWER" in
mp4|m4v|mov)
# AAC for MP4 containers - high quality VBR
AUDIO_CODEC="-c:a aac -b:a 256k"
;;
mkv|webm)
# Opus for MKV/WebM - excellent quality
AUDIO_CODEC="-c:a libopus -b:a 256k"
;;
*)
# Default to AAC
AUDIO_CODEC="-c:a aac -b:a 256k"
;;
esac
ffmpeg -i "$INPUT" \
-c:v copy \
-af "$AUDIO_FILTER" \
$AUDIO_CODEC \
-map 0:v? -map 0:a? -map 0:s? \
-movflags +faststart \
"$OUTPUT"
else
# Audio-only file: preserve format quality
OUT_EXT="${OUTPUT##*.}"
OUT_EXT_LOWER=$(echo "$OUT_EXT" | tr '[:upper:]' '[:lower:]')
case "$OUT_EXT_LOWER" in
wav)
AUDIO_CODEC="-c:a pcm_s24le"
;;
flac)
AUDIO_CODEC="-c:a flac -compression_level 8"
;;
mp3)
AUDIO_CODEC="-c:a libmp3lame -q:a 0"
;;
aac|m4a)
AUDIO_CODEC="-c:a aac -b:a 256k"
;;
*)
# Let ffmpeg decide based on output extension
AUDIO_CODEC=""
;;
esac
ffmpeg -i "$INPUT" \
-af "$AUDIO_FILTER" \
$AUDIO_CODEC \
"$OUTPUT"
fi
echo ""
echo "Done! Infrasound below ${CUTOFF}Hz removed."
echo "Output saved to: $OUTPUT"