feat(screencast): 自动激活窗口 / 多显示器 / 字幕独立时长

基于 SDK 新模块(前两个 commit)的 screencast 工具能力升级:

- runner.py:
  · 新增 activate_window: bool = True 参数,录屏前自动调
    activate_and_maximize_jiangchang_window,避免开头几秒录到 PowerShell/桌面
  · 新增 monitor_index: Optional[int] = None 参数,透传给 ScreenRecorder
  · 自带 SDK 路径兜底 _ensure_sdk_on_path,让 record_screencast.py 直接 python
    跑时(不走 pytest conftest)也能 import jiangchang_desktop_sdk.window_win32

- recorder.py:
  · ScreenRecorder.__init__ 加 monitor_index 参数
  · _capture_loop 用 idx 选 monitor,越界兜底到 0
  · None = 旧行为(monitors[0] 所有屏合并),1 = 主屏,2+ = 第 N 屏
  · 多显示器场景推荐显式传 monitor_index=1 避免录出半边空白

- subtitle.py:
  · SubtitleEngine.process_line 支持二元组(兼容旧脚本)和三元组(每条独立 duration)
  · 长等待场景可以让某条字幕停留更久(如 30s)覆盖中间无日志的"字幕真空"

所有改动向后兼容,全部新增参数有默认值。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-25 11:14:11 +08:00
parent 311441dab0
commit 43ec2d66a3
3 changed files with 68 additions and 8 deletions

View File

@@ -15,9 +15,15 @@ class _Entry:
class SubtitleEngine:
def __init__(self, script: List[Tuple[str, str]], default_duration: float = 5.0):
def __init__(
self,
script: List[Tuple],
default_duration: float = 5.0,
):
"""
script: [(关键词, 字幕文案), ...]
script: [(关键词, 字幕文案) | (关键词, 字幕文案, 显示时长秒), ...]
- 二元组:用 default_duration向后兼容
- 三元组:本条字幕独立指定显示秒数(用于长等待场景延长字幕停留)
关键词大小写不敏感,每个关键词只触发一次。
"""
self._script = script
@@ -31,12 +37,19 @@ class SubtitleEngine:
def process_line(self, line: str) -> None:
lower = line.lower()
for keyword, text in self._script:
for entry_tuple in self._script:
if len(entry_tuple) == 2:
keyword, text = entry_tuple
duration = self._default_duration
elif len(entry_tuple) == 3:
keyword, text, duration = entry_tuple
else:
continue
if keyword in self._matched:
continue
if keyword.lower() in lower:
elapsed = time.time() - self._t0
self._entries.append(_Entry(start=elapsed, text=text, duration=self._default_duration))
self._entries.append(_Entry(start=elapsed, text=text, duration=float(duration)))
self._matched.add(keyword)
def generate_srt(self, output_path: str) -> None: