Python:PortAudio+;Opus编码/解码
我正在用Pyaudio从麦克风捕获音频,并尝试用opus编解码器对其进行编码/解码。我正在使用SvartalF()制作的libopus绑定 这是我的密码:Python:PortAudio+;Opus编码/解码,python,portaudio,pyaudio,opus,Python,Portaudio,Pyaudio,Opus,我正在用Pyaudio从麦克风捕获音频,并尝试用opus编解码器对其进行编码/解码。我正在使用SvartalF()制作的libopus绑定 这是我的密码: import pyaudio from opus import encoder, decoder def streaming(p): chunk = 960 FORMAT = pyaudio.paInt16 CHANNELS = 1 RATE = 48000 streamin = p.open(for
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()
我必须把chunk*2
而不是chunk
放在data.append(streamin.read(chunk*2))
或DECDATA LENGTH==数据长度*2
中,我不知道为什么
产出:
DATA LENGTH : 384000
ENCDATA LENGTH : 12865
DECDATA LENGTH : 384000
在没有编码/解码的情况下,第一个streamout.write('''.join(data))
可以完美地工作。通过编码/解码,streamout.write(decdata)
可以正常工作,但有很多裂纹混入其中
我在这里做错了什么?这似乎是由python opus中解码方法中的错误引起的 根据opus_decode返回解码的样本数。python绑定假定它将完全填充它传入的结果缓冲区,因此每个解码样本集都会附加一个静默。这种沉默会导致低帧尺寸的裂缝和高帧尺寸的口吃。虽然文档中没有对此做任何说明,但返回的数字似乎是每个频道的 将行更改为以下选项可为我修复此问题:
return array.array('h', pcm[:result*channels]).tostring()
如果需要使用,解码浮点数方法可能需要相同的更改。只需将输出减半,然后取第一部分。 经过反复试验,我发现这个解决方案令人满意
from opus import decoder as opus_decoder
from opus import encoder as opus_encoder
class OpusCodec():
def __init__(self, *args, **kwargs):
self.chunk = 960
self.channels = 1
self.rate = 48000
self.encoder = opus_encoder.Encoder(
self.rate,
self.channels,
opus_encoder.APPLICATION_TYPES_MAP['voip']
)
self.decoder = opus_decoder.Decoder(
self.rate,
self.channels,
)
def encode(self, data, **kwargs):
if not 'frame_size' in kwargs:
kwargs['frame_size'] = self.chunk
out = self.encoder.encode(data, frame_size=self.chunk)
return out
def decode(self, data, **kwargs):
if not 'frame_size' in kwargs:
kwargs['frame_size'] = self.chunk
out = self.decoder.decode(data, **kwargs)
return out[0:int(len(out)/2)] # hackety hack :D
你好!我现在没有时间支持python opus,但是你可以提供它,这样我就可以用一个固定的版本更新PyPI repo了。那么你打算把输出减少一半吗?我怀疑这是个好主意。