2016-07-02 25 views
0

Ich habe mehrere Probleme beim Streamen eines Audios von Nodejs Server Realtime zu mehreren HTML-Clients (die auch zu späteren Zeiten verbunden sein könnte). Was ich in dem Code unten tun, ist laden 2 mp3-Dateien, in einem PufferArray und dann, wenn die Clients verbunden sind, halte ich aus PufferArray und dann drosseln bei 16384 Bytes/sec ~ 128kbits/sec und schreibe es an die Clients. Aber ich fühle, dass die Puffer ziemlich schnell geleert werden. Ist meine Vorgehensweise korrekt? Grundsätzlich sollte ich sicherstellen, dass alle Clients denselben Teil des Songs spielen sollten. Und vor allem kann keiner meiner Kunden die Songs spielen, das ist ein anderes Problem.stream audio von nodejs zu html5 audio tag

Jede Hilfe würde sehr geschätzt werden.

var http = require('http'); 
var fs = require("fs"); 
var url = require('url'); 
var stream = require('stream'); 
var Throttle = require('throttle'); 
var bufferArray = []; 
var clients = []; 
var entry = true; 
setInterval(function() { 
    if(bufferArray.length > 0 && clients.length > 0){ 
    entry = false; 
    var buffer = bufferArray.shift(); 
    var bufferStream = new stream.PassThrough(); 
    var throttledStream = new stream.PassThrough(); 
    var throttle = new Throttle(16384); 
    bufferStream.end(new Buffer(buffer)); 
    bufferStream.pipe(throttle).pipe(throttledStream); 
    throttledStream.on('data',function(data){ 
     console.log("Going to write to all the clients "+clients.length); 
     for(var i = 0; i < clients.length; i++){ 
      clients[i].write(data); 
     } 
    }); 
    throttledStream.on('end',function(){ 
     console.log("finished the buffer. Still have to write tot "+bufferArray.length+" buffers"); 
     entry = true; 
    }); 
    } 
},1); 
function readMp3FilesInBuffer(songName,callback){ 
    var fd = fs.createReadStream("./songs/"+songName); 
    fd.on('data',function(chunk){ 
     bufferArray.push(chunk); 
    }); 
    fd.on('end',callback); 
} 

readMp3FilesInBuffer("FeelOfLove.mp3",function(){ 
    readMp3FilesInBuffer("ILoveAfrica.mp3",function() { 
    console.log("successfully read the songs.."); 
    http.createServer(function (request, response) { 
     var parsedUrl = url.parse(request.url,true); 
     var requestType = parsedUrl.query.requestType; 
     if(requestType == "renderHtml"){ 
     console.log("got a request to render html"); 
     response.writeHead(200, { 
      'Content-Type': 'text/html' 
     }); 
     var htmlStream = fs.createReadStream("./views/audioStreaming.html"); 
     htmlStream.pipe(response); 
     } 
     else if (requestType === "stream") { 
     response.writeHead(200,{ 
      "Content-Type": "audio/mpeg", 
      'Transfer-Encoding': 'chunked' 
     }); 
     clients.push(response); 
     console.log("got a request to stream. Tot clients available : "+clients.length); 
     } 
     else{ 
     response.end(); 
     } 
    }).listen(8081,function() { 
     console.log("listening"); 
    }); 

    }); 
}); 

Antwort

1

Es ist schon ein Stück Code hier, und einiges an Informationen fehlt ... aber es gibt auch schon einige Dinge erwähnenswert, dass könnte die Quelle Ihrer spezifischen Probleme.

Sie erwähnten Clients können nicht spielen. Sind sie auf dem richtigen Weg, um deinen Stream zu nutzen? Erhalten sie die richtigen Header und Daten? Wenn nicht, repariere das zuerst.

Nur etwa ein Drittel der Streaming-Media-Audio-Player da draußen umgehen Chunked-Codierung tatsächlich richtig. Wenn Sie im Browser sind (eigentlich auf einer Webseite), sind Sie in der Regel in Ordnung, aber außerhalb davon ist die Chunked-Codierung ein Nicht-Starter. Sie müssen Node.js zwingen, Chunked-Codierung insgesamt zu überspringen.

Sie haben nicht angegeben, welches Drosselmodul Sie verwendet haben. Ist es TooTallNate durch Zufall? Wenn ja, hatte ich in der Vergangenheit Probleme mit diesem Modul. Es wurde vor kurzem nicht aktualisiert und spielt wahrscheinlich nicht gut mit modernen Node.js "Streams3".

