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


Joined
Dec 14, 2021
Messages
23
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
82
Reaction score
8
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
23
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
82
Reaction score
8
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
23
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
82
Reaction score
8
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