我正在使用 Pyaudio 从麦克风捕获音频,并尝试使用 opus 编解码器对其进行编码/解码。我正在使用 SvartalF ( https://github.com/svartalf/python-opus ) 对 libopus 的绑定(bind)。
这是我的代码:
import pyaudio
from opus import encoder, decoder
def streaming(p):
chunk = 960
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 48000
streamin = p.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
input_device_index = 7,
frames_per_buffer = chunk)
streamout = p.open(format = FORMAT,
channels = CHANNELS,
rate = 48000,
output = True,
output_device_index = p.get_default_input_device_info()["index"],
frames_per_buffer = chunk)
enc = encoder.Encoder(RATE,CHANNELS,'voip')
dec = decoder.Decoder(RATE,CHANNELS)
data = []
for i in xrange(100):
data.append(streamin.read(chunk*2))
streamout.write(''.join(data))
encdata = []
for x in data:
encdata.append(enc.encode(x,chunk))
print "DATA LENGTH :", len(''.join(data))
print "ENCDATA LENGTH :", len(''.join(encdata))
decdata = ''
for x in encdata:
decdata += dec.decode(x,chunk)
print "DECDATA LENGTH :", len(decdata)
streamout.write(decdata)
streamin.close()
streamout.close()
p = pyaudio.PyAudio()
streaming(p)
p.terminate()
我必须在 data.append(streamin.read(chunk*2))
或 中放置
我不知道为什么。chunk*2
而不是 chunk
>DECDATA LENGTH == DATA LENGTH*2
输出:
DATA LENGTH : 384000
ENCDATA LENGTH : 12865
DECDATA LENGTH : 384000
如果没有编码/解码,第一个streamout.write(''.join(data))
工作完美。通过编码/解码,streamout.write(decdata)
可以工作,但混有很多爆裂声。
我在这里做错了什么?
最佳答案
这似乎是由 python-opus 的解码方法中的错误引起的。
根据Opus API , opus_decode 返回解码的样本数。 python 绑定(bind)假设它将完全填充它传入的结果缓冲区,因此每组解码样本都会附加一个静音。这种沉默会导致低帧尺寸时出现裂纹,而高帧尺寸时会出现卡顿。虽然文档没有提及任何内容,但返回的数字似乎是每个 channel 的。
换线150 of opus/api/decoder.py以下为我解决了这个问题:
return array.array('h', pcm[:result*channels]).tostring()
如果您需要使用decode_float方法,则可能需要进行相同的更改。
关于 python : PortAudio + Opus encoding/decoding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17728706/