Как использовать pocketsphinx (5prealpha) с gstreamer-1.0 в python?

Я пытаюсь создать небольшой скрипт Python, который будет получать аудиопоток по сети, подавать его через pocketspinx для перевода речи в текст и запускать некоторые команды в зависимости от вывода pocketsphinx.

Я установил sphinxbase и pocketsphinx (5prealpha) на Ubuntu 15.10 vm и могу правильно обрабатывать содержимое примера аудиофайла (часть установки pocketsphinx) в Python. Поэтому я уверен, что моя установка sphinx работает правильно. К сожалению, тестовый скрипт python не может обрабатывать непрерывный звук и использует собственный API-интерфейс pocketsphinx. Согласно веб-сайту cmusphinx, я должен использовать gstreamer для непрерывного перевода. К сожалению, информация о том, как использовать pocketsphinx с gstreamer в Python, довольно ограничена. На основе примеров, которые я смог найти, я собрал следующий сценарий.

import gi gi.require_version('Gst', '1.0') from gi.repository import GObject, Gst GObject.threads_init() Gst.init(None) def element_message( bus, msg ): msgtype = msg.get_structure().get_name() if msgtype != 'pocketsphinx': return print "hypothesis= '%s' confidence=%s\n" % (msg.get_structure().get_value('hypothesis'), msg.get_structure().get_value('confidence')) pipeline = Gst.parse_launch('udpsrc port=3000 name=src caps=application/x-rtp ! rtppcmadepay name=rtpp ! alawdec name=decoder ! queue ! pocketsphinx name=asr ! fakesink') asr = pipeline.get_by_name("asr") asr.set_property("configured", "true") bus = pipeline.get_bus() bus.add_signal_watch() bus.connect('message::element', element_message) pipeline.set_state(Gst.State.PLAYING) # enter into a mainloop loop = GObject.MainLoop() loop.run() 

Отправляющая сторона выглядит так:

 import gobject, pygst pygst.require("0.10") import gst pipeline = gst.parse_launch('alsasrc ! audioconvert ! audioresample ! alawenc ! rtppcmapay ! udpsink port=3000 host=192.168.13.120') pipeline.set_state(gst.STATE_PLAYING) loop = gobject.MainLoop() loop.run() 

Это должно получить поток udp из сети, вставить его в pocketsphinx и распечатать вывод на терминал. Если я заменю 'очередь! pocketsphinx! fakesink 'by wavenc! filesink ', я получаю действительный звуковой файл с правильным контентом, поэтому я знаю, что часть отправки по сети работает правильно. (У меня нет звука на тестовой машине, поэтому я не могу протестировать локальный аудиоисточник).

Когда я запускаю скрипт, я вижу конфигурацию pocketspinx, но скрипт больше ничего не делает. Когда я запускаю скрипт с GST_DEBUG = *: 4, я вижу следующий вывод:

 0:00:04.789157687 2220 0x86fff70 INFO GST_EVENT gstevent.c:760:gst_event_new_segment: creating segment event time segment start=0:00:00.000000000, offset=0:00:00.000000000, stop=99:99:99.999999999, rate=1.000000, applied_rate=1.000000, flags=0x00, time=0:00:00.000000000, base=0:00:00.000000000, position 0:00:00.000000000, duration 99:99:99.999999999 0:00:04.789616981 2220 0x86fff70 INFO basesrc gstbasesrc.c:2838:gst_base_src_loop:<src> marking pending DISCONT 0:00:04.789995780 2220 0x86fff70 INFO GST_EVENT gstevent.c:760:gst_event_new_segment: creating segment event time segment start=0:00:00.000000000, offset=0:00:00.000000000, stop=99:99:99.999999999, rate=1.000000, applied_rate=1.000000, flags=0x00, time=0:00:00.000000000, base=0:00:00.000000000, position 0:00:04.079311489, duration 99:99:99.999999999 0:00:04.790420834 2220 0x86fff70 INFO GST_EVENT gstevent.c:679:gst_event_new_caps: creating caps event audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)8000, channels=(int)1 0:00:04.790851965 2220 0x86fff70 WARN GST_PADS gstpad.c:3989:gst_pad_peer_query:<decoder:src> could not send sticky events 0:00:04.791258320 2220 0x86fff70 WARN basesrc gstbasesrc.c:2943:gst_base_src_loop:<src> error: Internal data flow error. 0:00:04.791572605 2220 0x86fff70 WARN basesrc gstbasesrc.c:2943:gst_base_src_loop:<src> error: streaming task paused, reason not-negotiated (-4) 0:00:04.791917073 2220 0x86fff70 INFO GST_ERROR_SYSTEM gstelement.c:1837:gst_element_message_full:<src> posting message: Internal data flow error. 0:00:04.792305347 2220 0x86fff70 INFO GST_ERROR_SYSTEM gstelement.c:1860:gst_element_message_full:<src> posted error message: Internal data flow error. 0:00:04.792633841 2220 0x86fff70 INFO task gsttask.c:315:gst_task_func:<src:src> Task going to paused 

