I am trying to make an audio player, how do I get the selected file to be playable?


Joined
Dec 14, 2021
Messages
26
Reaction score
1
I have this audio player I am working on and well I can't get it to work, since the audio tag needs to have the full file path to play the audio file, so I need a way to play the audio file, regardless of the location of the audio file, so how would I do it?

Here is the code:
JavaScript:
function getHHMMSSFromSeconds(totalSeconds) {
    if (!totalSeconds) {
      return '00:00:00';
    }
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor(totalSeconds % 3600 / 60);
    const seconds = totalSeconds % 60;
    const hhmmss = padTo2(hours) + ':' + padTo2(minutes) + ':' + padTo2(seconds);
    return hhmmss;
}

var trackHold = document.getElementById("allTracks");

var trackFile = document.getElementById("trackFile");

var trackAddModal = document.getElementById("trackAddModal");
var addTrck = document.getElementById("addTrck");
var span = document.getElementsByClassName("close")[0];
addTrck.onclick = function() {
    trackAddModal.style.display = "block";
}
span.onclick = function() {
    trackAddModal.style.display = "none";
}
window.onclick = function(event) {
    if (event.target == trackAddModal) {
        trackAddModal.style.display = "none";
    }
}

var trackNum = 0;
document.getElementById("trackNum").innerHTML = trackNum;

function addTrack(tkName, tkLength) {
    var file = trackFile.files[0];
    var trackSource = file.name;
    if (tkName == null) {
        tkName = trackSource;
    }
    var trackName = tkName;
    var audio = document.createElement('audio');
    audio.src = trackFile.value;
    
    if (tkLength == null) {
        tkLength = getHHMMSSFromSeconds(parseInt(audio.duration));
    }
    var trackLth = tkLength;
    
    trackHold.innerHTML += "<div class='track'><button class='playTrack'>Play</button> | <button class='removeTrack'>Remove</button><audio controls><source src="+"'"+trackSource+"'"+">Your browser does not support the audio element.</audio><br><br><div class='ttrrds'><p class='trackName'>Name of Track: "+trackName+"</p><br><p class='trackLength'>"+trackLth+"</p></div><p>Track Number: <span style='font-weight:bold;'>"+trackNum+"</span></p></div><br>";
    trackNum += 1;
    document.getElementById("trackNum").innerHTML = trackNum;
}

Here is the HTML:
HTML:
| <button id="addTrck">Add Track</button> |
<p style="display:inline;">Number of Tracks: <span id="trackNum"></span></p>
<hr>
<div class="marg" id="allTracks"></div>
<br>
<div id="trackAddModal" class="modal">
    <div class="modal-content">
        <div class="modal-header">
            <span class="close">&times;</span>
            <h2>Add a Track</h2>
        </div>
        <div class="modal-body marg">
            <label for="trackFile">Select a file: (Only Audio Files)</label>
            <input type="file" id="trackFile" name="trackFile" accept="audio/*">
            <br><br>
            <button onclick="addTrack()">Submit</button>
        </div>
    </div>
</div>
 
Ad

Advertisements

Joined
Mar 11, 2022
Messages
181
Reaction score
24
First of all- You can't read from a temp file (input.value). Your file needs to be
A.) Uploaded

or

B.) converted to a readable (playable) base64 String. FileReader should be your choice.

Google for filereader and your good to go.

Next thing i would change is

Code:
<input type="file" id="trackFile" name="trackFile" onchange="addTrack(this)" accept="audio/*">
<script>
function addTrack(trackFile) {
    var file = trackFile.files[0];
//and so on
}
</script>

and skip that
"<button onclick="addTrack()">Submit</button>"

What should that be "addTrack(tkName, tkLength)" ? Give an existing argument if the function isn't called by an event. Otherwise it's BS.
 
Joined
Dec 14, 2021
Messages
26
Reaction score
1
First of all- You can't read from a temp file (input.value). Your file needs to be
A.) Uploaded

