Azure STT via EAGI Works, But AGI Commands Fail After Audio Streaming from FD 3

I’m using EAGI to stream audio from Asterisk to Azure’s Speech-to-Text service via Python. The audio is streamed successfully using file descriptor 3, and Azure returns recognized speech as expected.

However, after the stream starts from FD 3, no AGI commands work — including basic ones like stream_file, even though they worked right before the audio streaming started.

I’ve already confirmed:

  • agi = AGI() is initialized at the start.
  • self.agi._sock is valid before and after streaming.
  • No errors are thrown, but AGI commands silently fail after FD 3 is opened and read from.

It feels like reading from fd=3 blocks or kills the AGI command socket. Is this a known behavior or limitation in Asterisk’s EAGI implementation? Would love to hear if anyone has encountered and solved this!

import os
import time
import logging
import azure.cognitiveservices.speech as speechsdk
from asterisk.agi import AGI

class MySpeechHandler:
    def __init__(self):
        self.agi = AGI()
        self.speech_config = speechsdk.SpeechConfig(subscription="XXXX", region="centralindia")

    def process(self, node):
        logging.info("Initializing speech recognition")

        # Azure audio format
        audio_format = speechsdk.audio.AudioStreamFormat(
            samples_per_second=8000, bits_per_sample=16, channels=1
        )
        push_stream = speechsdk.audio.PushAudioInputStream(audio_format)
        audio_config = speechsdk.audio.AudioConfig(stream=push_stream)

        speech_recognizer = speechsdk.SpeechRecognizer(
            speech_config=self.speech_config,
            audio_config=audio_config
        )

        recognized_text = ""
        matched_node = None

        def on_recognized(evt):
            nonlocal recognized_text, matched_node
            recognized_text = evt.result.text.lower()
            print(f"RECOGNIZED: {evt.result.text}")
            for phrase, target_node in node.phrases.items():
                if phrase.lower() in recognized_text:
                    matched_node = target_node

        speech_recognizer.recognized.connect(on_recognized)

        # 🔊 This AGI command works fine before streaming:
        self.agi.stream_file("demo-welcome", [])

        # Start recognition
        audio_file = os.fdopen(3, 'rb')  # EAGI audio input
        speech_recognizer.start_continuous_recognition()

        start_time = time.time()
        while time.time() - start_time < 10:
            data = audio_file.read(1024)
            if not data:
                break
            push_stream.write(data)
            if matched_node:
                break

        audio_file.close()
        push_stream.close()
        speech_recognizer.stop_continuous_recognition()

        # 🔇 This AGI command doesn't work after audio streaming begins:
        self.agi.stream_file("demo-congrats", [])  # Doesn't play anything

        logging.info("Done processing")

# Usage
handler = MySpeechHandler()
handler.process(node)  # `node` contains prompt and phrases to match

:white_check_mark: What I’ve Tried:

  • Confirmed self.agi._sock is alive.
  • Ensured no exceptions from AGI commands.
  • Tried reading with different buffer sizes and durations.

:red_question_mark: What I Need Help With:

  • Is this expected behavior in Asterisk EAGI?
  • Can AGI and FD 3 read coexist?
  • Any workarounds to allow AGI commands after audio streaming?