def __init__(self) -> None:
        """
        Assign the speech recognition object and start the audio handling thread
        """
        self.__listener = sr.Recognizer()
        __audio_proc = Thread(target=self.__outputHandler)
        __audio_proc.start()

        # Remove stragglers to avoid corruption exceptions
        temp_storage_dir = path.dirname(Configuration.GetFilePath("temp_microphone_storage"))
        for file in listdir(temp_storage_dir):
            remove(os.path.join(path.dirname(Configuration.GetFilePath("temp_microphone_storage")), file))
    def setOutput(self, text: str) -> None:
        """
        Set audio output for handler to speak
        :param text: output text
        :return: None
        """
        self.__output_stack.append(text)
        base_dir = path.dirname(Configuration.GetFilePath("temp_microphone_storage"))
        output_path = Configuration.GetFilePath("temp_microphone_storage").format(audio_id=len([file for file in
                                                                                                listdir(base_dir) if
                                                                                                path.isfile(
                                                                                                    path.join(base_dir,
                                                                                                              file))]))

        language = Configuration.Get("language")
        out = gTTS(text, lang=language)
        out.save(output_path)
    def start(self, render: bool = True) -> None:
        """
        Currently doesnt do a lot except for starting render,
        placeholder if more startup functionality is required.
        """

        if render:
            self.__render(Configuration.GetFilePath("video_output_location"))
    def __outputHandler(self) -> None:
        """
        Output handling thread
        :return: None
        """
        base_dir = path.dirname(Configuration.GetFilePath("temp_microphone_storage"))

        while True:
            for file in [path.join(base_dir, file) for file in listdir(base_dir) if
                         path.isfile(path.join(base_dir, file))]:
                try:
                    playsound.playsound(file)
                except playsound.PlaysoundException as e:
                    print(f"Playback error: {e}")

                if path.exists(file):
                    try:
                        remove(file)
                    except PermissionError as e:
                        continue

            time.sleep(1)
    def __faceTrack(self, frame, encodings, write_process,
                    output_location) -> cv2.VideoWriter:
        """
        Track faces upon a frame
        :param frame: target frame
        :param encodings: known encodings
        :param write_process: (un)active write process
        :param output_location: output for writing process
        :return: updated writing process
        """
        rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        locations = face_recognition.face_locations(rgb_frame)
        found_names = []

        try:
            for encoding in face_recognition.face_encodings(
                    rgb_frame, locations):
                name = None
                match = None
                for set_name in encodings.keys():
                    match = face_recognition.compare_faces(encodings[set_name],
                                                           encoding,
                                                           tolerance=0.50)
                    if match[0]:
                        name = set_name
                        break
                    self.__lastDetectedTime = datetime.now()

                found_names.append(name)

        except Exception as e:
            print("Error parsing face name: ", e)

        try:
            for (top, right, bottom,
                 left), name in zip(locations, found_names):
                cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 0),
                              2)
                cv2.rectangle(frame, (left, bottom), (right, bottom),
                              (0, 0, 0), cv2.FILLED)
                font = cv2.FONT_HERSHEY_DUPLEX
                name = name if name is not None else "Unkown"
                cv2.putText(frame, name, (left + 6, bottom - 6), font, 0.5,
                            (255, 255, 255), 1)

                if self.__extractKnownFaces:
                    frame_slice = rgb_frame[top:bottom, left:right]
                    file_path = os.path.join(
                        Configuration.GetFilePath("know_face_encodings"), name)
                    if not os.path.exists(file_path):
                        os.mkdir(file_path)

                    Image.fromarray(frame_slice).save(
                        os.path.join(file_path,
                                     f"{len(os.listdir(file_path))}.png"))

        except Exception as e:
            print("Error setting face rect: ", e)

        if locations and write_process is None:
            try:
                day_dir, timestamp = f'{re.sub(r"[-.:]", "_", str(datetime.now()))}'.split(
                    " ")
                base_dir = os.path.dirname(
                    os.path.dirname(os.path.abspath(output_location)))
                if day_dir not in os.listdir(base_dir):
                    os.mkdir(
                        os.path.dirname(
                            output_location.format(directory=day_dir,
                                                   timestamp="")))

                write_process = cv2.VideoWriter(
                    output_location.format(directory=day_dir,
                                           timestamp=timestamp),
                    cv2.VideoWriter_fourcc(*'XVID'), 30.0, (640, 480))
            except Exception as e:
                print(e)
        elif len(locations) == 0 and write_process is not None:
            write_process = None

        return write_process