Други, добрый день! Нужна помощь знатаков. Есть сервер генерации аудио потока по тексту (Разработка ЦРТ). Я ему запрос с текстом «Привет Мир!» а он мне по rtp играет мой текст. Этот сервак играет одновременно не более 10 потоков. У меня задача - закешировать rtp потоки. Написал сервер на python и заюзал gstreameer. Pipeline такие
play_rtp (когда не нашли в кеше текста, играем с сервака и кешируем)
caps такие: 'application/x-rtp,media=(string)audio, clock-rate=(int)8000, encoding-name=(string)PCMU, payload=(int)0'
udpsrc -> capsfilter(caps) -> tee -> queue -> udpsink - транслируем
+ -> queue -> rtppcmudepay -> mulawdec -> audioconvert -> audioresample -> lamemp3enc -> filesink - кешируем
play_file (когда нашли текст в кеше, играем из него)
здесь допом установлен mtu
filesrc -> mad -> audioconvert -> audioresample -> mulawenc -> rtppcmupay(mtu=172) -> udpsink
Проблема в том, что играю я все это в железку. Так первый pipeline проигрывается хорошо и сохраняется в файл. Второй (уже из файла) - проигрывается с некоторыми заиканиями... Я снял дамп на приемной стороне для обоих pipeline. Для первого каждый кадр всегда 172 байта. Во твором творился бардак от 10 до 1500 байт, в итоге, добавил параметр mtu = 172, качество проигрывания значительно улучшилось, но заикания все же есть. Дамп второго пайплайна показал 90% пакетов размером в 172 но есть и меньше (больших нет)... Подскажите, куда копать... может формат кеширования другой (пробовал с wav - еще хуже)
Вот код pipline
class Pipeline:
def __init__(self, *a, **kw):
self.pipeline = None
self.current_elem = None
@property
def elements(self):
''' has to be iterable '''
raise NotImplementedError()
def configure(self, pipeline):
self.current_elem = None
for element in self.elements:
pipeline.add(element)
if self.current_elem:
self.current_elem.link(element)
self.current_elem = element
return pipeline
def start(self):
self.pipeline = self.configure(Gst.Pipeline())
...
class PlayRtp(Pipeline):
log = logging.getLogger('Play')
caps = 'application/x-rtp,media=(string)audio, clock-rate=(int)8000, ' \
'encoding-name=(string)PCMU, payload=(int)0'
def __init__(self, in_host, in_port, out_host, out_port, tmp_path=None, *a, **kw):
super().__init__(*a, **kw)
self.in_host = in_host
self.in_port = in_port
self.out_host = out_host
self.out_port = out_port
self.tmp_path = tmp_path
@property
def elements(self):
udpsrc = Gst.ElementFactory.make('udpsrc', 'udpsrc')
udpsrc.set_property('address', self.in_host)
udpsrc.set_property('port', self.in_port)
yield udpsrc
capsfilter = Gst.ElementFactory.make('capsfilter', 'capsfilter')
capsfilter.set_property('caps', Gst.caps_from_string(self.caps))
yield capsfilter
udpsink = Gst.ElementFactory.make('udpsink', 'udpsink')
udpsink.set_property('host', self.out_host)
udpsink.set_property('port', self.out_port)
if self.tmp_path:
# transmit
tee = Gst.ElementFactory.make('tee', 'tee')
yield tee
yield Gst.ElementFactory.make('queue', 'udp_queue')
yield udpsink
# save
self.current_elem = tee
yield Gst.ElementFactory.make('queue', 'write_queue')
yield Gst.ElementFactory.make('rtppcmudepay', 'rtppcmudepay')
yield Gst.ElementFactory.make('mulawdec', 'mulawdec')
yield Gst.ElementFactory.make('audioconvert', 'audioconvert')
yield Gst.ElementFactory.make('audioresample', 'audioresample')
yield Gst.ElementFactory.make('lamemp3enc', 'lamemp3enc')
filesink = Gst.ElementFactory.make('filesink', 'filesink')
filesink.set_property('location', self.tmp_path)
yield filesink
else:
# transmit
yield udpsink
class PlayFile(Pipeline):
log = logging.getLogger('Play')
def __init__(self, host, port, path, mtu, *a, **kw):
super().__init__(*a, **kw)
self.host = host
self.port = port
self.path = path
self.mtu = mtu
@property
def elements(self):
filesrc = Gst.ElementFactory.make('filesrc', 'filesrc')
filesrc.set_property('location', self.path)
yield filesrc
yield Gst.ElementFactory.make('mad', 'mad')
yield Gst.ElementFactory.make('audioconvert', 'audioconvert')
yield Gst.ElementFactory.make('audioresample', 'audioresample')
yield Gst.ElementFactory.make('mulawenc', 'mulawenc')
rtppcmupay = Gst.ElementFactory.make('rtppcmupay', 'rtppcmupay')
rtppcmupay.set_property('mtu', self.mtu)
yield rtppcmupay
udpsink = Gst.ElementFactory.make('udpsink', 'udpsink')
udpsink.set_property('host', self.host)
udpsink.set_property('port', self.port)
yield udpsink