Local beatmap timing and BPM drift inspection for Beat Saber maps.
BeatSync Lab compares a deterministic beat grid with an FFT-based view of the song audio. It provides editable timing anchors, BPM-event inspection, playback controls, and manual export workflows without uploading files or overwriting the source map.
- Loads a Beat Saber map folder directly in the browser.
- Matches
Info.dat, song audio, and available difficulty files. - Renders an FFT-based timing view with a BPM-derived beat grid.
- Creates editable timing anchors and derives BPM sections between them.
- Supports selection, movement, and deletion of BPM events and anchors.
- Provides playback speed, pitch preservation, follow mode, and a metronome.
- Transfers verified BPM events between difficulties with a preview step.
- Copies BPM JSON or downloads an updated difficulty file.
- Processes all map and audio data locally.
- A current desktop browser with Web Audio API, Canvas, File API, and local directory selection support.
- Chrome or another Chromium-based browser is recommended for the File System Access API.
- A Beat Saber map folder containing song audio and at least one difficulty
.datfile.
No installation, package manager, build process, or local server is required.
- Open the hosted application or download the repository and open
index.htmldirectly in the browser. - Select
Open local map folderand choose a Beat Saber map folder. - Select the difficulty and timing range to inspect.
- Compare the beat grid with the audio view, add or adjust anchors, and verify the derived BPM events.
- Use
Copy BPM JSON,Download difficulty .dat, or the BPM transfer controls to export the result.
- Navigate to a section where the beat grid and audio appear misaligned.
- Drag a blue beat-line handle onto the corresponding audio position, or right-click the plot to add an anchor at the nearest beat line.
- Drag the orange anchor horizontally to refine its audio position.
- Add another anchor at a later verified beat. Consecutive anchors determine the BPM of the section between them.
- Inspect the derived BPM labels, fitted-segment list, and cursor measurement before exporting.
The first anchor adjusts the preceding BPM section so its nearest beat line lands on the anchor. Each following anchor creates a boundary for the next calculated section. Existing BPM events outside the fitted anchor range are preserved.
| Action | Control |
|---|---|
| Set the visible range | Edit Current beat and Beats per view |
| Set bar emphasis | Select a meter or enter a custom beats-per-bar value |
| Pan the timing view | Mouse wheel, drag inside the plot, or use the timeline scrollbar |
| Zoom around the pointer | Ctrl + mouse wheel |
| Zoom in or out | + / - buttons or keyboard keys |
| Move one visible section | ArrowLeft / ArrowRight |
| Set the play cursor | Click inside the timing plot |
| Play or pause | Space or the Play / Pause button |
| Change playback speed | Set Speed from 0.25x to 2x |
| Preserve pitch | Enable Preserve pitch |
| Keep playback centered | Enable Follow |
| Enable beat clicks | Enable Metronome and set its volume |
| Create an anchor | Drag a blue beat-line handle or right-click the plot |
| Refine an anchor | Drag an orange anchor horizontally |
| Select an event or anchor | Click its BPM box or anchor |
| Select multiple items | Hold Ctrl while selecting |
| Move an unanchored BPM event | Drag its BPM box to another grid beat |
| Delete selected items | Delete |
Keyboard shortcuts are inactive while an input field is focused.
When Info.dat is available, BeatSync Lab uses it to locate the song audio and listed difficulties. It initially selects Standard / Normal when present, otherwise the first available Standard difficulty or the first listed difficulty.
If Info.dat is unavailable, the loader falls back to common filenames such as song.ogg, NormalStandard.dat, HardStandard.dat, and ExpertStandard.dat.
Recognized audio filename extensions are .ogg, .egg, .wav, and .mp3. Actual decoding support depends on the browser.
Browsers with the File System Access API can store the last selected directory handle locally so the next folder dialog starts in the same location. Other browsers use the directory-upload fallback when available.
Copy BPM JSONcopies the current_type: 100BPM-event list.Download difficulty .datcreates a copy of the active difficulty containing the current BPM events.- BPM transfer replaces only
_type: 100BPM events in the downloaded target difficulty.
BeatSync Lab does not modify source beatmap files. Timing anchors exist only in browser memory and are not included in exported files.
- BPM and grid calculations are deterministic, but their accuracy depends on correctly placed anchors.
- The spectrogram-like display is an FFT-based visual aid, not an automatic onset detector.
- Cursor uncertainty reflects the approximate time resolution of the rendered audio columns.
- Playback and the metronome are secondary verification aids; visual grid alignment remains the primary timing check.
- BPM editing and export currently target Beat Saber v2-style
_type: 100events. - Exported timing should be reviewed in the intended Beat Saber mapping workflow before release.
Selected map files and audio remain in the browser. BeatSync Lab does not upload them or send them to an external service.
The project intentionally uses one local HTML application with plain HTML, CSS, and JavaScript. It has no runtime dependencies, frontend framework, bundler, or generated build output.
| Path | Purpose |
|---|---|
index.html |
Complete application and GitHub Pages entry point |
.github/workflows/deploy-pages.yml |
Release-triggered GitHub Pages deployment |
docs/beatsync-lab.png |
README screenshot |
CHANGELOG.md |
Project history |
AGENTS.md |
Repository development guidelines |
LICENSE |
MIT License |
BeatSync Lab is a prototype for visual timing inspection and manual BPM correction. Exported results require deliberate verification by the mapper.
The hosted application is deployed from the commit attached to a published GitHub Release. Commits on main do not update the live site automatically.
Licensed under the MIT License.
Project history is documented in the changelog.
