Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -941,19 +941,15 @@ async def handle_action(ws: WebSocket, msg: dict, sess: dict):
|
|
| 941 |
|
| 942 |
async def _safe_capture(scale, quality, force_mx=None, force_my=None):
|
| 943 |
"""
|
| 944 |
-
تُستخدم من shot_bg (التلقائية) — تنتظر القفل
|
| 945 |
-
ت
|
|
|
|
|
|
|
| 946 |
"""
|
| 947 |
-
async
|
| 948 |
-
|
| 949 |
-
|
| 950 |
-
|
| 951 |
-
)
|
| 952 |
-
try:
|
| 953 |
-
return await asyncio.wait_for(_do_capture(), timeout=25)
|
| 954 |
-
except asyncio.TimeoutError:
|
| 955 |
-
print(f"[shot:{display}] ⚠️ capture timed out after 25s — skipping this frame")
|
| 956 |
-
return {"data": "", "width": 1920, "height": 1080, "mouse_x": 0, "mouse_y": 0}
|
| 957 |
|
| 958 |
async def _priority_capture(scale, quality, force_mx=None, force_my=None):
|
| 959 |
"""
|
|
@@ -961,27 +957,23 @@ async def handle_action(ws: WebSocket, msg: dict, sess: dict):
|
|
| 961 |
تحاول الحصول على القفل لمدة قصيرة (1 ثانية) فقط؛ إن لم تنجح (القفل
|
| 962 |
محجوز من shot_bg تلقائية بطيئة)، تُنفَّذ التصوير فوراً بدون قفل بدل
|
| 963 |
الانتظار خلف عملية أخرى — العميل يجب أن يحصل على رد سريع دائماً.
|
|
|
|
|
|
|
| 964 |
"""
|
| 965 |
try:
|
| 966 |
await asyncio.wait_for(_shot_lock.acquire(), timeout=1.0)
|
| 967 |
try:
|
| 968 |
-
return await asyncio.
|
| 969 |
-
|
| 970 |
-
timeout=20
|
| 971 |
)
|
| 972 |
finally:
|
| 973 |
_shot_lock.release()
|
| 974 |
except asyncio.TimeoutError:
|
| 975 |
-
# لم نحصل على القفل بسرعة كافية
|
| 976 |
-
#
|
| 977 |
-
|
| 978 |
-
|
| 979 |
-
|
| 980 |
-
timeout=20
|
| 981 |
-
)
|
| 982 |
-
except asyncio.TimeoutError:
|
| 983 |
-
print(f"[shot:{display}] ⚠️ priority capture timed out — skipping this frame")
|
| 984 |
-
return {"data": "", "width": 1920, "height": 1080, "mouse_x": 0, "mouse_y": 0}
|
| 985 |
|
| 986 |
async def shot_bg(label: str = "", delay: float = 0.5,
|
| 987 |
force_mx: int | None = None, force_my: int | None = None,
|
|
|
|
| 941 |
|
| 942 |
async def _safe_capture(scale, quality, force_mx=None, force_my=None):
|
| 943 |
"""
|
| 944 |
+
تُستخدم من shot_bg (التلقائية) — تنتظر القفل ثم تنتظر التقاط الشاشة
|
| 945 |
+
حتى ينتهي فعلياً، بدون أي سقف زمني يقطعها. هذا يضمن أن العملية لن
|
| 946 |
+
تُقطع أبداً في منتصفها وتُرجع فراغاً؛ ستكمل حتى تنجح (أو تفشل كل
|
| 947 |
+
المحاولات الداخلية في capture_with_grid وتُرجع placeholder صريح).
|
| 948 |
"""
|
| 949 |
+
async with _shot_lock:
|
| 950 |
+
return await asyncio.to_thread(
|
| 951 |
+
capture_with_grid, display, scale, quality, force_mx, force_my
|
| 952 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 953 |
|
| 954 |
async def _priority_capture(scale, quality, force_mx=None, force_my=None):
|
| 955 |
"""
|
|
|
|
| 957 |
تحاول الحصول على القفل لمدة قصيرة (1 ثانية) فقط؛ إن لم تنجح (القفل
|
| 958 |
محجوز من shot_bg تلقائية بطيئة)، تُنفَّذ التصوير فوراً بدون قفل بدل
|
| 959 |
الانتظار خلف عملية أخرى — العميل يجب أن يحصل على رد سريع دائماً.
|
| 960 |
+
بعد الحصول على القفل (أو تجاوزه)، لا يوجد أي سقف زمني على عملية
|
| 961 |
+
الالتقاط نفسها — تنتظر حتى تكتمل فعلياً بدل أن تُقطع في المنتصف.
|
| 962 |
"""
|
| 963 |
try:
|
| 964 |
await asyncio.wait_for(_shot_lock.acquire(), timeout=1.0)
|
| 965 |
try:
|
| 966 |
+
return await asyncio.to_thread(
|
| 967 |
+
capture_with_grid, display, scale, quality, force_mx, force_my
|
|
|
|
| 968 |
)
|
| 969 |
finally:
|
| 970 |
_shot_lock.release()
|
| 971 |
except asyncio.TimeoutError:
|
| 972 |
+
# لم نحصل على القفل بسرعة كافية — ننفّذ التصوير مباشرة بدون قفل
|
| 973 |
+
# بدل الانتظار خلف عملية أخرى، لكن بدون أي سقف زمني على الالتقاط
|
| 974 |
+
return await asyncio.to_thread(
|
| 975 |
+
capture_with_grid, display, scale, quality, force_mx, force_my
|
| 976 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 977 |
|
| 978 |
async def shot_bg(label: str = "", delay: float = 0.5,
|
| 979 |
force_mx: int | None = None, force_my: int | None = None,
|