Я не понимаю, что происходит неправильно на основе информации и примеров, которые я нашел в Google.

Любая помощь будет высоко оценен.

Нико

Элементу Gstreamer требуется 16000 кГц аудио, вы пытаетесь передать 8000. Вам нужно будет изменить источники pocketsphinx, чтобы включить 8000 в элементе pocketsphinx. Вам необходимо обновить спецификацию элемента, параметр конфигурации samprate для pocketsphinx и акустическую модель.

В качестве альтернативы вам необходимо отправить широкополосный аудио через сеть. В этом случае вы не должны использовать alaw-кодек.

Оказалось, что это немного скрипка, чтобы правильно настроить трубопровод gstreamer. Поскольку Николай указал, что pocketsphinx 5 по умолчанию требует звука 16000 кГц, к сожалению передача 16000 кГц по сети с gstreamer не была прямой (для меня). Поэтому, если вы, похоже, ищете нечто похожее, вот что сработало для меня в конце:

Сторона отправки:

 import gi gi.require_version('Gst', '1.0') from gi.repository import GObject, Gst GObject.threads_init() Gst.init(None) pipeline = Gst.parse_launch('alsasrc ! audioconvert ! audio/x-raw,channels=1,depth=16,width=16,rate=16000 ! rtpL16pay ! udpsink port=3000 host=192.168.13.120') pipeline.set_state(Gst.State.PLAYING) loop = GObject.MainLoop() loop.run() 

Принимающая сторона:

 import gi gi.require_version('Gst', '1.0') from gi.repository import GObject, Gst GObject.threads_init() Gst.init(None) def element_message( bus, msg ): msgtype = msg.get_structure().get_name() print "hypothesis= '%s' confidence=%s\n" % (msg.get_structure().get_value('hypothesis'),msg.get_structure().get_value('confidence')) pipeline = Gst.parse_launch('udpsrc port=3000 name=src ! application/x-rtp,media=(string)audio, clock-rate=(int)16000, width=16, height=16, encoding-name=(string)L16, encoding-params=(string)1, channels=(int)1, channel-positions=(int)1, payload=(int)96 ! rtpL16depay ! audioconvert ! pocketsphinx name=asr ! fakesink') asr = pipeline.get_by_name("asr") asr.set_property("dict", "/usr/local/share/pocketsphinx/model/en-us/cmudict-en-us.dict") asr.set_property("lm","/usr/local/share/pocketsphinx/model/en-us/en-us.lm.bin") asr.set_property("hmm","/usr/local/share/pocketsphinx/model/en-us/en-us/") asr.set_property("configured", "true") bus = pipeline.get_bus( bus.add_signal_watch() bus.connect('message::element', element_message) pipeline.set_state(Gst.State.PLAYING) loop = GObject.MainLoop()