HTML5 audio player drag and drop - javascript

I'm implementing audio player in html5, which has drag-drop option for load and play mp3 files, but I have problem with plaing the file.
When the file is dropped on the area, I can see in the console properties of object, but there is no information about absolute path, because of security in web browser.
Is there an option, how to play mp3 this way ?
index.html and body content:
<div style="border: 1px solid black; width: 200px; height: 50px; padding: 10px;"" id="cudl">add file here</div>
<div id="play" style="border: 1px solid black; width: 200px; height: 50px; padding: 10px;">PLAY</div>
<div id="pause" style="border: 1px solid black; width: 200px; height: 50px; padding: 10px;">PAUSE</div>
<div id="progress" style="width: 1000px; height: 50px; background: black; "><div id="time" style="width: 0%; height: 50px; background: green;"></div></div>
javascript:
window.onload = function () {
var cudl = document.getElementById("cudl");
cudl.addEventListener("dragover", function (ev) {
ev.preventDefault();
}, false);
cudl.addEventListener("drop", function (ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("audio/mpeg");
var allAudio = document.getElementsByTagName("audio");
if (allAudio.length > 0) {
for (var i = 0; i < allAudio.length; i++) document.body.removeChild(allAudio[i]);
}
var audio = document.createElement("audio");
audio.setAttribute("src", ev.dataTransfer.files[0].name);
document.body.appendChild(audio);
console.log("append file");
console.log(ev.dataTransfer.files[0]);
audio.addEventListener("durationchange", function () {
console.log("dc " + this.duration);
});
audio.addEventListener("timeupdate", function () {
//console.log("ct " + this.currentTime);
var prog = document.getElementById("time");
prog.style.width = Math.floor(this.currentTime / this.duration * 100) + "%";
});
var play = document.getElementById("play");
play.addEventListener("click", function () {
document.getElementsByTagName("audio")[0].play();
});
var pause = document.getElementById("pause");
pause.addEventListener("click", function () {
document.getElementsByTagName("audio")[0].pause();
});
}, false);
};

Instead of using the absolute path to use as an src-attribute on an audio element, I suggest you read the contents of the file(s) and use the webAudio API for decoding the audio data.
Here is a working example for playing the dropped file immediately. But you can just save the buffer for later playback.
var context = new AudioContext()
window.addEventListener('load', function() {
var dropzone = document.querySelector('#dropzone');
dropzone.addEventListener('drop', handleDrop, false)
dropzone.addEventListener('dragover', handleDragOver, false)
})
var handleDragOver = function(e) {
e.preventDefault()
e.stopPropagation()
}
var handleDrop = function(e) {
e.preventDefault()
e.stopPropagation()
var files = e.dataTransfer.files
for (var i = 0; i < files.length; i++) {
var file = files[i]
var reader = new FileReader()
reader.addEventListener('load', function(e) {
var data = e.target.result
context.decodeAudioData(data, function(buffer) {
playSound(buffer)
})
})
reader.readAsArrayBuffer(file)
}
}
var playSound = function(buffer) {
var source = context.createBufferSource()
source.buffer = buffer
source.connect(context.destination)
source.start(0)
}

You can disable the web security of the browser. In the terminal, cd to the application and type "--disable-web-security" without the quotes.

I think you are forgetting to load the audio before playing it. I always forget this when retrieving audio files to play.
document.getElementsByTagName("audio")[0].load();
document.getElementsByTagName("audio")[0].play();

Related

How to display uploaded image in CSS background URL property using input file API - vanilla Javascript

