async def run_until_complete(self) -> None: if self.is_started: raise StreamError("ffmpeg command already started") await self.start() if self.process is None: raise StreamError("Could not start stream") await asyncio.wait([ self._read_stream(self.process.stdout, "stdout"), self._read_stream(self.process.stderr, "stderr") ]) await self.process.wait()
def is_error(self) -> bool: if self.process is None: raise StreamError("ffmpeg has not started") if self.is_running: return False return self.process.returncode != 0
async def start(self) -> None: if self.is_started: raise StreamError("ffmpeg command already started") if self.ffmpeg_path is None: system_ffmpeg = await which("ffmpeg") if system_ffmpeg is None: raise StreamError("Could not find ffmpeg") self.ffmpeg_path = Path(system_ffmpeg) if not self.ffmpeg_path.exists(): raise StreamError("Could not find ffmpeg") self.process = await create_subprocess_exec(self.ffmpeg_path, *self.args, stdout=PIPE, stderr=PIPE)
async def play_audio(self, content_url: str, ffmpeg_path: Optional[Path] = None) -> None: """ Plays audio to a camera through its speaker. Requires ffmpeg to use. Args: * `content_url`: Either a URL accessible by python or a path to a file (ffmepg's `-i` parameter) * `ffmpeg_path`: Optional path to ffmpeg binary """ stream = self.create_talkback_stream(content_url, ffmpeg_path) await stream.run_until_complete() _LOGGER.debug("ffmpeg stdout:\n%s", "\n".join(stream.stdout)) _LOGGER.debug("ffmpeg stderr:\n%s", "\n".join(stream.stderr)) if stream.is_error: error = "\n".join(stream.stderr) raise StreamError("Error while playing audio (ffmpeg): \n" + error)
async def stop(self) -> None: if self.process is None: raise StreamError("ffmpeg has not started") self.process.kill() await self.process.wait()