I have 2 web apps that present audio using the <audio>
HTML tag. I cannot figure out why one app will play the MP3 file and the other will not. I did get this message from Firefox, buried in some others from a Google doc:
All candidate resources failed to load. Media load paused.
Ok... why?
Note: Yes, there are similar questions asked. I read them already. Most of them are also 5-10 years old.
Doesn't work on Firefox:
<audio controls>
<source src="/media/my_audio.mp3" />
</audio>
Works fine on Firefox:
<audio controls="">
<source src="/media/other_audio.mp3">
</audio>
...and also in Chrome:
Other site is working as expected in Firefox:
Things I tried:
crossorigin
to the <audio>
tag, adding permissive Access-Control-Allow-<stuff>: *
headers via the .htaccess
file. I even moved the audio file to the same domain. Nothing.<audio>
tag and the rest of that page are created in JS and then added to the page container (no framework, just me). Again, doesn't make sense why that would be an issue, but maybe?Content-Type: "audio/mpeg"
header to .htaccess
where the audio is served, but that also didn't help. Tried adding the MIME type to the source tag in HTML, too.First 40 bytes of the MP3:
FF FB 90 44 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 58 69 6E 67
Supposedly FF FB
are magic numbers for MP3 (without ID3v2 metadata). However, I did try a few other MP3s with the page, and none worked. At least one of the others did start with the 3 bytes ID3
.
More complete HTML looks like this:
Everything inside #content
is being created in JS using document.createElement('template')
and then setting innerHTML
. The audio URL is inserted via $interview.audio_path
. The iframe
shows a Google document for editing. This whole #interview-editor
element is then added to #content
's children.
<body>
<div id="nav-bar">
...
</div>
<div id="content">
<div id="interview-editor" class="right-sidebar">
<div id="interview-audio">
<a data-action="replay_30" class="btn-large">30</a>
<a data-action="replay_10" class="btn-large">10</a>
<a data-action="replay_5" class="btn-large">5</a>
<audio id="audio-control" controls src="${interview.audio_path}"></audio>
<!-- above is what i did originally, then tried this variation as well
<audio id="audio-control" controls>
<source src="${interview.audio_path}">
</audio> -->
<a data-action="forward_5" class="btn-large">5</a>
<a data-action="forward_10" class="btn-large">10</a>
<a data-action="forward_30" class="btn-large">30</a>
</div>
<div id="interview-transcript">
<iframe src="${interview.text_path}" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
</div>
</div>
</div>
</body>
There is some JS hooked up to the 6 a.btn-large
elements to jump backward and forward in the audio:
function onButtonClick(btn) {
// action can be close or one of the audio skip buttons
const action = btn.dataset.action;
if (action.startsWith("replay") || action.startsWith("forward")) {
let [direction, amount] = action.split("_");
amount = Number(amount);
if (direction === "replay") amount *= -1
console.log(`audio seek: ${amount}`);
const audioControl = document.getElementById("audio-control");
audioControl.currentTime += amount;
} else {
console.error(`error: unknown action ${action}`);
}
}
I was able to make my page work with Firefox by delaying setting <audio>
's src
attribute until after the new node (#interview-editor
) was actually inserted into the page's DOM.
I did not have to take this step on Chrome, Edge, or Safari.