or

B.) converted to a readable (playable) base64 String. FileReader should be your choice.

Google for filereader and your good to go.

Next thing i would change is

Code:
<input type="file" id="trackFile" name="trackFile" onchange="addTrack(this)" accept="audio/*">
<script>
function addTrack(trackFile) {
    var file = trackFile.files[0];
//and so on
}
</script>

and skip that
"<button onclick="addTrack()">Submit</button>"

What should that be "addTrack(tkName, tkLength)" ? Give an existing argument if the function isn't called by an event. Otherwise it's BS.
So how would I go about making this work, as I tried what you suggested and it didn't work? After all, I don't know much about this stuff, so I know I must be doing something wrong.
All I did was change it to the why you said, basically just changed the var file = trackFile.files[0]; to var file = tkFile.files[0]; and I added theonchange="addTrack(this)" to the input, it didn't work, so is there anything else I have to add and/or remove to make it work?
 
Joined
Mar 11, 2022
Messages
181
Reaction score
24
Of course this ain't work unless you do what i wrote. The changes about onchange instead of onclick are only a way for improvement.
Have you looked up for FileReader? Because that's the key.

Easy Example. Copy and try on your site
Code:
<script>
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new window.AudioContext();
var source;
function playAudio(ab) {
    context.decodeAudioData(ab, function (buffer) {
        src = context.createBufferSource();
        src.connect(context.destination);
        src.buffer = buffer;
        src.start(0);
    });
}

function playThis(inp) {
    var files = inp.files;  addAudio(files[0]);
}

function addAudio(file) {
    var fr = new FileReader();

    fr.onload = function (e) {
        console.log(e.target.result);
        playAudio(e.target.result);
    };
    fr.readAsArrayBuffer(file);
}
</script>
<input type="file" accept="audio/*" onchange="playThis(this);" />
 
Joined
Dec 14, 2021
Messages
26
Reaction score
1
Of course this ain't work unless you do what i wrote. The changes about onchange instead of onclick are only a way for improvement.
Have you looked up for FileReader? Because that's the key.
I have looked it up and I have gotten it to work the way that I want it to. However, I can't seem to be able to get the duration of the audio file.

Here is the updated code:

JavaScript:
function getHHMMSSFromSeconds(totalSeconds) {
    if (!totalSeconds) {
      return '00:00:00';
    }
    const hours = Math.floor(totalSeconds / 3600);
    const minutes = Math.floor(totalSeconds % 3600 / 60);
    const seconds = totalSeconds % 60;
    const hhmmss = padTo2(hours) + ':' + padTo2(minutes) + ':' + padTo2(seconds);
    return hhmmss;
}

function padTo2(value) {
    if (!value) {
      return '00';
    }
    return value < 10 ? String(value).padStart(2, '0') : value;
}

var trackHold = document.getElementById("allTracks");

var trackFile = document.getElementById("trackFile");

var track = document.querySelectorAll(".track");
var ttrrds = document.querySelectorAll(".ttrrds");

var trackNum = 0;
document.getElementById("trackNum").innerHTML = trackNum;