The initial project had an array with file names stored in there and the image slider would display them.
I am trying to create the upload functionality where the user can upload an image and that image would then be pushed to the array.
I've tried utilizing the URL.createObjectURL method on the uploaded file and pushing it to the display but there's an error when the slide arrives at the array index.
The file comes out as 'blob:http etc...' and so i've tried removing 'blob' from the string and still receiving an error.
HTML:
<div id="container">
<button class="button" id="leftButton"><i class="fa fa-arrow-left"></i></button>
<button class="button" id="rightButton"><i class="fa fa-arrow-right"></i></button>
</div>
<div class="upload">
<p><input type='file' name='image' id="input"></p>
</div>
CSS:
#container {
margin: 100px auto;
height: 500px;
width: 900px;
border: 7px solid #3e92cc;
border-radius: 10px;
background: url('images/one.jpg');
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
Javascript:
let container = document.getElementById("container");
let rightButton = document.getElementById("rightButton");
let leftButton = document.getElementById("leftButton");
let images = ["one.jpg", "two.jpg", "three.jpg", "four.jpg", "five.jpg"];
let imagesIndex = 0;
const inputElement = document.getElementById("input");
let newURL;
//Add background to slider
function addBackground() {
if (!images[imagesIndex].includes('http')) {
container.style.background = `url('images/${images[imagesIndex]}')`;
} else {
container.style.background = `url('${images[imageIndex]}')`;
}
container.style.backgroundPosition = "center";
container.style.backgroundRepeat = "no-repeat";
container.style.backgroundSize = "cover";
}
// upload files
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
const objectURL = window.URL.createObjectURL(fileList[0]);
//remove 'blob:';
newURL = objectURL.replace('blob:', '');
console.log(newURL);
images.push(newURL);
}
// Event listeners
inputElement.addEventListener("change", handleFiles, false);
rightButton.addEventListener("click", function () {
imagesIndex++;
if (imagesIndex >= images.length) {
imagesIndex = 0;
}
console.log(imagesIndex);
addBackground();
})
leftButton.addEventListener("click", function () {
imagesIndex--;
if (imagesIndex < 0) {
imagesIndex = images.length - 1;
}
console.log(imagesIndex);
addBackground();
})
Don't remove blob: it's required in the URL scheme
// upload files
function handleFiles() {
const fileList = this.files; /* now you can work with the file list */
const objectURL = window.URL.createObjectURL(fileList[0]);
//remove 'blob:';
//newURL = objectURL.replace('blob:', '');
console.log(objectURL);
images.push(objectURL);
}
Corrected typo in imagesIndex
//Add background to slider
function addBackground() {
if (!images[imagesIndex].includes('http')) {
container.style.background = `url('images/${images[imagesIndex]}')`;
} else {
container.style.background = `url('${images[imagesIndex]}')`;
}
//.. other code
}

Load multiple picture files with angularjs

I found this useful link which shows how to load picture from your local pc with a directive (newbie w/angular). But I don't know where to modify it to display also the selected images. How could I achieve this? I found that many examples like this that only lists the filenames.
I found this approach which loads the file and I adapted it to load multiple files. By this doesn't use angular.
window.onload = function() {
var fileInput = document.getElementById('fileInput');
var fileDisplayArea = document.getElementById('fileDisplayArea');
fileInput.addEventListener('change', function(e) {
var file = fileInput.files[0];
var imageType = /image.*/;
if (file.type.match(imageType)) {
var reader = new FileReader();
reader.onload = function(e) {
fileDisplayArea.innerHTML = "";
var img = new Image();
img.src = reader.result;
fileDisplayArea.appendChild(img);
}
reader.readAsDataURL(file);
} else {
fileDisplayArea.innerHTML = "File not supported!"
}
});
What would be a better approach. I want to load multiple files, display and finally upload them as byteArray.
The below code will allow selection of multiple files and display them on the webpage. For uploading them you can use Formdata Here is the link to use FormData . Also you can find several post explaining how to upload files using FormData you just have to ask Google.
window.onload = function(){
//Check File API support
if(window.File && window.FileList && window.FileReader)
{
var filesInput = document.getElementById("fileInput");
filesInput.addEventListener("change", function(event){
var files = event.target.files; //FileList object
var output = document.getElementById("fileDisplayArea");
output.innerHTML="";
for(var i = 0; i< files.length; i++)
{
var file = files[i];
//Only pics
if(!file.type.match('image'))
continue;
var picReader = new FileReader();
picReader.addEventListener("load",function(event){
var picFile = event.target;
var div = document.createElement("div");
div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
"title='" + picFile.name + "'/>";
output.insertBefore(div,null);
});
//Read the image
picReader.readAsDataURL(file);
}
});
}
else
{
console.log("Your browser does not support File API");
}
}
html {
font-family: Helvetica, Arial, sans-serif;
font-size: 100%;
background: #333;
}
#page-wrapper {
width: 600px;
background: #FFF;
padding: 1em;
margin: 1em auto;
min-height: 300px;
border-top: 5px solid #69c773;
box-shadow: 0 2px 10px rgba(0,0,0,0.8);
}
h1 {
margin-top: 0;
}
img {
max-width: 100%;
}
#fileDisplayArea {
margin-top: 2em;
width: 100%;
overflow-x: auto;
}
<div id="page-wrapper">
<h1>Image File Reader</h1>
<div>
Select an image file:
<input type="file" id="fileInput" multiple>
</div>
<div id="fileDisplayArea"></div>
</div>

