2015-10-24 15 views
3

Я пытаюсь отправить blob, исходящий из нового API MediaRecorder в Firefox в NodeJS, чтобы сохранить его в файле. Блок содержит запись как преобразованный webm-файл. Я обманываю этот blob до определенного размера перед отправкой, чтобы иметь возможность отправлять его по пропускной способности, предоставляемой каналом данных webrtc. Это выглядит следующим образом:Отправка blob как Uint8Array в NodeJS и сохранение его в файл

var blobToBuffer = function(blob, cb) { 
    var reader = new FileReader(); 
    reader.onload = function() { 
    cb(reader.result); 
    }; 
    reader.readAsArrayBuffer(blob); 
}; 

blobToBuffer(blob, function(buffer){ 
    var sendInterval = setInterval(function(){ 
    var currentEnd = dataSend + dis._dataChunkSize; 
    if(currentEnd > buffer.byteLength){ 
     currentEnd = buffer.byteLength; 
    } 
    var part = Array.apply([], new Uint8Array(buffer.slice(dataSend, currentEnd))); 
    dis.dataChannel.send(
     JSON.stringify({ 
     payload: part 
     }) 
    ); 
    dataSend = currentEnd; 
    if(dataSend + 1 >= buffer.byteLength){ 
     dis.dataChannel.send(JSON.stringify({action: 'dataEnd'})); 
     clearInterval(sendInterval); 
    } 
    }, 1000); 
}); 

На стороне nodeJS я пытаюсь преобразовать данные обратно в WebM файл, например так:

fs.appendFile('my/path/file.webm', new Buffer(new Uint8Array(message.payload)), function(error){ 
    if(error){ 
     console.log(error); 
    } else { 
     console.log('Chunk successfully written'); 
    } 
}); 

Он говорит мне, что кусок был написан, однако файл пуст. Я пробовал то же самое с кодировкой base64, полученной из blob, которая работала, но показалась плохой идеей из-за возможного повреждения данных.

Что мне не хватает? Или есть лучший способ передать blob с JavaScript на NodeJS?

EDIT

uint8array-конструктор, кажется, не принимает данные, поступающие в виде строки:

'0': 39, '1': 209, '2': 79, '3': 0, '4': 230, '5': 133,
'6': 190, '7': 138, '8': 188, '9': 103, '10': 131,

После новой части Uint8Array (message.payload) длина массива все еще равна 0. Таким образом, как это сделать?

РЕДАКТИРОВАТЬ II

После добавления .ToString() при использовании JSON.stringify() мне удалось получить UInt8Array как хотелось бы. Однако, поскольку код показан выше, он только записывает [объект uint8array] в файл.

EDIT III - Решение

Используя код выше работает отлично.

ответ

1

[объект uint8array] - это то, что вы должны получить, когда используете toString на uint8array. Просто преобразуйте буфер в строку и отправьте строку. Если вы хотите, вы можете попробовать кодировку base64, но я не думаю, что вам это нужно.

var str = ""; // string version of the part 
for{var i = 0; i < part.length; i++){ 
    str += String.fromCharCode(part[i]); 
} 
dis.dataChannel.send(
    JSON.stringify({ 
    payload: str 
    }) 
); 

Если Nodejs не нравится строка, как затем использовать btoa, чтобы преобразовать его в кодировке base64. Не волнуйтесь, вы не получите коррупцию, вот почему base64 остановил некоторые транспортные протоколы от неправильной интерпретации исходной двоичной строки.

dis.dataChannel.send(
    JSON.stringify({ 
    payload: btoa(str) // encode string as base64; 
    }) 
); 

Также убедитесь, что типы мим правильны.

+0

спасибо. Я действительно получил его на работу (см. Выше). Использование toString() было своего рода наивной проблемой. Интересно, какой из них лучше работает. –

+0

Для всех заинтересованных: Я создал тест на JSPerf. http://jsperf.com/filereader-reading-blob-and-stringify/2 - просмотрите консоль браузеров для получения инструкций. Гист: используйте ArrayBuffer и обработайте его на NodeJS –