How to play only the audio of a Youtube video using HTML 5?
UPDATE 2022
webm formats added for demo. You can always check for console log and add all formats needed.
UPDATE 2021
You can parse Youtube HTML page for all streams available for this particular video and extract audio only streams.
Here is an example with public Google Image proxy (but you can use any free or your own CORS
proxy):
var vid = "3r_Z5AYJJd4",
audio_streams = {},
audio_tag = document.getElementById('youtube');
fetch("https://images" + ~~(Math.random() * 33) + "-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=" + encodeURIComponent("https://www.youtube.com/watch?hl=en&v=" + vid)).then(response => {
if (response.ok) {
response.text().then(data => {
var regex = /(?:ytplayer\.config\s*=\s*|ytInitialPlayerResponse\s?=\s?)(.+?)(?:;var|;\(function|\)?;\s*if|;\s*if|;\s*ytplayer\.|;\s*<\/script)/gmsu;
data = data.split('window.getPageData')[0];
data = data.replace('ytInitialPlayerResponse = null', '');
data = data.replace('ytInitialPlayerResponse=window.ytInitialPlayerResponse', '');
data = data.replace('ytplayer.config={args:{raw_player_response:ytInitialPlayerResponse}};', '');
var matches = regex.exec(data);
var data = matches && matches.length > 1 ? JSON.parse(matches[1]) : false;
console.log(data);
var streams = [],
result = {};
if (data.streamingData) {
if (data.streamingData.adaptiveFormats) {
streams = streams.concat(data.streamingData.adaptiveFormats);
}
if (data.streamingData.formats) {
streams = streams.concat(data.streamingData.formats);
}
} else {
return false;
}
streams.forEach(function(stream, n) {
var itag = stream.itag * 1,
quality = false;
console.log(stream);
switch (itag) {
case 139:
quality = "48kbps";
break;
case 140:
quality = "128kbps";
break;
case 141:
quality = "256kbps";
break;
case 249:
quality = "webm_l";
break;
case 250:
quality = "webm_m";
break;
case 251:
quality = "webm_h";
break;
}
if (quality) audio_streams[quality] = stream.url;
});
console.log(audio_streams);
audio_tag.src = audio_streams['256kbps'] || audio_streams['128kbps'] || audio_streams['48kbps'];
audio_tag.play();
})
}
});
<audio id="youtube" autoplay controls loop></audio>
Doesn't work for all videos, very depends on monetization settings or something like that.
Embed the video player and use CSS to hide the video. If you do it properly you may even be able to hide only the video and not the controls below it.
However, I'd recommend against it, because it will be a violation of YouTube TOS. Use your own server instead if you really want to play only audio.