elfchart โ ELF Spectrogram Chart Generator
Generates a black-on-white FFT spectrogram of the infrasound / extremely-low-frequency (ELF) range from video or audio recordings. Charts
5 pixels per second at
1080 px height, showing the FFT below
100 Hz with horizontal markers at
50 Hz and
20 Hz, and appends a source filmstrip at the exact time markers for visual context to infrasound artifacts.
Uses
SoX,
ffmpeg,
ImageMagick, and
GNUPlot.
---
Output
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ 1080 px tall
โ filename โ HTTPS://ESUI.CC | ELF Chart (0โ100 Hz) โ
โ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ โโ (50 Hz)โ
โ โ (black = high mag)
โ ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท ยทยท (20 Hz)โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ 2 px spacer
โ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ ๐ (filmstrip thumbnails) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ time (5 px/sec) โ
- X axis โ time (horizontal); default 5 px per second
- Y axis โ frequency (vertical, 0 Hz at bottom, 100 Hz at top)
- Colour โ pure black/white; black = high magnitude, white = low
- Markers โ dashed lines at 50 Hz and 20 Hz labelled in grey
- Filmstrip โ video thumbnails aligned to the same time axis, one frame per 72 px interval (one still every ~14.4 seconds at default PPS)
---
Dependencies
| Tool | Purpose |
|---|
| SoX | Audio resampling, low-pass filter, and raw FFT spectrogram generation |
| ffmpeg | Audio extraction from MTS/MP4 and video thumbnail extraction |
ImageMagick (convert, mogrify) | Frequency-marker annotation, label overlay, filmstrip compositing |
| GNUPlot | Fallback annotator when ImageMagick is unavailable |
Install on Debian/Ubuntu:
sh
sudo apt install sox ffmpeg imagemagick gnuplot
---
Usage
elfchart.sh [OPTIONS] [FILE ...]
When no files are given the script scans the current directory (or
--dir) for
.mts,
.mp4, and
*.wav files.
Options
| Flag | Long form | Default | Description |
|---|
-H | --height NUM | 1080 | Chart height in pixels |
-p | --pps NUM | 5 | Pixels per second on the time axis |
-f | --max-freq HZ | 100 | Maximum frequency displayed (Hz) |
-r | --sample-rate HZ | 1000 | SoX resample rate (Nyquist = rate รท 2) |
-w | --max-width PX | 8000 | Maximum output image width (ImageMagick policy guard) |
-d | --dir PATH | . | Directory to scan for media files |
-o | --output-dir PATH | . | Directory for generated PNG files |
-i | --interactive | โ | Prompt for each setting; defaults shown in [] |
-h | --help | โ | Print help and exit |
Examples
sh
Process every MTS/MP4/WAV in the current directory with all defaults
./elfchart.sh
Interactive setup โ walks through every setting
./elfchart.sh -i
Single file, 10 px/sec, 720 px tall
./elfchart.sh -p 10 -H 720 recording.mp4
Batch scan a footage directory, write charts elsewhere
./elfchart.sh -d /mnt/camera -o ~/charts
Higher time resolution for a short clip
./elfchart.sh -p 20 clip.mts
---
How it works
Audio extraction โ ffmpeg pulls the mono audio track from MTS/MP4 files. WAV files are used directly.
ELF filter โ SoX resamples the audio to 1 kHz (configurable) and applies a low-pass filter at MAX_FREQ, isolating the infrasound band.
FFT spectrogram โ SoX generates a monochrome, axes-free PNG at the exact target pixel dimensions (-m -l -r).
Marker overlay โ ImageMagick draws dashed horizontal lines and labels at 50 Hz and 20 Hz, then adds the title and scale annotation. GNUPlot performs the same step if ImageMagick is not installed.
Filmstrip โ For video files, ffmpeg extracts thumbnails at intervals matching the time axis scale; ImageMagick assembles them into a strip and appends it below the chart.
---
Output files
Each input file produces one PNG named
<filename>elfchart.png in the output directory.
---
Notes
The 10 Hz empirical frequency offset in the Y-position calculation compensates for the way SoX aligns FFT frequency bins relative to the image boundary.
For recordings longer than MAXOUTPUTWIDTH รท PPS seconds the pixels-per-second value is automatically reduced to keep the image within the configured width limit.
Minimum image width is enforced as OUTPUT_HEIGHT + 100 px to guarantee landscape orientation.
All intermediate files are written to a temporary directory and cleaned up automatically on exit.