无法将blob打包为适当的二进制格式

时间:2017-01-25 23:24:38

标签: javascript python json serialization

我想做什么

我录制麦克风。我有一大块音频作为blob类型audio/wav。我想在json中传输这些数据并将其发送到另一台与浏览器无关的机器。然后该设备在其系统上播放声音。

我拥有什么

这就是我在浏览器上所做的事情:

// .js

navigator.mediaDevices.getUserMedia({audio: true}).then(onMediaSuccess);

function onMediaSuccess(stream) {
    var mediaRecorder = new MediaStreamRecorder(stream);
    mediaRecorder.mimeType = 'audio/wav';

    mediaRecorder.ondataavailable = handleDataAvailable;
    mediaRecorder.start();
    function handleDataAvailable(blob) {
        BlobUtil.blobToBinaryString(blob).then(function(binaryString) {
                // success
                ws.publish(`com.app.audioStream__`, binaryString);
            }
            console.log('BlobUtil: success')
        }).catch(function(err) {
            // error
            console.log('BlobUtil: error')
        });
    }
}

这是我的Python方面,并没有真正发生。

# .py

import pyaudio

CHUNK = 1024
CHANNELS = 1
RATE = 44100
WIDTH = 2

p = pyaudio.PyAudio()
stream = p.open(format=p.get_format_from_width(WIDTH),
                channels=CHANNELS,
                rate=RATE,
                output=True,
                frames_per_buffer=CHUNK)

stream.start_stream()

# when the .js triggers the event this runs. So on every chunk sent.
def audioStream(data):
    if stream.is_active():
        print data[:100]
        stream.write(data) # encoding error on data

yield self.subscribe(audioStream, 'com.app.audioStream__{}'.format(''))

stream.stop_stream()
stream.close()

binaryString看起来不正确。它接近于看起来像wav文件,但似乎它使用不同的编码。

但是,当直接在python中读取文件(.wav)时,会产生以下byte string

当我使用套接字传输数据时,它会将所有内容序列化为JSON。

所以,我需要以某种方式从blob --> binaryString --> json(unicode) --> bytes获得。我不确定二进制字符串和字节是否有所不同,或者它被强制通过JSON序列化而毁了。

编辑:

toBuffer正在帮助。

我在另一篇文章中找到的内容JSON cannot encode binary data. You should parse your buffer (probably as UTF8), or use base64.要试一试,看看它是否有效

在toBuffer的帮助下,我能够在浏览器端获得正确的格式

代码:

function handleDataAvailable(blob) {
    toBuffer(blob, function(err, buffer) {
        if (err)
            throw err

        ws.publish(`com.app.audioStream__`, buffer.toString());
    });
}

但是,当我从websocket的Python端获取它时。它以正确的方式显示数据,但编码关闭。卡在unicode中我无法用任何东西解码它总是导致`exceptions.UnicodeEncodeError:' ascii'编解码器不能对字符u' \ ufffd'进行编码。位置5:序数不在范围内(128)。但是,当我将打印数据复制并粘贴到python终端并从那里播放时,它可以工作。

当我从socket中获取使用JSON的数据时,可能会篡改二进制数据的编码。

我也尝试在JSON的接收端执行buffer.toJSON()

[82L, 73L, 70L, 70L, 36L, 192L, 2L, 0L, 87L, 65L, 86L, 69L, 102L, 109L, 116L, 32L, 16L, 0L, 0L, 0L, 1L, 0L, 2L, 0L, 68L, 172L, 0L
, 0L, 16L, 177L, 2L, 0L, 4L, 0L, 16L, 0L, 100L, 97L, 116L, 97L, 0L, 192L, 2L, 0L, 232L, 255L, 232L, 255L, 254L, 255L, 254L, 255L, 5L, 0L, 5L, 0L, 253L, 25
5L, 253L, 255L, 3L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 252L, 255L, 252L, 255L, 250L, 255L, 250L, 255L, 243L, 255L, 243L, 255L, 251L, 255L, 251L, 255L, 249L, 255L
, 249L, 255L, 250L, 255L, 250L, 255L, 1L, 0L, 1L, 0L, 7L, 0L, 7L, 0L]

我不确定如何处理此信息。我猜它是字节的长表示。所以字节数组,我需要转换为字节字符串。

我在另一篇文章中发现了这个:

def Dump(n): 
  s = '%x' % n
  if len(s) & 1:
    s = '0' + s
  return s.decode('hex')
print repr(Dump(1245427))  #: '\x13\x00\xf3'

试图拉开上面的二进制数据。

b''.join([Dump(i) for i in data])

我屈服

'RIFF$\xc0\x02\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x02\x00D\xac\x00\x00\x10\xb1\x02\x00\x04\x00\x10\x00data\x00\xc0\x02\x00\xe8\xff\xe8\xff\xfe\xff\xfe\xff\x05\x00\x05\x00\xfd\x19\x05\xfd\xff\x03\x00\x03\x00\x00\x00\x00\x00\xfc\xff\xfc\xff\xfa\xff\xfa\xff\xf3\xff\xf3\xff\xfb\xff\xfb\xff\xf9\xff\xf9\xff\xfa\xff\xfa\xff\x01\x00\x01\x00\x07\x00\x07\x00'

它很接近,但我需要它更像RIFFX�WAVEfmt D��Xdata4�

我无法用它做任何事情。那里的一些字节只是不允许任何en / de-coding。我只是不知道去哪里获得正确的格式。

我可能无法理解在通过套接字和阅读时我的信息是如何处理的。

1 个答案:

答案 0 :(得分:0)

所以,我能够找到问题并解决它。

主要问题是我用来使用websockets进行交互的软件。 它的序列化方法默认为JSON,但JSON一直在修改我的字节数据。

我让websocket框架使用了不同的序列化程序msgpack,它可以正确处理字节而不会破坏数据。