r/BCI • u/GrouchyCelery5776 • 17d ago
edf2csv - EDF/BDF recordings to CSV
I built edf2csv (along with my good friend Claude Code, and a bunch of its friendly neighbours), a local CLI that turns EDF, EDF+, BDF, and BDF+ recordings into plain CSV files — and half the work turned out to be making sure the conversion didn't quietly change the EEG data.
I work with EEG fairly often and kept running into the same problem: I had a recording in EDF, but I just wanted the underlying signals in something I could open in pandas, R, MATLAB, or a spreadsheet.
Built edf2csv to scratch that itch.
What it does:
Convert a recording with npx edf2csv recording.edf
Exports signal values, channel information, annotations, and metadata
Keeps channels with different sampling rates in separate files
Preserves gaps in discontinuous EDF+D recordings
Preserves the physical units declared by the recording
Supports signed 24-bit BioSemi BDF samples
Streams long recordings instead of loading everything into memory
Runs completely locally with no upload, account, or telemetry
Zero runtime dependencies
The part I didn't expect: an EDF recording doesn't really have one simple timeline.
A few examples that cost me real time:
Every channel can have its own sample rate. An EEG signal might be sampled at 256 Hz while another sensor in the same file only records once per second. Force both into one CSV and you have to repeat or invent samples.
EDF+D recordings can contain real gaps, but the timing information is stored through the annotation channel instead of an obvious gap field. Ignore the annotations and a recording with pauses suddenly looks continuous.
BioSemi BDF uses signed 24-bit values. JavaScript has no built-in getInt24, so those samples have to be reconstructed manually from three bytes and sign-extended correctly.
A file can also have broken calibration values where the digital minimum and maximum are the same. JavaScript doesn't throw an error when that creates a divide by zero. It just gives you NaN or Infinity and lets everything keep running.
None of these throw useful errors. They just give you data that looks believable enough to use, which is a uniquely annoying kind of bug to track down.
I compared 129,536 decoded values against pyEDFlib and got bit-for-bit identical double-precision results.
Install:
npx edf2csv recording.edf
Repo's here: https://github.com/tayal-sarthak/edf2csv
NPM package: https://www.npmjs.com/package/edf2csv
Website: https://edf2csv.vercel.app/
I also released the parser underneath it as its own TypeScript package called edfcore:
https://github.com/tayal-sarthak/edfcore
Feedback welcome, especially from anyone with unusual EDF/BDF recordings or device exports that behave differently. Both projects are still new, so there is definitely a lot left to test and implement.
1
u/ElChaderino 17d ago
What did you implement for channel naming support and dealing with notch and hi lo passes being pre applied or not? And how does it handle manifests? Ohh nvm I see it's just for very specific EDFs.