美文网首页
2018-09-13 DuerOS + Raspberry3B+

2018-09-13 DuerOS + Raspberry3B+

作者: 0db99e947190 | 来源:发表于2018-09-14 09:53 被阅读0次

    DuerOS的个人开发者版本在官方的介绍中已经停止申请, 代码也大半年没人更新了, 不过好在这个版本需要的麦克风阵列可以自行在网上购买, 相关的代码也是托管在Github上, 于是在研究了网上的各位大神的文章后, 终于把DuerOS运行起来了...

    选购硬件

    树莓派3B+: 网上到处有卖, 需要买相关的套件, 单独的板子是无法玩的.
    麦克风阵列: ReSpeaker树莓派4麦克风阵列扩展板

    烧录系统

    在树莓派上烧录raspbian-2018.4.18这个镜像. 千万不要烧录官网最新的镜像, 最新的镜像可能无法安装某些第三方库(比如pyaudio死活安装不了). 也不要安装DuerOS_For_Raspberry这个镜像, 因为这个镜像是针对Raspberry3B的, 3B+安装DuerOS这个镜像后会无法开机

    安装声卡驱动

    按照官方的文档去安装声卡驱动就行. 官方文档: http://wiki.seeedstudio.com/cn/ReSpeaker_4_Mic_Array_for_Raspberry_Pi/

    运行装DuerOS

    官方的文档: https://developer.baidu.com/forum/topic/show/244796?pageNo=1 安装完成后会有两个问题:

    1. 运行enter_trigger_start.sh 脚本, 服务器有回应但是没有声音
    2. 无法运行wakeup_trigger_start.sh 脚本

    解决第一个问题
    修改/home/pi/DUerOS-Python-Client/app/framework 目录下面的play.py文件

    # -*- coding: utf-8 -*-
    
    """
    基于GStreamer的播放模块
    """
    
    import gi
    import logging
    import app.app_config as app_config
    
    gi.require_version('Gst', '1.0')
    from gi.repository import Gst
    
    Gst.init(None)
    
    logging.basicConfig(level=app_config.LOGGER_LEVEL)
    logger = logging.getLogger(__file__)
    
    class Player(object):
        '''
        播放器实现类
        '''
    
        def __init__(self):
            # create a new gstreamer pipeline
            self.pipeline = Gst.Pipeline.new("mypipeline")
    
            # add a file source to the pipeline
            self.urisrc = Gst.ElementFactory.make("uridecodebin","source")
            self.urisrc.connect("pad-added", self.decode_link)
            self.pipeline.add(self.urisrc)
    
            # add a convertor to the pipeline
            self.convert = Gst.ElementFactory.make("audioconvert","convert")
            self.pipeline.add(self.convert)
    
            # add an alsa sink to the pipeline and link it to theconvertor
            self.sink = Gst.ElementFactory.make("alsasink", "sink")
            self.pipeline.add(self.sink)
            self.convert.link(self.sink)
    
            self.bus = self.pipeline.get_bus()
            self.bus.add_signal_watch()
            self.bus.enable_sync_message_emission()
    
        def decode_link(self, dbin, pad):
            pad.link(self.convert.get_static_pad("sink"))
    
    
        def play(self, uri):
            '''
            播放
            :param uri:播放资源地址
            :return:
            '''
            self.convert.unlink(self.sink)
            self.pipeline.set_state(Gst.State.NULL)
            
            # start playing
            logger.info('播放资源 uri: {}'.format(uri))
            self.urisrc.set_property("uri", uri)#'http://zhangmenshiting.qianqian.com/data2/music/067eaeefb2eb0498fe404edba700c6b1/599610520/599610520.mp3?xcode=d8bf0fee68258ce2350a5c038dd045b5')
            self.convert.link(self.sink)
            self.pipeline.set_state(Gst.State.PLAYING)
    
        def stop(self):
            '''
            停止
            :return:
            '''
            logger.info('停止')
            self.urisrc.unlink(self.convert)
            self.convert.unlink(self.sink)
            self.pipeline.set_state(Gst.State.NULL)
    
        def pause(self):
            '''
            暂停
            :return:
            '''
            logger.info('暂停')
            self.pipeline.set_state(Gst.State.PAUSED)
    
        def resume(self):
            '''
            回复播放
            :return:
            '''
            logger.info('回复播放')
            self.pipeline.set_state(Gst.State.PLAYING)
    
        def add_callback(self, name, callback):
            '''
            播放状态回调
            :param name: {eos, ...}
            :param callback: 回调函数
            :return:
            '''
            if not callable(callback):
                return
    
            def on_message(bus, message):
                callback()
    
            self.bus.connect('sync-message::{}'.format(name), on_message)
    
        @property
        def duration(self):
            '''
            播放时长
            :return:
            '''
            success, duration = self.pipeline.query_duration(Gst.Format.TIME)
            if success:
                return int(duration / Gst.MSECOND)
    
        @property
        def position(self):
            '''
            播放位置
            :return:
            '''
            success, position = self.pipeline.query_position(Gst.Format.TIME)
            if not success:
                position = 0
    
            return int(position / Gst.MSECOND)
    
        @property
        def state(self):
            '''
            播放状态
            :return:
            '''
            # GST_STATE_VOID_PENDING        no pending state.
            # GST_STATE_NULL                the NULL state or initial state of an element.
            # GST_STATE_READY               the element is ready to go to PAUSED.
            # GST_STATE_PAUSED              the element is PAUSED, it is ready to accept and process data.
            #                               Sink elements however only accept one buffer and then block.
            # GST_STATE_PLAYING             the element is PLAYING, the GstClock is running and the data is flowing.
            _, state, _ = self.pipeline.get_state(Gst.SECOND)
            return 'FINISHED' if state != Gst.State.PLAYING else 'PLAYING'
    
    

    修改/home/pi/DUerOS-Python-Client/app 目录下面的enter_trigger_main.py文件

    # -*- coding: utf-8 -*-
    '''
    通过输入[Enter]触发唤醒状态
    '''
    import logging
    from sdk.dueros_core import DuerOS
    
    from app.framework.mic import Audio
    from app.framework.player import Player
    from app.utils.prompt_tone import PromptTone
    
    logging.basicConfig(level=logging.INFO)
    
    
    def directive_listener(directive_content):
        '''
        云端下发directive监听器
        :param directive_content:云端下发directive内容
        :return:
        '''
        content = u'云端下发directive:%s' % (directive_content)
        logging.info(content)
    
    
    def main():
        # 创建录音设备(平台相关)
        audio = Audio()
        # 创建播放器(平台相关)
        player = Player()
    
        dueros = DuerOS(player)
        dueros.set_directive_listener(directive_listener)
    
        audio.link(dueros)
    
        dueros.start()
        audio.start()
    
        #prompt_tone_player = PromptTone()
    
        while True:
            try:
                try:
                    print '\n'
                    input('单击[Enter]建,然后发起对话\n')
                except SyntaxError:
                    pass
                # 唤醒态提示音
                #prompt_tone_player.play()
                dueros.listen()
            except KeyboardInterrupt:
                break
    
        dueros.stop()
        audio.stop()
    
    
    if __name__ == '__main__':
        main()
    
    

    解决第二个问题
    还未解决...

    相关文章

      网友评论

          本文标题:2018-09-13 DuerOS + Raspberry3B+

          本文链接:https://www.haomeiwen.com/subject/afmngftx.html