From 633a4d4c58bcef03246be08ba92081bedd33c184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleix=20Conchillo=20Flaqu=C3=A9?= Date: Fri, 14 Feb 2025 15:42:05 -0800 Subject: [PATCH] FalImageGenService: load image async to not block the event loop --- CHANGELOG.md | 3 +++ src/pipecat/services/fal.py | 14 +++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5542674ec..c8590e665 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,6 +105,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed a `FalImageGenService` issue that was causing the event loop to be + blocked while loading the downloadded image. + - Fixed a `CartesiaTTSService` service issue that would cause audio overlapping in some cases. diff --git a/src/pipecat/services/fal.py b/src/pipecat/services/fal.py index d229861f1..7173861ab 100644 --- a/src/pipecat/services/fal.py +++ b/src/pipecat/services/fal.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: BSD 2-Clause License # +import asyncio import io import os from typing import AsyncGenerator, Dict, Optional, Union @@ -53,6 +54,11 @@ class FalImageGenService(ImageGenService): os.environ["FAL_KEY"] = key async def run_image_gen(self, prompt: str) -> AsyncGenerator[Frame, None]: + def load_image_bytes(encoded_image: bytes): + buffer = io.BytesIO(encoded_image) + image = Image.open(buffer) + return (image.tobytes(), image.size, image.format) + logger.debug(f"Generating image from prompt: {prompt}") response = await fal_client.run_async( @@ -73,10 +79,8 @@ class FalImageGenService(ImageGenService): logger.debug(f"Downloading image {image_url} ...") async with self._aiohttp_session.get(image_url) as response: logger.debug(f"Downloaded image {image_url}") - image_stream = io.BytesIO(await response.content.read()) - image = Image.open(image_stream) + encoded_image = await response.content.read() + (image_bytes, size, format) = await asyncio.to_thread(load_image_bytes, encoded_image) - frame = URLImageRawFrame( - url=image_url, image=image.tobytes(), size=image.size, format=image.format - ) + frame = URLImageRawFrame(url=image_url, image=image_bytes, size=size, format=format) yield frame