← API Reference
Luau SDK

Drop-in for AssetService

NEW
AudioScape:getAssetService()

On this pageGetting started

Getting started

If you already call AssetService:SearchAudioAsync, you can point it at AudioScape by changing one line. The AudioSearchParams you build and the AudioPages you iterate stay exactly the same, including AdvanceToNextPageAsync, IsFinished, and raising on failure rather than returning an error.

Luau (Roblox)
local AssetService = game:GetService("AssetService")   -- before
local AssetService = AudioScape:getAssetService()      -- after

-- Everything below is unchanged.
local params = Instance.new("AudioSearchParams")
params.SearchKeyword = "rainy night jazz"

local pages = AssetService:SearchAudioAsync(params)
for _, audio in pages:GetCurrentPage() do
    print(audio.Title, audio.Artist, audio.Duration)
end

Search then runs against AudioScape's catalog, matched on meaning rather than keywords. AudioSubType routes the call — Music searches music, SoundEffect searches sound effects.

Assumes the SDK is installed and keyed — see the Quickstart.

Always returns results

Whenever AudioScape can't serve a query, the call routes to the real AssetService:SearchAudioAsync and returns from there instead. Your players get audio either way, so the swap only ever adds to what native search already gives you.

Pass { fallback = false } to handle those cases yourself.

Other methods

Only SearchAudioAsync is overridden. Every other member forwards straight to the real service, so the rest of your AssetService code behaves exactly as it does today.

Luau (Roblox)
local AssetService = AudioScape:getAssetService()

-- Runs against AudioScape's catalog.
local pages = AssetService:SearchAudioAsync(params)

-- Goes straight to Roblox, exactly as before.
local meta = AssetService:GetAudioMetadataAsync({ "rbxassetid://1837879082" })
local bundle = AssetService:GetBundleDetailsAsync(bundleId)

What you gain

Native audio search matches keywords against titles and tags. AudioScape matches on what a track sounds like, and every result carries metadata the native API has no field for.

Luau (Roblox)
for _, audio in pages:GetCurrentPage() do
    -- Every field the native API returns.
    print(audio.Title, audio.Artist, audio.Duration, audio.Tags)

    -- Plus fields native has no equivalent for.
    print(audio.Genre, audio.Bpm, audio.Score)

    sound.SoundId = "rbxassetid://" .. audio.AssetId
end
FieldDescription
AssetIdThe asset ID as a string, ready to concatenate onto rbxassetid://
Genre / GenreSlugCanonical genre and its URL-safe slug (music only)
BpmTempo, when known (music only)
ScoreRelevance to your query — compare results against each other, not against a fixed scale

What's different

  • IsEndorsed is always false. That's Roblox's own endorsement flag and we don't track it. The field is present so code that reads it keeps working.
  • Results come from our catalog, not Roblox's. Everything we return is public and usable in any experience, but an asset we haven't ingested won't appear. If you need a specific ID, look it up directly with search.

From a LocalScript

Boomboxes, radios and jukeboxes usually search from the client. Enable client access once on the server, then use the same shim on AudioScapeClient.

Luau (Roblox)
-- Server, once:
AudioScape:enableClientAccess()

-- LocalScript:
local AudioScapeClient = require(
    game:GetService("ReplicatedStorage"):WaitForChild("AudioScapeClient")
)
local AssetService = AudioScapeClient:getAssetService()
local pages = AssetService:SearchAudioAsync(params)

The request and the result mapping both happen on the server — HttpService is server-only — so your key never reaches the client.