How to play audio files from Sanity using the file type in a blog component?

4 replies
Last updated: Nov 29, 2025
Hi everyone. I've been stuck on something for a few days now, and after looking online and trying different things, I still can't figure it out. I haven't been using Sanity that long and have not yet had to do this, so I don't know what I'm doing wrong.
So I'm building like a blog site that displays cards with student names, bios, an image, etc. Each card also has a button that when clicked, should play a short audio clip from an
.mp3 file. I am able to see all of the information displayed in the browser when the information is entered in Sanity (the text for the name bio, the image file, etc.). However, I am not able to hear the audio when I click the button to hear the audio. When I click the button, I get the error in the console (see screenshot). As I understand from the documentation , the
file
type is used for all other file types such as documents and audio files. Going by this information, I added to my "student" schema (lines 17-19 in my screenshot). Then, in my component, I added audio to my query (see "query" screenshot", line 10). Finally, down below in the component, I added a click event for the audio (see "button" screenshot, lines 4-7), using
student.audio
in order to get the .mp3 audio from Sanity. Up above, I used
student.name
to get the name,
student.image
to get the image, etc., and they all worked. The audio is the only thing I am having problems with.
However, I noticed that when I use a URL instead of
student.audio
it works, though I need it to work when an .mp3 file is added into Sanity, and not a URL:
let audio = new Audio('<https://assets.coderrocketfuel.com/pomodoro-times-up.mp3>');
However, it does not work when I use
student.audio
and this is when I get the error in the console. I don't know what I am doing wrong and how I can make it work so that the .mp3 audio plays. Any thoughts or ideas? Maybe my schema or query or both are incorrect? Any ideas would help. And by the way, there is nothing wrong with the .mp3 files I'm using (they all work), so it's not that. Thank you so much!
AI Update

I can see your issue! When you query a file field from Sanity, you're getting a file object/reference, not the actual URL string. That's why student.audio doesn't work directly with the Audio() constructor, but a direct URL does.

The file field in Sanity returns an object that contains metadata about the file, including a reference to the asset. To get the actual playable URL, you need to resolve that asset reference in your GROQ query.

Here's what you need to change:

In your GROQ query, instead of just querying audio, you need to get the URL from the asset:

*[_type == "student"] {
  name,
  bio,
  image,
  "audioUrl": audio.asset->url
}

The key part is "audioUrl": audio.asset->url - this follows the reference (->) to the actual asset and retrieves its URL.

In your component, you'd then use:

const playAudio = () => {
  let audio = new Audio(student.audioUrl);
  audio.play();
}

The reason your other fields work is that for images, you're probably using Sanity's image URL builder or a similar helper that automatically resolves the asset reference. For the file type with audio, you need to explicitly get the URL in your query.

As mentioned in the Sanity documentation on file types, the file field stores a reference to an asset, and you need to query asset->url to get the actual URL string you can use in your JavaScript.

Your schema looks correct (using type: 'file' for the audio field), so it's just the query that needs the adjustment!

Show original thread
4 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?