Google drag and drop not working

I am trying to implement drag and drop div, like this. Unfortunately, it doesn't work for me, when I try to drag to this div, a new tab with the selected file opens.
Here is my code
<div id="dropzone" style="height:200px; border: 4px double black;" ></div>
<script>
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
var dropzone = document.getElementById('dropzone');
dropzone.ondrop = function(e) {
var length = e.dataTransfer.items.length;
for (var i = 0; i < length; i++) {
var entry = e.dataTransfer.items[i].webkitGetAsEntry();
if (entry.isFile) {
// do whatever you want
} else if (entry.isDirectory) {
// do whatever you want
}
}
};
</script>
How can I make it work?
var dropbox;
dropbox = document.getElementById("dropbox");
dropbox.addEventListener("dragenter", dragenter, false);
dropbox.addEventListener("dragover", dragover, false);
dropbox.addEventListener("drop", drop, false);
function dragenter(e) {
e.stopPropagation();
e.preventDefault();
}
function dragover(e) {
e.stopPropagation();
e.preventDefault();
}
function drop(e) {
e.stopPropagation();
e.preventDefault();
var dt = e.dataTransfer;
var files = dt.files;
handleFiles(files);
}
#dropbox
{
height: 100px;
border: 4px double black;
background-color: lightgray;
font: 5em bold monospace;
text-align: center;
}
<div id="dropbox">
Drag files here!
</div>
The Google link is outdated, but this allows the file system to work in a very similar fashion. An example of this is above.

why is file drag and drop disabling draggable elements?

