autotrain/nextgen/autotrain_next/sampling.py
2026-07-24 10:37:32 +08:00

58 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""把人工演示录制转换成新手机的初始档案;不把任何像素坐标写进配置。"""
from __future__ import annotations
import json
import hashlib
import shutil
import struct
from datetime import datetime, timezone
from pathlib import Path
from .profiles import save
from .paths import ROOT, WORK
def png_size(path: Path) -> tuple[int, int]:
with path.open("rb") as handle:
header = handle.read(24)
if header[:8] != b"\x89PNG\r\n\x1a\n" or header[12:16] != b"IHDR":
raise ValueError(f"不是有效 PNG{path}")
return struct.unpack(">II", header[16:24])
def import_recording(recording: Path, device: dict[str, str], label: str = "") -> dict:
recording = recording.resolve()
session_path = recording / "session.json"
timeline_path = recording / "timeline.json"
if not session_path.exists() or not timeline_path.exists():
raise ValueError("录制目录必须包含 session.json 和 timeline.json")
session = json.loads(session_path.read_text(encoding="utf-8"))
recorded_device = session.get("device", {})
if recorded_device.get("serial") != device.get("serial"):
raise ValueError("录制设备与当前导入设备不一致")
timeline = json.loads(timeline_path.read_text(encoding="utf-8"))
destination = WORK / "samples" / hashlib.sha256(device["serial"].encode()).hexdigest()[:10] / datetime.now().strftime("%Y%m%d-%H%M%S")
destination.mkdir(parents=True, exist_ok=False)
samples: dict[str, dict] = {}
for entry in timeline.get("snapshots", []):
hint = str(entry.get("page_hint") or "other")
folder = (recording / str(entry.get("folder") or "")).resolve()
if recording not in folder.parents:
continue
screenshot = folder / "screen.png"
if hint in samples or not screenshot.exists():
continue
width, height = png_size(screenshot)
copied = destination / f"{hint}.png"
shutil.copy2(screenshot, copied)
samples[hint] = {"snapshot": str(copied.relative_to(ROOT)), "sha256": hashlib.sha256(copied.read_bytes()).hexdigest(), "screen": {"width": width, "height": height}, "captured_at": entry.get("timestamp", "")}
profile = {
"schema_version": 1, "label": label or device.get("model") or device["serial"],
"status": "draft", "device": device,
"sampling": {"source": "android_manual_recording", "recorded_at": session.get("started_at", ""), "samples": samples},
"gestures": {"scroll_up": {"from": [0.5, 0.82], "to": [0.5, 0.25], "duration_ms": 350}},
"created_at": datetime.now(timezone.utc).isoformat(),
}
save(profile)
return profile