respeaker / avs

python implementation of alexa voice service app, 支持DuerOS
Other
195 stars 63 forks source link

Send pre recorded audio files to Alexa #32

Closed sradmard closed 5 years ago

sradmard commented 5 years ago

Hi, I am planning to send pre-recorded audio files to Alexa in addition to sending stream of audio input through the microphone. It looks like this is not supported at the moment. I would appreciate any hint on that. I think the file that I need to start modifying is the speech_recognizer.py, is that correct?

I have found this package that claims to send pre-recorded audio files to Alexa: https://github.com/richtier/alexa-voice-service-client but I would like to add such functionality to the avs package.

xiongyihui commented 5 years ago

It's actually very simple using voice-engine package with this package to implement it.

"""
pre-requirements
    pip install voice-engine avs
"""

import time
import logging
from voice_engine.file_source import Source
from voice_engine.channel_picker import ChannelPicker
from voice_engine.kws import KWS
from avs.alexa import Alexa

logging.basicConfig(level=logging.DEBUG)

def main():
    if len(sys.argv) < 2:
        print('Usage: {} audio.wav')
        sys.exit(1)

    src = Source(sys.argv[1])
    ch0 = ChannelPicker(channels=src.channels, pick=0)
    kws = KWS(model='alexa')
    alexa = Alexa()

    src.link(kws)
    kws.link(alexa)

    def on_detected(keyword):
        logging.info('detected {}'.format(keyword))
        alexa.listen()

    kws.set_callback(on_detected)

    src.recursive_start()

    while True:
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            break

    src.recursive_stop()

if __name__ == '__main__':
main()
sradmard commented 5 years ago

@xiongyihui thank you so much for your response. I am currently using Picovoice/Porcupine as my wake-up-word detector, and I am using the followings to be able to connect to Alexa.

audio = Audio()
alexa = Alexa()
audio.link(alexa)
...

> after my wake-up-word is detected, then:

alexa.listen()

Now with your hints, I have added the followings:

src=Source('custom_alexa_app_name.wav')
audio = Audio()
alexa = Alexa()
audio.link(alexa)
src.link(alexa)
...

> after my wake-up-word is detected, then:

alexa.listen()
src.recursive_start()

I do the src.recursive_stop() in my KeyboardInterrupt Exception. Now everything is working and I can call on my custom app directly without having to use its name. However, this only works for the first time that the wake-up-word is detected. It looks like as if src.recursive_start() only sends the .wav file the first time it is called. After the first time detection of the wake-up-word, I do not get any response from my custom app, which means I cannot send the .wav file anymore. I have also used src.start(), but it worked almost the same. I would appreciate any further hints on this matter.

sradmard commented 5 years ago

I found a way that it is working for me now and I thought it might be useful for others to share it here. Basically I had to just initialize Alexa at the beginning and then move majority of the calls to after my wake-up-word is detected. Something like this:

alexa = Alexa(config)
alexa.start()

after my wake_up_word is detected every time then:

src = Source(audio_file,1024) 
src.link(self.alexa)
alexa.listen()
src.start()