Hello stack overflow community!
I am writing a script to make simple drag and drop able document maker. i wrote all my current code by myself, but i had no clue how to enable dragging of desktop files to the document. here is the code i have written so far(sorry for the messedup indenting, the codeblock feature messed it up):
<html>
<head>
<style>
#main { position:absolute; top:10px; left:50%; margin-left:-450px; width:900px; height:900px; border:dashed 1px lightgrey; }
#trash { margin-top:10px; width:200px; height:200px; border:dotted 4px black; position:absolute; top:0px; left:5px; }
#new { width:200px; height:200px; border:dotted 5px black; }
.new { float:right; }
.drag { float:left; resize:both; overflow:hidden; height:110px; width:110px; }
.square { background-color:none; width:10px; height:10px; float:left; }
.drag * { resize:none; width:100px; height:100px }
.block { background-color:red; }
</style>
<script src="jq/jquery-1.9.1.js"></script>
<script src="jq/jquery-ui.js"></script>
<script>
var blockcolors = ["red","blue","green","yellow","white","black","lightgrey","lightblue"];
var color = 1;
var id = 2;
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
ev.target.appendChild(document.getElementById(ev.dataTransfer.getData("Text")));
}
function droptrash(ev)
{
ev.preventDefault();
$("#"+ev.dataTransfer.getData("Text")).remove();
}
function change(div)
{
var divw=parseInt(div.style.width);
var divh=parseInt(div.style.height);
var imgw=divw-10;
var imgh=divh-10;
div.children[0].style.width=imgw;
div.children[0].style.height=imgh;
div.style.border="dotted 3px grey";
}
function makeGrid()
{
var main = $("#main");
for (var i = 0; i < 8100; i++)
{
var square = document.createElement('div');
square.setAttribute('class', 'square');
square.ondragover = function(event) { event.preventDefault(); };
square.ondrop = function(event) { drop(event); };
main.prepend(square);
}
}
function additem() {
var newbox = document.getElementById("new");
newbox.innerHTML = '<div id="div'+id+'" class="drag" onmouseout="this.style.border=0" draggable="true" ' +
'ondragstart="drag(event)" onmousemove="change(this)"></div>';
div = document.getElementById("div"+id);
div.innerHTML = $("#newtype").val();
id+=1;
}
function blockcolor(block) {
block.style.backgroundColor = blockcolors[color];
if (color == blockcolors.length-1)
color = 0;
color++;
}
</script>
</head>
<body onload="makeGrid()" class="new">
<div id="new" class="new"></div>
<div style="clear:both"></div>
<select id="newtype" class="new">
<option value="<img draggable='false' src='glider.jpg'/>">Image</option>
<option value="<textarea></textarea>">Text box</option>
<option value="<div onclick='blockcolor(this)' class='block'></div>">Block</option>
</select>
<button onclick="additem()" class="new">add an item</button>
<div style="clear:both"></div>
<center>
<div style="clear:both"></div>
<div ID="main" overflow="auto">
</div>
</center>
<div style="clear:both"></div>
<div id="trash" ondragover="event.preventDefault()" ondrop="droptrash(event)" overflow="auto"><big>Trash</big></div>
</body>
</html>
this works, but it has no functionality for dragging in files. i wanted to add this code i found online which works by itself:
<html>
<head>
<style>
#drop { min-height: 150px; width: 250px; border: 1px solid blue; margin: 10px; padding: 10px; }
</style>
<script>
if(window.FileReader) {
var drop;
addEventHandler(window, 'load', function() {
drop = document.getElementById('drop');
var list = document.getElementById('list');
function cancel(e) {
if (e.preventDefault) { e.preventDefault(); }
return false;
}
// Tells the browser that we *can* drop on this target
addEventHandler(drop, 'dragover', cancel);
addEventHandler(drop, 'dragenter', cancel);
addEventHandler(drop, 'drop', function (e) {
e = e || window.event; // get window.event if e argument missing (in IE)
if (e.preventDefault) { e.preventDefault(); } // stops the browser from redirecting off to the image.
var dt = e.dataTransfer;
var files = dt.files;
for (var i=0; i<files.length; i++) {
var file = files[i];
var reader = new FileReader();
//attach event handlers here...
reader.readAsDataURL(file);
addEventHandler(reader, 'loadend', function(e, file) {
var bin = this.result;
var img = document.createElement("img");
img.file = file;
img.src = bin;
drop.innerHTML = "";
drop.appendChild(img);
}.bindToEventHandler(file));
}
return false;
});
Function.prototype.bindToEventHandler = function bindToEventHandler() {
var handler = this;
var boundParameters = Array.prototype.slice.call(arguments);
//create closure
return function(e) {
e = e || window.event; // get window.event if e argument missing (in IE)
boundParameters.unshift(e);
handler.apply(this, boundParameters);
}
};
});
} else {
document.getElementById('status').innerHTML = 'Your browser does not support the HTML5 FileReader.';
}
function addEventHandler(obj, evt, handler) {
if(obj.addEventListener) {
// W3C method
obj.addEventListener(evt, handler, false);
} else if(obj.attachEvent) {
// IE method.
obj.attachEvent('on'+evt, handler);
} else {
// Old school method.
obj['on'+evt] = handler;
}
}
</script>
</head>
<body>
<DIV id="drop"></DIV>
<DIV id="list"></DIV>
</body>
</html>
my problem is combining them. the second script messes up all drag and drop functionality for the whole thing. i would much appreciate any help.
there is some minor change in the file drop script. Just rename the variable "drop" to "dropElement"( or any other name then "drop"), as it was conflicting with the function name "drop" in first script. so here is your second script.
<script>
if(window.FileReader) {
var dropElement;
addEventHandler(window, 'load', function() {
dropElement = document.getElementById('drop');
var list = document.getElementById('list');
function cancel(e) {
if (e.preventDefault) { e.preventDefault(); }
return false;
}
// Tells the browser that we *can* drop on this target
addEventHandler(dropElement, 'dragover', cancel);
addEventHandler(dropElement, 'dragenter', cancel);
addEventHandler(dropElement, 'drop', function (e) {
e = e || window.event; // get window.event if e argument missing (in IE)
if (e.preventDefault) { e.preventDefault(); } // stops the browser from redirecting off to the image.
var dt = e.dataTransfer;
var files = dt.files;
for (var i=0; i<files.length; i++) {
var file = files[i];
var reader = new FileReader();
//attach event handlers here...
reader.readAsDataURL(file);
addEventHandler(reader, 'loadend', function(e, file) {
var bin = this.result;
var img = document.createElement("img");
img.file = file;
img.src = bin;
dropElement.innerHTML = "";
dropElement.appendChild(img);
}.bindToEventHandler(file));
}
return false;
});
Function.prototype.bindToEventHandler = function bindToEventHandler() {
var handler = this;
var boundParameters = Array.prototype.slice.call(arguments);
//create closure
return function(e) {
e = e || window.event; // get window.event if e argument missing (in IE)
boundParameters.unshift(e);
handler.apply(this, boundParameters);
}
};
});
} else {
document.getElementById('status').innerHTML = 'Your browser does not support the HTML5 FileReader.';
}
function addEventHandler(obj, evt, handler) {
if(obj.addEventListener) {
// W3C method
obj.addEventListener(evt, handler, false);
} else if(obj.attachEvent) {
// IE method.
obj.attachEvent('on'+evt, handler);
} else {
// Old school method.
obj['on'+evt] = handler;
}
}
</script>

