我录制麦克风。我有一大块音频作为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。我只是不知道去哪里获得正确的格式。
我可能无法理解在通过套接字和阅读时我的信息是如何处理的。
答案 0 :(得分:0)
所以,我能够找到问题并解决它。
主要问题是我用来使用websockets进行交互的软件。 它的序列化方法默认为JSON,但JSON一直在修改我的字节数据。
我让websocket框架使用了不同的序列化程序msgpack
,它可以正确处理字节而不会破坏数据。