0

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(); 
    } 

} 

Antwort

0

Der rekursive Aufruf buffer_seg in dem Hauptkörper der buffer_seg ist, nicht in der Callback, so dass er sofort geschieht - nicht, wie Sie anscheinend beabsichtigen, nachdem eine Antwort empfangen wurde. Zweitens bedeutet dies auch, dass der rekursive Aufruf unbedingt ist, wenn er darauf basieren sollte, ob die vorherige Antwort mehr Daten verfügbar gemacht hat. Wenn das nicht nur Ihren Browser zum Absturz bringt, weiß ich nicht warum. Es bedeutet auch, dass Teile des gestreamten Audiomaterials in den Puffer verschoben werden können.

So zu starten, würde ich betrachten, den rekursiven Anruf an das Ende des onload Handlers zu verschieben, nach der Überprüfung auf Ende des Streams.

In der 2. Funktion, was haben Sie vor, if (buffer_seg == false) zu tun? Diese Bedingung wird niemals erfüllt werden. Denken Sie, dass dies eine Möglichkeit ist, den letzten Rückgabewert von buffer_seg zu sehen? So geht es nicht. Vielleicht solltest du eine Variable haben, die beide Funktionen sehen können, die setzen kann und play testen kann oder so ähnlich.

+0

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 –

+0

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. –

+0

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? –

Verwandte Themen