0

Я пытаюсь передать mp3-данные с моего сервера на клиентскую сторону. Я делаю это с помощью Ajax. Сервер отправляет 50 килобайт за запрос. Я написал две функции: одну, которая получает mp3-данные и одну, которая их воспроизводит. Первая функция занимает 50 килобайт, декодирует их и хранит декодированные данные в массиве, тогда она называет себя рекурсивно. Вторая функция начинает воспроизведение, как только первый элемент массива заполняется данными. Проблема в том, что это работает для первых 50kilobytes только тогда, когда это терпит неудачу. Я хочу, чтобы моя функция get_buffer работала до тех пор, пока сервер не сообщит ему больше данных для отправки и сохранит функцию play(), играя данные, пока в массиве не будет больше элементов.Асинхронные рекурсивные функции в javascript

Вот мои две функции:

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

Вторая функция:

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

} 

ответ

0

Рекурсивный вызов buffer_seg находится в главном корпусе buffer_seg, а не в обратном вызове, так что это происходит сразу - не, как вы, кажется, намерены, после получения ответа. Во-вторых, это также означает, что рекурсивный вызов является безусловным, если он должен основываться на том, будет ли в предыдущем ответе больше данных. Если это не просто сбой вашего браузера, я не уверен, почему. Это также означает, что куски потокового аудио могут быть вытолкнуты в буфер из строя.

Чтобы начать, я бы посмотрел на перемещение рекурсивного вызова в конец обработчика onload после проверки конца потока.

Во 2-й функции, что вы намерены делать if (buffer_seg == false)? Это условие никогда не будет выполнено. Вы думаете, что это способ увидеть последнее возвращаемое значение от buffer_seg? Это не так, как это работает. Возможно, у вас должна быть переменная, которую могут видеть обе функции, которую может установить buffer_seg, и play может протестировать или что-то в этом роде.

+0

Переменная «offset» указывает серверу, начиная с которого байт должен посылать сервер аудио. Таким образом, сервер отвечает «done», если смещение отправляется в конец файла или после окончания файла. Я проверяю, равен ли размер arraybuffer 4, чем должен быть «сделан». Тогда он возвращает false. Извините, это мое плохое, это должно быть (buffer_seg() == false). он вызывает функцию buffer_seg(), когда он достигает конца массива, чтобы увидеть, будет ли buffer_seg буферизовать новые данные или возвращает false, указывающий EOF. Спасибо за ваш ответ –

+0

Да, я знаю, что вы намерены компенсировать. Я не уверен, почему вы указываете это; это не изменит, что ответы могут выходить из строя, когда вы написали свой код. Кроме того, '(buffer_seg() == false)' не будет работать лучше, так как вызов 'buffer_seg' никогда не вернется. В любом случае, поскольку у вас есть 'buffer_seg', вызывающий себя, нет смысла также иметь' play'. –

+0

Да, я согласен с вашими точками, я вижу, как это может привести к неправильному запуску скрипта, и я даже исправил некоторые из этих проблем. Но есть ли у вас какие-либо предложения о том, как я могу написать функцию, которая сохраняет потоковые данные в фоновом режиме и сохраняет их в массиве и другую функцию, которая считывает массив и сохраняет его. Или любая идея, как я могу хранить двоичные данные mp3 и воспроизводить их до того, как будет выполнена вся буферизация? –

Смежные вопросы