Infrasound Removal Script (remove_low_freq.sh)

Shell Script Uploaded Mar 7, 2026 by Unknown 0 views 3.8 KB
Infrasound Removal Script (remove_low_freq.sh)
A Bash script that removes infrasound frequencies below a configurable threshold (default 100Hz) from video and audio files using ffmpeg. Non-destructive: video streams are copied without re-encoding, audio is filtered with a Butterworth high-pass filter with minimal artifacts.
infrasound ffmpeg bash audio filter tool
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"
Download SH

← Back to all documents