function addTrack(tkFile) {
    var trackSource;
    var trackLth;
    var trackName = tkFile.files[0].name;
    window.AudioContext = window.AudioContext || window.webkitAudioContext;
    var context = new window.AudioContext();
    var source;
    function playAudio(ab) {
        context.decodeAudioData(ab, function (buffer) {
            src = context.createBufferSource();
            src.connect(context.destination);
            src.buffer = buffer;
            trackLth = getHHMMSSFromSeconds(parseInt(buffer.duration)); // For geting duration of audio file, also changes from seconds into hhmmss format
        });
    }
    function playThis(inp) {
        var files = inp.files;  addAudio(files[0]);
        trackSource = URL.createObjectURL(files[0]);
    }
    function addAudio(file) {
        var fr = new FileReader();
        fr.onload = function (e) {
            playAudio(e.target.result);
        };
        fr.onerror = function (e) {
            console.error("An error ocurred reading the file: ", e);
        };
        fr.readAsArrayBuffer(file);
    }
    playThis(tkFile);
    
    const div = document.createElement("div");
    div.className = "track";
    
    const audio = document.createElement("audio");
    audio.controls = true;
    audio.src = trackSource;
    audio.innerHTML = "Your browser does not support the audio element.";
    div.appendChild(audio);
    
    const button = document.createElement("button");
    button.className = "playTrack";
    button.innerHTML = "Play";
    button.onclick = function() {
        if (button.innerHTML == "Play") {
            audio.play();
            button.innerHTML = "Pause";
            audio.onended = function() {
                button.innerHTML = "Play";
            }
        } else if (button.innerHTML == "Pause") {
            audio.pause();
            button.innerHTML = "Play";
        }
    }
    div.appendChild(button);
    
    const span2 = document.createElement("span");
    span2.innerHTML = " | ";
    div.appendChild(span2);
    
    const button2 = document.createElement("button");
    button2.className = "loopTrack";
    button2.innerHTML = "Loop";
    button2.onclick = function() {
        if (button2.innerHTML == "Loop") {
            audio.loop = true;
            button2.innerHTML = "Unloop";
            audio.onended = function() {
                button.innerHTML = "Pause";
            }
        } else if (button2.innerHTML == "Unloop") {
            audio.loop = false;
            button2.innerHTML = "Loop";
        }
    }
    div.appendChild(button2);
    
    const span3 = document.createElement("span");
    span3.innerHTML = " | ";
    div.appendChild(span3);
    
    const button3 = document.createElement("button");
    button3.className = "removeTrack";
    button3.innerHTML = "Remove";
    button3.onclick = function() {
        var remTrack = document.querySelectorAll(".removeTrack");
        div.remove();
        trackNum -= 1;
        document.getElementById("trackNum").innerHTML = trackNum;
    }
    div.appendChild(button3);
    
    
    
    const br = document.createElement("br");
    div.appendChild(br);
    
    const br2 = document.createElement("br");
    div.appendChild(br2);
    
    const div2 = document.createElement("div");
    div2.className = "ttrrds";
    div.appendChild(div2);
    
    const para = document.createElement("p");
    para.className = "trackName";
    para.innerHTML = "Name of Track: " + trackName;
    div2.appendChild(para);
    
    const br3 = document.createElement("br");
    div2.appendChild(br3);
    
    const para2 = document.createElement("p"); //to state the duration of audio file
    para2.className = "trackLength";
    para2.innerHTML = trackLth;
    div2.appendChild(para2);
    
    const para3 = document.createElement("p");
    para3.innerHTML = "Track Number: ";
    div.appendChild(para3);
    
    const span4 = document.createElement("span");
    span4.style.fontWeight = "bold";
    span4.innerHTML = trackNum;
    para3.appendChild(span4);
    
    trackHold.appendChild(div);
    
    const br4 = document.createElement("br");
    trackHold.appendChild(br4);
    
    trackNum += 1;
    document.getElementById("trackNum").innerHTML = trackNum;
}

I only added onchange="addTrack(this)" to the input field:

As I said, I can't seem to get the duration of the audio file, I tried everything I could come up with, well, none of them worked. So what should I do to fix it?
 
Ad

Advertisements

Joined
Mar 11, 2022
Messages
181
Reaction score
24
Filereader comes with more than just one thing.

You also still may use an HTML Audio element and get the duration from there (but source must be loaded first)
Code:
var fr = new FileReader();
        fr.onload = function (e) {
            var audiosrc=this.result;
           //do something with audiosrc. E.g. myaudioelement.src=audiosrc; After myaudioelement is loaded you may get it's duration by myaudioelement.duration
        };
        
        fr.readAsDataURL(file);
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top