I'm testing with following HTML hosted on a node.js server:
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Audio Testing</title>
</head>
<body>
<audio src='/public/tests/audioTest.mp3' controls autoplay loop></audio>
</body>
</html>
The problem is that the audio will only play once when the page loads (Chrome only since it is mp3).
I suspect this is a node.js issue because the audio loops fine when I test this locally by just loading the HTML file without any webserver. It also works as expected on the Apache server that I tested it on. Additionally, if I link to an mp3 file hosted on an Apache server, it still works as expected with the HTML being served by the node server.
The audio also loops fine when encoded as base64.
I am using version 0.8.14 of node.js. A live demo of the code hosted on node can be accessed here.
EDIT The server has a directory named "public" which the server will always serve files from if they are requested. The audio file and the html page are both in the "public" directory.
The node.js server code is as follows:
var http = require('http');
var fs = require('fs');
var mime = require('mime');//Third party library for looking up mime types
var handleRequest = function(req, res) {
if (req.url === '/') {
fs.createReadStream(__dirname+'/public/homePage.html').pipe(res);
return;
}
else if (req.url === '/favicon.ico') {
fs.createReadStream(__dirname+'/public/favicon.ico').pipe(res);
return;
}
else if (req.url.substr(0, 7) === '/public') {
var mim = mime.lookup(req.url);
var ext = mime.extension(mim);
console.log('mime '+mim+' ext '+ext);
if (ext !== 'bin') {
fs.exists(__dirname+'/'+req.url, function(exists) {
if (exists) {
if (req.headers.range) {
var filename = __dirname+req.url;
fs.readFile(filename, 'binary', function(err, file) {
var header = {};
var range = req.headers.range;
var parts = range.replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var total = file.length;
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : total-1;
header["Content-Range"] = "bytes " + start + "-" + end + "/" + (total);
header["Accept-Ranges"] = "bytes";
header["Content-Length"]= (end-start)+1;
//header['Transfer-Encoding'] = 'chunked';
header["Connection"] = "close";
res.writeHead(206, header);
res.write(file.slice(start, end)+'0', "binary");
res.end();
return;
});
}
else {
res.writeHead(200,{'Content-Type':mim});
fs.createReadStream(__dirname+'/'+req.url).pipe(res);
return;
}
else {res.end();}
});
}
else {res.end();}
}
else {res.end();}
};
var server = http.createServer(handleRequest);
server.listen(8888);//Listening on port 8888
I suspect that this is because your Node.js server isn't responding to the range request.
Chrome is sending a range request for a certain set of bytes in the file. I don't know why it would be incapable of looping without getting those bytes in the response, but that should be the only difference.