Передача ArrayBuffer с метаданными (по соединению данных webRTC)

В документах я вижу следующий пример отправки строки по каналу данных WebRTC:

var message = messageInputBox.value;
sendChannel.send(message);

Я пытаюсь отправить изображения и видео, поэтому я создаю ArrayBuffer:

var reader = new FileReader();
reader.addEventListener("loadend", function () {
     // reader.result contains the contents of blob as a typed array
     data.media = reader.result; // ArrayBuffer
     outboundMediaQueue.push(data);
});
reader.readAsArrayBuffer(data.media);

Я могу передать этот ArrayBuffer, но я также пытаюсь отправить вместе с ним некоторые метаданные (идентификатор носителя). Учитывая, что я не могу JSON.serialize создать ArrayBuffer, как я могу передать эти данные с соответствующими метаданными?

Обновление:

Это работает:

sendChannel.send(data.media); // sending `ArrayBuffer` only

Но это не работает:

sendChannel.send(data); // arbitrary object with desired metadata

И это тоже не работает:

sendChannel.send(JSON.stringify(data));

Обновление 2

Я составил следующий модуль, который, кажется, обрабатывает кодирование и декодирование. Он не полностью протестирован и не тестировался на больших файлах; Я буду держать это в курсе, когда выясню, что работает:

define([], function () {
    // https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_–_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8
    // https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String

    const arrayBufferConverter = {};
    arrayBufferConverter.bufferToString = function (outboundBuffer) {
        const dataView = new DataView(outboundBuffer);
        const decoder = new TextDecoder('utf-8'); // base64?
        const decodedString = decoder.decode(dataView);
        return decodedString;
    }

    arrayBufferConverter.stringToBuffer = function (inboundString) {
        var encoded = new TextEncoderLite('utf-8').encode(inboundString);
        var b64Encoded = base64js.fromByteArray(encoded);
        return b64Encoded;
    }

    return arrayBufferConverter;
});

Обновление 3

Поскольку моя единственная реальная потребность здесь — соединить метаданные с ArrayBuffer, я собираюсь забыть о бессмыслице кодирования/декодирования и просто сгенерировать дайджест на обоих концах транзакции:

arrayBufferConverter.getDigestFromBuffer = function (buffer) {
    const view = new DataView(buffer);
    const numBytes = view.byteLength;
    const interval = Math.floor(numBytes / 32);
    var currentIndex = 0;
    var digest = "";
    while (currentIndex < numBytes) {
        digest += view.getInt8(currentIndex);
        currentIndex += interval;
    }
    return digest;
}

Таким образом, я буду отправлять ArrayBuffers и соответствующие метаданные в двух отдельных запросах и управлять сопряжением с помощью некоторой базовой логики очереди. Это полностью устраняет текущие затраты на обработку и риски, связанные с кодированием/декодированием больших медиафайлов, в пользу небольшой фиксированной стоимости логики сопряжения. Я оставлю это открытым, если у кого-то есть другие рекомендации.


person SB2055    schedule 29.06.2017    source источник
comment
О, я думал, что вы имели в виду метаданные изображения раньше. Вы можете добавить больше атрибутов к объекту data, не так ли? Или я ошибаюсь?   -  person Patrick Roberts    schedule 30.06.2017
comment
@PatrickRoberts - только что обновил несколько примеров того, что я собираюсь сделать   -  person SB2055    schedule 30.06.2017
comment
Ах хорошо. Спасибо. Я посмотрю на это позже. Ненавижу это говорить, но вам либо понадобится сторонняя библиотека, либо вам нужно будет изучить двоичный формат изображения/jpeg (по крайней мере, как организованы байты заголовка, не обязательно формат сжатия).   -  person Patrick Roberts    schedule 30.06.2017
comment
@PatrickRoberts - ой. Я тоже начну копать в этом направлении. Спасибо вам за помощь!   -  person SB2055    schedule 30.06.2017
comment
Возможный дубликат добавления свойства в ArrayBuffer, отправленного по DataChannel   -  person jib    schedule 30.06.2017
comment
@jib Я думаю, что стоит оставить это, учитывая, как быстро движется WebRTC. Теперь может быть другое решение, которое другой вопрос никогда не сможет привлечь в качестве ответа.   -  person SB2055    schedule 30.06.2017
comment
@ SB2055 Что вы имеете в виду под другой вопрос никогда не сможет привлечь внимание в качестве ответа? Если есть новый ответ на вопрос, любой может опубликовать его. Если вы хотите переключить внимание, предложите награду.   -  person Bergi    schedule 30.06.2017
comment
@Bergi Чтобы получить обновленный ответ, кто-то должен найти этот вопрос и опубликовать ответ, несмотря на то, что он был выбран. Затем читателям придется сделать дополнительный шаг, чтобы пролистать выбранный (потенциально устаревший) ответ. Я не видел этот вопрос раньше, но я не понимаю, как оставление этого вопроса может помочь, опять же, учитывая, как быстро развивается эта конкретная технология.   -  person SB2055    schedule 30.06.2017
comment
@SB2055 Я нашел библиотеку и отправил запрос на поддержку TypedArrays. Независимо от того, работают они или нет, вы все равно можете использовать его, просто выполняя манипуляции со строками в кодировке base64 или двоичными строками, а затем используйте API чтения файлов для преобразования в TypedArrays для передачи. К сожалению, пока библиотека не поддерживает TypedArrays, потребление памяти вашим приложением будет довольно большим.   -  person Patrick Roberts    schedule 30.06.2017
comment
@PatrickRoberts Понятно - спасибо за это. Что вы думаете о простой отправке TypedArray независимо от метаданных для обновления 3? Я также нацелен на мобильные клиенты, поэтому я должен помнить о потреблении памяти, хотя я еще не профилировал обновление 3 по сравнению с piexifjs.   -  person SB2055    schedule 30.06.2017