Skip to content

Beatmaps ​

Create, inspect, import, and export beatmaps and their storyboards.

create-storyboard ​

Builds a beatmap and storyboard from three images, then imports the finished set.

Full source

sh
cd examples/create-storyboard
npm install
npm start

Open the Realm together with its files folder. This example writes both database records and file content, so it does not use read-only mode.

js
const 
osu
=
init
(
realmPath
, {
schemaVersion
: 51,
filesFolderPath
:
filesPath
})
View source

Read the three images and put each buffer in the content-addressed file store. The returned hash is what the beatmap set keeps in Realm.

js
const [
bgBuf
,
logoBuf
,
spBuf
] = [
readFileSync
(
bgPath
),
readFileSync
(
logoPath
),
readFileSync
(
spPath
)]
const
images
= [
{
filename
:
bgPath
.
split
(/[\\/]/).
pop
(),
content
:
bgBuf
,
hash
:
osu
.
files
.
put
(
bgBuf
).
hash
},
{
filename
:
logoPath
.
split
(/[\\/]/).
pop
(),
content
:
logoBuf
,
hash
:
osu
.
files
.
put
(
logoBuf
).
hash
},
{
filename
:
spPath
.
split
(/[\\/]/).
pop
(),
content
:
spBuf
,
hash
:
osu
.
files
.
put
(
spBuf
).
hash
},
]
View source

A storyboard is split into layers. Here, every sprite goes into the foreground layer. Commands can be chained, which keeps a short animation readable without hiding its timing.

js
const 
sb
= new
Storyboard
()
const
fg
=
sb
.
getLayer
("Foreground")
const
bg
= new
StoryboardSprite
(
images
[0],
Anchor
.
Centre
, {
x
: 320,
y
: 240 })
bg
.
addAlpha
(
Easing
.
None
, 0, 8000, 1, 0).
addScale
(
Easing
.
Out
, 0, 1000, 1.1, 0.9)
fg
.
add
(
bg
)
const
logo
= new
StoryboardSprite
(
images
[1],
Anchor
.
Centre
, {
x
: 320,
y
: -50 })
logo
.
addAlpha
(
Easing
.
In
, 500, 1500, 1, 0).
addMoveY
(
Easing
.
Out
, 1500, 3000, 240, -50)
fg
.
add
(
logo
)
const
sp
= new
StoryboardSprite
(
images
[2],
Anchor
.
Centre
, {
x
: 100,
y
: 100 })
const
loop
=
sp
.
addLoopingGroup
(2000, 5)
loop
.
addAlpha
(
Easing
.
None
, 0, 400, 0.8, 0).
addScale
(
Easing
.
None
, 0, 400, 1.5, 0.5)
fg
.
add
(
sp
)
View source

Serialize the plain beatmap object back to .osu text, then store that text like any other file.

js
const 
osuContent
=
osu
.
beatmap
.
serialize
(
beatmap
)
const
osuHash
=
osu
.
files
.
put
(
Buffer
.
from
(
osuContent
)).
hash
View source

Register the set after all of its files have hashes. importSet writes the set, beatmap, and file references in one operation.

js
const 
result
=
osu
.
sets
.
importSet
({
onlineID
: -1,
setHash
,
status
: 0,
protected
: false,
files
:
allFiles
,
beatmaps
: [{
filename
:
osuFile
,
hash
:
osuHash
,
md5Hash
:
createHash
('md5').
update
(
Buffer
.
from
(
osuContent
)).
digest
('hex'),
osuBeatmap
:
beatmap
,
}], })
View source

API used: init · OsuFilesAPI#files · OsuFilesAPI#beatmap · OsuFilesAPI#sets · Storyboard · StoryboardSprite · StoryboardLoopingGroup · Anchor · Easing

explore-storyboard ​

Opens a beatmap and lets you browse its storyboard one layer and element at a time.

Full source

sh
cd examples/explore-storyboard
npm install
npm start

Start with the available sets. The labels use the first beatmap's metadata so the picker shows an artist and title instead of a Realm ID.

js
const 
sets
=
osu
.
sets
.
get
.
map
(
s
=> ({
item
:
s
,
label
: `${
s
.
Beatmaps
?.[0]?.
Metadata
?.
Artist
} - ${
s
.
Beatmaps
?.[0]?.
Metadata
?.
Title
} (#${
s
.
OnlineID
})`
}))
View source

Realm only stores the beatmap record. getFullData also reads and parses the .osu file, which is where the storyboard lives.

js
const 
data
=
osu
.
beatmap
.
getFullData
(
String
(
beatmap
.ID))
if (!
data
?.
storyboard
) {
console
.
log
("No storyboard on this beatmap."); return }
const
sb
=
data
.
storyboard
View source

NOTE

Query results are detached, read-only snapshots. Use osu.sets.open(id) or osu.beatmap.save(...) when you need to keep an edit.

Each layer contains sprites, animations, and samples. Pick an element to print its commands, including commands nested in loops and triggers.

js
const 
layers
= [...
sb
.
layers
.
entries
()].
map
(([
name
,
layer
]) => ({
item
: {
name
,
layer
},
label
: `${
name
} (${
layer
.
elements
.
length
} elements)`,
})) const
picked
= await
pick
(
layers
, `Layers - ${
beatmap
.DifficultyName} (q=quit)`)
View source

API used: init · OsuFilesAPI#sets · OsuFilesAPI#beatmap · OsuBeatmap · Storyboard · StoryboardLayer · StoryboardCommandGroup

export-newest-osz ​

Exports the most recently added beatmap set as an .osz archive.

Full source

sh
cd examples/export-newest-osz
npm install
npm start

Sort the sets by DateAdded and take the first result. If Realm is empty, there is nothing to export.

js
const 
newest
=
initialized
.
sets
.
get
.
sortedBy
('DateAdded').
first
()
if (!
newest
) {
console
.
log
('No beatmap sets found.')
return }
View source

Export by Realm ID. The exporter reads the beatmaps and their referenced files, then packs them into one .osz archive.

js
await 
initialized
.
osz
.
export
(
newest
.
ID
.
toString
(),
outputPath
)
View source

API used: init · OsuFilesAPI#sets · OsuFilesAPI#osz

import-beatmap ​

Imports every .osz in a folder and deletes each archive after a successful import.

Full source

sh
cd examples/import-beatmap
npm install
npm start

Read the chosen directory and keep only files with an .osz extension. checkHash makes the file store verify content before accepting it.

js
const 
allFiles
= await
readdir
(
beatmapDir
)
const
oszFiles
=
allFiles
.
filter
(
f
=>
extname
(
f
).
toLowerCase
() === '.osz')
View source

Import one archive at a time. A successful import returns the set ID and its beatmaps; only then does the example remove the original archive.

js
const 
result
= await
initialized
.
osz
.
import
(
fullPath
)
console
.
log
(` OK: setID=${
result
.
onlineID
} beatmaps=${
result
.
beatmaps
.
length
}`)
await
rm
(
fullPath
)
View source

API used: init · OsuFilesAPI#osz · BeatmapSetData

Released under the MIT License.