Я пытаюсь передать 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();
}
}
Переменная «offset» указывает серверу, начиная с которого байт должен посылать сервер аудио. Таким образом, сервер отвечает «done», если смещение отправляется в конец файла или после окончания файла. Я проверяю, равен ли размер arraybuffer 4, чем должен быть «сделан». Тогда он возвращает false. Извините, это мое плохое, это должно быть (buffer_seg() == false). он вызывает функцию buffer_seg(), когда он достигает конца массива, чтобы увидеть, будет ли buffer_seg буферизовать новые данные или возвращает false, указывающий EOF. Спасибо за ваш ответ –
Да, я знаю, что вы намерены компенсировать. Я не уверен, почему вы указываете это; это не изменит, что ответы могут выходить из строя, когда вы написали свой код. Кроме того, '(buffer_seg() == false)' не будет работать лучше, так как вызов 'buffer_seg' никогда не вернется. В любом случае, поскольку у вас есть 'buffer_seg', вызывающий себя, нет смысла также иметь' play'. –
Да, я согласен с вашими точками, я вижу, как это может привести к неправильному запуску скрипта, и я даже исправил некоторые из этих проблем. Но есть ли у вас какие-либо предложения о том, как я могу написать функцию, которая сохраняет потоковые данные в фоновом режиме и сохраняет их в массиве и другую функцию, которая считывает массив и сохраняет его. Или любая идея, как я могу хранить двоичные данные mp3 и воспроизводить их до того, как будет выполнена вся буферизация? –