WhyDoYouDie
WhyDoYouDie

Reputation: 45

How to use filediscriptor 3 to stream audio to dialogflow

I currently use asterisk record to capture audio in a file and use the file to stream the audio to dialogflow to detect intents. I want to change this to streaming the audio directly instead of recording it first. I changed my script to a EAGI script so the audio would be available on file descriptor 3, however i have no expirience with file descriptors so i'm not sure how they work or how i should change my code to make it work so i could use some help. Below is the code i currently have which uses a file to stream the audio to dialogflow ( with hardcoded codec ).

agi = AGI()
sesionId = agi.get_variable('caller')
channelId = agi.get_variable('channelId')

def detect_intent_audio():
    project_id = "fake-219706"
    session_id = sesionId
    language_code = lang
    filename = channelId + "" + sesionId + ".sln16"
    audio_file_path = "/var/lib/asterisk/sounds/%(s)s"%{'s':filename}
    import dialogflow_v2 as dialogflow

    """Returns the result of detect intent with streaming audio as input.

    Using the same `session_id` between requests allows continuation
    of the conversaion."""
    session_client = dialogflow.SessionsClient()

    # Note: hard coding audio_encoding and sample_rate_hertz for simplicity.
    audio_encoding = dialogflow.enums.AudioEncoding.AUDIO_ENCODING_LINEAR_16
    sample_rate_hertz = 16000

    session_path = session_client.session_path(project_id, session_id)

    def request_generator(audio_config, audio_file_path):
        query_input = dialogflow.types.QueryInput(audio_config=audio_config)

        # The first request contains the configuration.
        yield dialogflow.types.StreamingDetectIntentRequest(
            session=session_path, query_input=query_input)

        # Here we are reading small chunks of audio data from a local
        # audio file.  In practice these chunks should come from
        # an audio input device.
        with open(audio_file_path, 'rb') as audio_file:
            while True:
                chunk = audio_file.read(4096)
                if not chunk:
                    break
                # The later requests contains audio data.
                yield dialogflow.types.StreamingDetectIntentRequest(
                    input_audio=chunk)

    audio_config = dialogflow.types.InputAudioConfig(
        audio_encoding=audio_encoding, language_code=language_code,
        sample_rate_hertz=sample_rate_hertz)

    requests = request_generator(audio_config, audio_file_path)
    responses = session_client.streaming_detect_intent(requests)

    print('=' * 20)
    for response in responses:
        print('Intermediate transcript: "{}".'.format(
                response.recognition_result.transcript))
      agi.verbose("count")
    # Note: The result from the last response is the final transcript along
    # with the detected content.
    query_result = response.query_result

    print('=' * 20)
    print('Query text: {}'.format(query_result.query_text))
    print('Detected intent: {} (confidence: {})\n'.format(
        query_result.intent.display_name,
        query_result.intent_detection_confidence))
    print('Fulfillment text: {}\n'.format(
        query_result.fulfillment_text))
    return response

Upvotes: 0

Views: 1264

Answers (1)

Camilo Gutierrez
Camilo Gutierrez

Reputation: 41

First, you can open your file descriptor this way:

File Descriptor delivery in Asterisk

FD=3

Open File Descriptor

file=os.fdopen(FD, 'rb')

Probably you will get an error that says the file is longer than 60 seconds. Try modifying the following line as follows: (The single_utterance property allows google to handle the audio input)

yield dialogflow.types.StreamingDetectIntentRequest(
      session=session_path, query_input=query_input, single_utterance=True)

And finally you don't have to re-open the file on the while statement, instead simply use:

while True:
            chunk = file.read(4096)
            if not chunk:
                break
            # The later requests contains audio data.
            yield dialogflow.types.StreamingDetectIntentRequest(
                input_audio=chunk)

Upvotes: 0

Related Questions