Ich versuche, MP3-Daten von meinem Server auf die Client-Seite streamen. Ich mache das mit Ajax. Der Server sendet 50 Kilobyte pro Anfrage. Ich habe zwei Funktionen geschrieben: eine, die die mp3-Daten bekommt und eine, die sie abspielt. Die erste Funktion nimmt die 50 Kilobyte, decodiert sie und speichert die dekodierten Daten in einem Array, dann ruft sie sich rekursiv auf. Die zweite Funktion beginnt zu spielen, sobald das erste Element im Array mit Daten gefüllt ist. Das Problem ist, dass dies nur für die ersten 50 Kilobytes funktioniert. Ich möchte, dass meine get_buffer-Funktion läuft, bis der Server sagt, dass keine Daten mehr zu senden sind, und meine play() - Funktion so lange Daten abspielt, bis keine Elemente mehr im Array sind.Asynchrone rekursive Funktionen in Javascript
Hier sind meine zwei Funktionen:
function buffer_seg() {
// starts a new request
buff_req = new XMLHttpRequest();
// Request attributes
var method = 'GET';
var url = '/buffer.php?request=buffer&offset=' + offset;
var async = true;
// set attributes
buff_req.open(method, url, async);
buff_req.responseType = 'arraybuffer';
// keeps loading until something is recieved
if (!loaded) {
change_icon();
buffering = true;
}
buff_req.onload = function() {
segment = buff_req.response;
// if the whole file was already buffered
if (segment.byteLength == 4) {
return true;
} else if (segment.byteLength == 3) {
return false;
}
// sets the new offset
if (offset == -1) {
offset = BUFFER_SIZE;
} else {
offset += BUFFER_SIZE;
}
//decodes mp3 data and adds it to the array
audioContext.decodeAudioData(segment, function(decoded) {
buffer.push(decoded);
debugger;
if (index == 0) {
play();
}
});
}
buff_req.send();
buff_seg();
}
Zweite Funktion:
function play() {
// checks if the end of buffer has been reached
if (index == buffer.length) {
loaded = false;
change_icon();
if (buffer_seg == false) {
stop();
change_icon();
return false;
}
}
loaded = true;
change_icon();
// new buffer source
var src = audioContext.createBufferSource();
src.buffer = buffer[index++];
// connects
src.connect(audioContext.destination);
src.start(time);
time += src.buffer.duration;
src.onended = function() {
src.disconnect(audioContext.destination);
play();
}
}
Die Variable "offset" teilt dem Server mit, welches Byte der Server das Mp3-Audio senden soll. Der Server antwortet mit "done", wenn der Offset an das Ende der Datei oder nach dem Ende der Datei gesendet wird. Ich überprüfe, ob die Größe des Array-Puffers gleich 4 ist, es muss "erledigt" sein. Es gibt dann false zurück. Sorry, es ist mein Fehler, sollte es sein (buffer_seg() == false). Es ruft die Funktion buffer_seg() auf, wenn es das Ende des Arrays erreicht, um zu sehen, ob buffer_seg neue Daten puffert oder false zurückgibt, was den EOF anzeigt. Danke für Ihre Antwort –
Ja, ich weiß, was Sie beabsichtigen, Offset zu tun. Ich bin mir nicht sicher, wieso Sie darauf hinweisen; Es ändert sich nicht, dass Antworten, die Sie geschrieben haben, nicht mehr in der richtigen Reihenfolge angezeigt werden. Außerdem wird '(buffer_seg() == false)' nicht besser funktionieren, da der Aufruf von 'buffer_seg' niemals zurückkehrt. In jedem Fall, da Sie 'buffer_seg' sich selbst nennen, gibt es keinen Sinn,' play' zu nennen. –
Ja, ich stimme deinen Punkten zu, ich kann sehen, wie dies dazu führen kann, dass das Skript nicht korrekt läuft, und ich habe sogar einige dieser Probleme bereits korrigiert. Aber haben Sie irgendwelche Vorschläge, wie ich eine Funktion schreiben könnte, die Daten im Hintergrund speichert und sie in einem Array speichert und eine andere Funktion, die das Array liest und speichert. Oder irgendeine Idee, wie kann ich MP3-Binärdaten puffern und es vor der ganzen Pufferung tun? –