bug: RawImage.render() ACKs stall in packaged Windows app but work with flet run
Author: emannohCreated Sep 15, 2026Updated Sep 16, 2026
Labelsbug
Duplicate Check
- I have searched the opened issues and there are no duplicates
Describe the bug
Flet 0.86.5 RawImage.render() frame acknowledgements stall in a packaged Windows desktop app, while the identical app runs smoothly with flet run.
OpenCV capture remains at ~30–31 FPS in both cases. In the packaged app, await RawImage.render() frequently waits until ack_timeout=1.0 (~1.006 s per frame), while in the development/IDE app acknowledgements arrive normally.
A minimal standalone app containing only VideoCapture, one RawImage, a capture worker, and one async render loop reproduces the issue.
Code sample
Codeimport asyncio
import time
from pathlib import Path
import cv2
import flet as ft
LOG_FILE = Path.home() / "flet_rawimage_test.log"
def log(message: str):
with LOG_FILE.open("a", encoding="utf-8") as f:
f.write(f"{time.perf_counter():.3f}: {message}\n")
async def main(page: ft.Page):
page.title = "Flet RawImage Camera Test"
page.window.width = 900
page.window.height = 700
raw_image = ft.RawImage(
width=640,
height=480,
fit=ft.BoxFit.CONTAIN,
ack_timeout=1.0,
)
status = ft.Text("Camera stopped")
running = False
latest_frame = None
capture_task_running = False
async def render_loop():
nonlocal latest_frame
while True:
if not running:
await asyncio.sleep(0.05)
continue
frame = latest_frame
if frame is None:
await asyncio.sleep(0.001)
continue
# Consume the newest available frame.
latest_frame = None
started = time.perf_counter()
try:
await raw_image.render(
frame,
premultiplied=True,
)
except TimeoutError:
elapsed = time.perf_counter() - started
log(f"RENDER TIMEOUT after {elapsed:.3f} sec")
continue
except RuntimeError:
return
elapsed = time.perf_counter() - started
if elapsed >= 0.9:
log(f"ACK likely timed out: {elapsed:.3f} sec")
else:
log(f"ACK OK: {elapsed:.3f} sec")
def capture_loop():
nonlocal latest_frame
nonlocal capture_task_running
nonlocal running
capture_task_running = True
cap = cv2.VideoCapture(0)
# Change these if your camera doesn't support 640x480.
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
if not cap.isOpened():
log("ERROR: camera could not be opened")
running = False
capture_task_running = False
return
count = 0
fps_start = time.perf_counter()
try:
while running:
ret, frame = cap.read()
if not ret:
log("ERROR: cap.read() failed")
break
# Draw something so we know OpenCV processing is occurring.
cv2.line(
frame,
(0, 240),
(640, 240),
(0, 255, 0),
3,
)
cv2.line(
frame,
(320, 0),
(320, 480),
(0, 255, 0),
3,
)
# RawImage expects RGB rather than OpenCV's BGR.
frame = cv2.cvtColor(
frame,
cv2.COLOR_BGR2RGB,
)
# Drop old frames. The renderer always gets the newest one.
latest_frame = frame
count += 1
now = time.perf_counter()
if now - fps_start >= 1.0:
log(f"Captured FPS: {count}")
count = 0
fps_start = now
finally:
cap.release()
capture_task_running = False
log("Capture thread stopped")
async def toggle_camera(e):
nonlocal running
if not running:
LOG_FILE.write_text("", encoding="utf-8")
running = True
status.value = "Camera running"
toggle_button.content = "Stop camera"
page.update()
page.run_thread(capture_loop)
else:
running = False
status.value = "Camera stopped"
toggle_button.content = "Start camera"
page.update()
async def poke_ui(e):
"""
Intentionally unrelated UI activity. Noticed that this causes
the RawImage frames to update quicker.
"""
status.value = f"UI clicked at {time.perf_counter():.1f}"
page.update()
toggle_button = ft.Button(
"Start camera",
on_click=toggle_camera,
)
poke_button = ft.Button(
"Update unrelated UI",
on_click=poke_ui,
)
page.add(
ft.Row(
[
toggle_button,
poke_button,
]
),
status,
raw_image,
ft.Text(f"Log file: {LOG_FILE}"),
)
# One persistent render task for the lifetime of the page.
asyncio.create_task(render_loop())
if __name__ == "__main__":
ft.run(main)To reproduce
- Run the repro code using
flet run. Notice smooth video after clicking "Start camera" button. - Package app with
flet build windows. Notice laggy video after clicking "Start camera" button. Also notice quicker video update when repeatedly clicking "Update unrelated UI" button. - Open log file saved to home directory (flet_rawimage_test.py). Notice timeouts ~= 1 s, notice quicker updates when unrelated button clicked.
Expected behavior
Smooth video updates in the packaged app
Screenshots / Videos
Captures[Upload media here]
Operating System
Windows
Operating system details
Windows 11
Flet version
0.86.5
Regression
I'm not sure / I don't know
Suggestions
No response
Logs
Logs[Paste your logs here]Additional details
No response
Source: flet-dev/flet