feat: add step-by-step visual replay and harden process lifecycle

- UI: Implement dual-mode playback in FloatingVideoPlayer supporting video and step-by-step frame replay with scrub controls and auto-fallback
- Runtime: Prevent asyncio event loop hangs on Darwin and Linux by avoiding psutil.wait_procs on direct child processes
- Task Queue: Add worker exit watchdog and automatic recording recovery for completed or interrupted sessions
- Recording: Add ffmpeg ultrafast transcode fallback, shield recording finalization against cancellation, and handle on-the-fly MP4 conversion
- Docs: Polish README_CN styling and streamline flash runner agent prompt
This commit is contained in:
somew1nd committed 2026-08-26 00:53:24 -07:00
1 parent 06643e955b
commit a36a66ce6d
26 files changed
+1152 -117

No files matched your search

@@ -176,6 +176,48 @@
gap: 4px;
flex-shrink: 0;
.mode-toggle-group {
display: flex;
align-items: center;
background: rgba(241, 245, 249, 0.7);
backdrop-filter: blur(12px);
border: 1px solid rgba(226, 232, 240, 0.85);
border-radius: 8px;
padding: 2px;
margin-right: 4px;
gap: 2px;
.mode-btn {
display: inline-flex;
align-items: center;
gap: 3px;
border: none;
background: transparent;
color: #475569;
font-size: 11px;
font-weight: 600;
padding: 2px 7px;
border-radius: 6px;
cursor: pointer;
transition: all 0.15s ease;
.mode-icon {
font-size: 13px;
}
&:hover:not(.active) {
color: #0f172a;
background: rgba(255, 255, 255, 0.8);
}
&.active {
background: #0284c7;
color: #ffffff;
box-shadow: 0 1px 3px rgba(2, 132, 199, 0.3);
}
}
}
.speed-pill-group {
display: flex;
align-items: center;
@@ -185,8 +227,6 @@
border-radius: 8px;
padding: 2px;
margin-right: 4px;
padding: 2px;
margin-right: 4px;
.speed-btn {
border: none;
@@ -370,6 +410,98 @@
}
}
.step-replay-container {
display: flex;
flex-direction: column;
background: #000000;
position: relative;
width: 100%;
overflow: hidden;
.step-replay-notice {
display: flex;
align-items: center;
gap: 6px;
background: rgba(254, 243, 199, 0.95);
color: #92400e;
padding: 6px 12px;
font-size: 11.5px;
font-weight: 500;
border-bottom: 1px solid rgba(245, 158, 11, 0.3);
.notice-icon {
font-size: 14px;
color: #d97706;
flex-shrink: 0;
}
}
.step-image-viewport {
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: #0a0a0c;
min-height: 240px;
max-height: 520px;
cursor: pointer;
overflow: hidden;
.step-frame-img {
max-width: 100%;
max-height: 520px;
width: auto;
height: auto;
object-fit: contain;
display: block;
user-select: none;
transition: opacity 0.15s ease;
&:hover {
opacity: 0.96;
}
}
.step-frame-badge {
position: absolute;
bottom: 12px;
left: 12px;
right: 12px;
display: flex;
align-items: center;
gap: 6px;
background: rgba(15, 23, 42, 0.84);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
border-radius: 8px;
padding: 6px 10px;
color: #ffffff;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.45);
pointer-events: none;
animation: fadeIn 0.2s ease;
.badge-step-no {
font-size: 11px;
font-weight: 700;
background: #0284c7;
padding: 1px 6px;
border-radius: 4px;
letter-spacing: 0.2px;
flex-shrink: 0;
}
.badge-action-desc {
font-size: 11.5px;
font-weight: 500;
color: #f8fafc;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
.video-container {
position: relative;
width: 100%;