I’ve recently published a game that allows players to act as DJs. In the game, you can approach any player’s booth, tune in, and enjoy the music together. The game has been steadily growing, which shows there’s a huge opportunity for music-driven user creation on Roblox.
My goal is to build an infinite library of music and creative expression — powered entirely by the community. However, players are currently limited to uploading music only for personal use.
At the moment, there’s no way for players to upload music to the marketplace and share it with my experience unless one of the following conditions is met:
The player is on my friend list.
This would require me to manually add every artist, and I’d still be limited to 1,000 friends in total.
The player (or a role in my group) has full edit access to the experience.
Obviously, I can’t give edit permissions to everyone who wants to upload music.
Both of these options severely limit the scalability and automation of not just my project, but any experience that aims to create a user-generated music library.
I’m also aware that one possible workaround is using existing music distribution services (like DistroKid, Clippsly, etc.). However, using these means that — at least within Roblox — players lose credit as the actual owners of their music, since it’s published under the distributor’s name.
I strongly believe Roblox is a platform where music artists can start careers, grow, and make it big. As a game creator, it would be a dream come true to build a platform within Roblox that supports that vision.
My question is: What would be a scalable solution in the near future to allow players to upload and share music within an experience without giving them edit access or adding them as friends?
Hi there, as distributors on Roblox we fill up the metadata of each track that we distribute via our DDEX pipeline. Metadata we distribute include cover art, duration, title, genre and the artist name of the creator which can be directly used in studio and in games.
Below you can find a dummy script that shows you how to do so:
local MarketplaceService = game:GetService("MarketplaceService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local AssetService = game:GetService("AssetService")
local handleElement = script.Parent.Handle
local notifyUser = ReplicatedStorage.NotifyUser
local audioPlayer = handleElement.AudioPlayer
local audioAnalyser = handleElement.AudioAnalyzer
local audioTextToSpeech = handleElement.AudioTextToSpeech
local function stripAssetText(songId)
if string.sub(songId, 1, 13) == "rbxassetid://" then
return string.sub(songId, 14)
elseif string.find(songId, "roblox.com") then
return string.match(songId, "%d+")
end
return songId
end
local function isValidSong(songId)
return tonumber(songId) ~= nil
end
local function sendNotification(player, title, message)
notifyUser:FireClient(player, title, message)
end
script.Parent.NewSong.OnServerEvent:Connect(function(player, songId)
songId = stripAssetText(songId)
if not isValidSong(songId) then
sendNotification(player, "Error", "Invalid Song ID: " .. tostring(songId))
return
end
local successAssetInfo, assetInfo = pcall(function()
return MarketplaceService:GetProductInfo(songId, Enum.InfoType.Asset)
end)
local successSongInfo, metadataArray = pcall(function()
return AssetService:GetAudioMetadataAsync({songId})
end)
if successAssetInfo and assetInfo and successSongInfo and metadataArray then
local metadata = metadataArray[1]
if metadata and metadata.AssetId then
local title = metadata.Title or assetInfo.Name or "Unknown Title"
local artist = metadata.Artist or assetInfo.Creator.Name or "Unknown Artist"
local isLegal = assetInfo.IsPublicDomain
local isWhitelistedCreator = assetInfo.Creator.Name == "Clippsly" or assetInfo.Creator.Name == "Blanka HQ"
if isLegal or isWhitelistedCreator then
if songId == "0" then
audioPlayer:Stop()
sendNotification(player, "Now Playing", "Stopped Playing Audio.")
else
handleElement.Parent.Bass.Enabled = true
audioPlayer.TimePosition = 0
audioPlayer.AssetId = "rbxassetid://" .. songId
local announcement = player.Name .. " is now playing " .. title .. " by " .. artist
audioTextToSpeech.Text = announcement
audioTextToSpeech.VoiceId = "2"
audioTextToSpeech.TimePosition = 0
local played = false
local function playSong()
if not played then
played = true
audioPlayer:Play()
sendNotification(player, "Now Playing", "Playing '" .. title .. "' by " .. artist)
end
end
local connection
connection = audioTextToSpeech.Ended:Connect(function()
if connection then
connection:Disconnect()
connection = nil
end
playSong()
end)
audioTextToSpeech:Play()
task.spawn(function()
local t = 0
while not played and t < 5 do
task.wait(0.2)
t = t + 0.2
end
if not played then
if connection then
connection:Disconnect()
connection = nil
end
playSong()
end
end)
end
else
sendNotification(player, "Error", "The audio is not public or you don't have permission to play it.")
end
else
sendNotification(player, "Error", "Failed to retrieve metadata for song ID: " .. tostring(songId))
end
else
audioPlayer:Stop()
sendNotification(player, "Error", "Failed to retrieve song information for ID: " .. tostring(songId))
end
end)
Additionally, if there is a need we are gladly offering our membership to artists that are unable to afford our already cheap options. If you’re an artist please reach out to us at support@clippsly.app and we’ll see what we can do!