In jedem Fall ist die Art der Drosselung nicht angemessen. Während Ihre durchschnittliche Bitrate 128k ist, wird es nicht unbedingt genau 128k sein. Sie sollten nicht die Bitrate annehmen. Sie könnten Ihren eigenen Code schreiben, um MP3-Frame-Header zu lesen und entsprechend zu synchronisieren, aber warum tun Sie das, wenn es bereits anderswo gemacht wurde? Ich würde FFmpeg als Kind-Prozess starten und es in Echtzeit ausführen lassen. Ungeprüfte, aber so etwas wie dies:

ffmpeg -re -i yourfile.mp3 -map_metadata -1 -acodec copy -f mp3 - 

Neben auf den tatsächlichen Medien basiert Drosselung hat dies den Vorteil der Beseitigung aller zufälligen ID3-Tags und andere zufällige Mist, dass Software wie iTunes mag in MP3 einzubetten, geben Du hast einen schönen sauberen Strom, mit sehr wenig Overhead.

Das nächste Problem, das Sie haben werden, ist, dass Ihre Clients eine lange Zeit benötigen, um die Wiedergabe zu puffern und zu starten. Einen großen Puffer bereit zu haben, um sie zu bündeln, sobald sie sich verbinden, löst dieses Problem.

Viele Browser (wie Chrome) werden Bereichsanfragen stellen und versuchen, Ihren Stream wie jede andere MP3-Datei zu behandeln. Wenn Sie diese Bereichsanfragen einfach ignorieren, wie Sie es tun, wird alles gut funktionieren. Sie könnten jedoch in Betracht ziehen, sie zu behandeln, basierend auf den Besonderheiten Ihrer Arbeit.

Am Ende des Tages, können Sie dies funktioniert, aber es gibt eine Menge beteiligt, und eine Menge kleine Verbesserungen, um den Stream für alle Ihre Zuhörer arbeiten zu lassen. Könnte ich vorschlagen, den Stream zu etwas zu lassen, das das bereits tut, wie Icecast? Sie können die Streams weiterhin in Node.js bereitstellen, sodass Sie jede beliebige Anwendungslogik um die Quelle des Streams binden können. Ein bisschen Eigenwerbung ... Ich habe einen Node.js-Code, den ich für die Verbindung mit Icecast lizenzieren kann. Ich habe auch eine CDN, die Sie direkt von Ihrer Node.js App streamen können. Sie können es unter https://audiopump.co oder per E-Mail an [email protected] ausprobieren.Selbst wenn Sie sich dazu entschließen, alles selbst zu tun, sollten Sie den Stream aus Ihrer Node.js-App beziehen und etwas anderes bereitstellen.

+0

Hey tnx für die Antwort. Ich konnte die Bitrate der Ausgabe-MP3-Datei als 128kbps mit einem npm-Modul https://github.com/fluent-ffmpeg/node-fluent-ffmpeg einstellen, das ffmpeg verwendet, wie Sie es vorgeschlagen hatten. Aber meine zweite Frage ist, ich versuche eine Live-Streaming-App zu machen. Als Vorstufe wollte ich es mit nur zwei mp3-Dateien versuchen. Ich wollte auch sicherstellen, dass zwei Clients (meist Browser), die zu verschiedenen Zeitpunkten mit dem Server verbunden waren, so synchronisiert werden sollten, dass beide Clients den gleichen Teil des Songs spielen. Wie würde ich dieses Szenario angehen? Irgendwelche Eingaben wären großartig. –

+0

MP3 und AAC mit ADTS können beliebig segmentiert werden. Dies bedeutet, dass Sie die Daten gleichzeitig an die Browser senden können und sie sich selbst synchronisieren. Dies ist sehr hilfreich für Sie, da Ihr Server die Daten nicht kennen muss. Puffern Sie es einfach und senden Sie es wie es ist an die Clients. Verwenden Sie idealerweise einen vorhandenen Server und verwenden Sie Ihre Anwendung als Quelle für diesen Server. Sie erhalten den Vorteil, dass Sie den Code, den Sie für die Quelle des Streams haben möchten, schreiben, ohne eine Menge Zeit damit zu verbringen, die bereits vorhandenen Teile neu zu erfinden. – Brad