How to play only the audio of a Youtube video using HTML 5?

Is it possible to play only the audio from a YouTube video using HTML 5 and Javascript?
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.
UPDATED FOR 2020
It seems in Septeber 2019, YouTube updated the values that are returned by get_video_info.
Rather than data.url_encoded_fmt_stream_map and data.adaptive_fmts (as used in the other older examples) now we are looking for for data.formats and data.adaptiveFormats.
Anyways here is what you are all here for some code that loads a YouTube video into an <audio> element. Try it on CodePen
// YouTube video ID
var videoID = "CMNry4PE93Y";
// Fetch video info (using a proxy to avoid CORS errors)
fetch('https://cors-anywhere.herokuapp.com/' + "https://www.youtube.com/get_video_info?video_id=" + videoID).then(response => {
if (response.ok) {
response.text().then(ytData => {
// parse response to find audio info
var ytData = parse_str(ytData);
var getAdaptiveFormats = JSON.parse(ytData.player_response).streamingData.adaptiveFormats;
var findAudioInfo = getAdaptiveFormats.findIndex(obj => obj.audioQuality);
// get the URL for the audio file
var audioURL = getAdaptiveFormats[findAudioInfo].url;
// update the <audio> element src
var youtubeAudio = document.getElementById('youtube');
youtubeAudio.src = audioURL;
});
}
});
function parse_str(str) {
return str.split('&').reduce(function(params, param) {
var paramSplit = param.split('=').map(function(value) {
return decodeURIComponent(value.replace('+', ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
<audio id="youtube" controls></audio>
This may be an old post but people could still be searching for this so here you go:
<div style="position:relative;width:267px;height:25px;overflow:hidden;">
<div style="position:absolute;top:-276px;left:-5px">
<iframe width="300" height="300"
src="https://www.youtube.com/embed/youtubeID?rel=0">
</iframe>
</div>
</div>
You can make a fake audio player to toggle the Youtube iframe through Youtube Iframe API,
and also use the API to get informations that you want to display on your audio player.
Here is my example.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="player.css">
<script src="https://www.youtube.com/iframe_api"></script>
<script src="player.js"></script>
<script>
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '360',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
</script>
</head>
<body>
<!--Youtube-->
<div id="player" style="display: none; visibility: hidden;"></div>
<!--Player-->
<div class="audio-player">
<div class="player-controls">
<div id="radioIcon"></div>
<button id="playAudio"></button>
<div id="seekObjContainer">
<div id="seekObj">
<div id="percentage"></div>
</div>
</div>
<p><small id="currentTime">00:00</small></p>
</div>
</div>
</body>
</html>
player.js
var player;
function onPlayerReady(event) {
document.getElementById(ui.play).addEventListener('click', togglePlay);
timeupdater = setInterval(initProgressBar, 100);
}
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.ENDED) {
document.getElementById(ui.play).classList.remove('pause');
document.getElementById(ui.percentage).style.width = 0;
document.getElementById(ui.currentTime).innerHTML = '00:00';
player.seekTo(0, true);
}
}
let ui = {
play: 'playAudio',
audio: 'audio',
percentage: 'percentage',
seekObj: 'seekObj',
currentTime: 'currentTime'
};
function togglePlay() {
if (player.getPlayerState() === 1) {
player.pauseVideo();
document.getElementById(ui.play).classList.remove('pause');
} else {
player.playVideo();
document.getElementById(ui.play).classList.add('pause');
}
}
function calculatePercentPlayed() {
let percentage = (player.getCurrentTime() / player.getDuration()).toFixed(2) * 100;
document.getElementById(ui.percentage).style.width = `${percentage}%`;
}
function calculateCurrentValue(currentTime) {
const currentMinute = parseInt(currentTime / 60) % 60;
const currentSecondsLong = currentTime % 60;
const currentSeconds = currentSecondsLong.toFixed();
const currentTimeFormatted = `${currentMinute < 10 ? `0${currentMinute}` : currentMinute}:${
currentSeconds < 10 ? `0${currentSeconds}` : currentSeconds
}`;
return currentTimeFormatted;
}
function initProgressBar() {
const currentTime = calculateCurrentValue(player.getCurrentTime());
document.getElementById(ui.currentTime).innerHTML = currentTime;
document.getElementById(ui.seekObj).addEventListener('click', seek);
function seek(e) {
const percent = e.offsetX / this.offsetWidth;
player.seekTo(percent * player.getDuration());
}
calculatePercentPlayed();
}
player.css
* {
box-sizing: border-box;
}
body {
background-size: 6px 6px !important;
background-image: linear-gradient(-45deg, rgba(0, 0, 0, 0) 46%, coral 49%, coral 51%, rgba(0, 0, 0, 0) 55%);
background-color: white;
padding-top: 60px;
}
.audio-player {
width: 470px;
padding: 35px 20px;
margin: auto;
background-color: white;
border: 1px solid black;
}
.audio-player .player-controls {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
}
.audio-player #radioIcon {
width: 30px;
height: 30px;
background: url("https://img.icons8.com/ios/50/000000/microphone.png") no-repeat center;
background-size: contain;
}
.audio-player #playAudio {
-webkit-appearance: none;
outline: none;
cursor: pointer;
border: none;
width: 30px;
height: 30px;
background: url("https://img.icons8.com/play") no-repeat center;
background-size: contain;
}
.audio-player #playAudio.pause {
background: url("https://img.icons8.com/pause") no-repeat center;
background-size: contain;
}
.audio-player p {
margin: 0 0 0 5px;
line-height: 1;
display: inline-flex;
}
.audio-player p small {
font-size: 10px;
}
.audio-player #seekObjContainer {
position: relative;
width: 300px;
margin: 0 5px;
height: 5px;
}
.audio-player #seekObjContainer #seekObj {
position: relative;
width: 100%;
height: 100%;
background-color: #e3e3e3;
border: 1px solid black;
}
.audio-player #seekObjContainer #seekObj #percentage {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: coral;
}
The audio player came from here.
Hope this could help you guys!!
VIDEO_ID with actual ID of your YouTube video.
<div data-video="VIDEO_ID"
data-autoplay="0"
data-loop="1"
id="youtube-audio">
</div>
<script src="https://www.youtube.com/iframe_api"></script>
<script src="https://cdn.rawgit.com/labnol/files/master/yt.js"></script>
The answer is simple:
Use a 3rd party product like jwplayer or similar,
then set it to the minimal player size which is the audio player size (only shows player controls).
Voila.
Been using this for over 8 years.
I agree with Tom van der Woerdt. You could use CSS to hide the video (visibility:hidden or overflow:hidden in a div wrapper constrained by height), but that may violate Youtube's policies. Additionally, how could you control the audio (pause, stop, volume, etc.)?
You could instead turn to resources such as http://www.houndbite.com/ to manage audio.
Adding to the mentions of jwplayer and possible TOS violations, I would like to to link to the following repository on github: YouTube Audio Player Generation Library, that allows to generate the following output:
Library has the support for the playlists and PHP autorendering given the video URL and the configuration options.
var vid = "bpt84ceWAY0",
audio_streams = {},
audio_tag = document.getElementById('youtube');
fetch("https://"+vid+"-focus-opensocial.googleusercontent.com/gadgets/proxy?container=none&url=https%3A%2F%2Fwww.youtube.com%2Fget_video_info%3Fvideo_id%3D" + vid).then(response => {
if (response.ok) {
response.text().then(data => {
var data = parse_str(data),
streams = (data.url_encoded_fmt_stream_map + ',' + data.adaptive_fmts).split(',');
streams.forEach(function(s, n) {
var stream = parse_str(s),
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;
}
if (quality) audio_streams[quality] = stream.url;
});
console.log(audio_streams);
audio_tag.src = audio_streams['128kbps'];
audio_tag.play();
})
}
});
function parse_str(str) {
return str.split('&').reduce(function(params, param) {
var paramSplit = param.split('=').map(function(value) {
return decodeURIComponent(value.replace('+', ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
<audio id="youtube" autoplay controls loop></audio>
As an alternative answer, you can set the video's brightness to zero and the video area will go all black while the controls remain visible...
Via CSS...
filter: brightness(0%);
Via JS...
V.style.filter='brightness(0%)';
NB: Normal default value for brightness is 100%.
// YouTube video ID
var videoID = "CMNry4PE93Y";
// Fetch video info (using a proxy to avoid CORS errors)
fetch('https://cors-anywhere.herokuapp.com/' + "https://www.youtube.com/get_video_info?video_id=" + videoID).then(response => {
if (response.ok) {
response.text().then(ytData => {
// parse response to find audio info
var ytData = parse_str(ytData);
var getAdaptiveFormats = JSON.parse(ytData.player_response).streamingData.adaptiveFormats;
var findAudioInfo = getAdaptiveFormats.findIndex(obj => obj.audioQuality);
// get the URL for the audio file
var audioURL = getAdaptiveFormats[findAudioInfo].url;
// update the <audio> element src
var youtubeAudio = document.getElementById('youtube');
youtubeAudio.src = audioURL;
});
}
});
function parse_str(str) {
return str.split('&').reduce(function(params, param) {
var paramSplit = param.split('=').map(function(value) {
return decodeURIComponent(value.replace('+', ' '));
});
params[paramSplit[0]] = paramSplit[1];
return params;
}, {});
}
<audio id="youtube" controls></audio>

Categories

Resources