(video_path: Path)
| 19945 | return None |
| 19946 | |
| 19947 | def probe_metadata(video_path: Path): |
| 19948 | stat = video_path.stat() |
| 19949 | base = { |
| 19950 | "file_name": video_path.name, |
| 19951 | "file_path": str(video_path), |
| 19952 | "file_size_bytes": stat.st_size, |
| 19953 | "file_size_mb": round(stat.st_size / (1024 * 1024), 4), |
| 19954 | "created_utc": datetime.fromtimestamp(stat.st_ctime, tz=timezone.utc).isoformat(), |
| 19955 | "modified_utc": datetime.fromtimestamp(stat.st_mtime, tz=timezone.utc).isoformat(), |
| 19956 | "hashes": _compute_hashes(video_path) |
| 19957 | } |
| 19958 | |
| 19959 | def _safe(v): |
| 19960 | if v is None: |
| 19961 | return None |
| 19962 | if isinstance(v, bytes): |
| 19963 | try: |
| 19964 | return v.decode("utf-8", errors="replace") |
| 19965 | except Exception: |
| 19966 | return repr(v) |
| 19967 | if isinstance(v, (str, int, float, bool)): |
| 19968 | return v |
| 19969 | if isinstance(v, dict): |
| 19970 | out = {} |
| 19971 | for kk, vv in v.items(): |
| 19972 | k2 = _safe(kk) |
| 19973 | v2 = _safe(vv) |
| 19974 | if k2 is not None: |
| 19975 | out[str(k2)] = v2 |
| 19976 | return out |
| 19977 | if isinstance(v, (list, tuple)): |
| 19978 | return [_safe(x) for x in v] |
| 19979 | if hasattr(v, "printable"): |
| 19980 | return str(v.printable) |
| 19981 | return str(v) |
| 19982 | |
| 19983 | def _parse_video_coord(raw): |
| 19984 | if raw is None: |
| 19985 | return None |
| 19986 | if isinstance(raw, (int, float)): |
| 19987 | try: |
| 19988 | v = float(raw) |
| 19989 | if v == v: |
| 19990 | return v |
| 19991 | except Exception: |
| 19992 | return None |
| 19993 | txt = str(raw).strip() |
| 19994 | if not txt: |
| 19995 | return None |
| 19996 | found = re.search(r"(-?\d+(?:[.,]\d+)?)", txt) |
| 19997 | if not found: |
| 19998 | return None |
| 19999 | try: |
| 20000 | return float(found.group(1).replace(",", ".")) |
| 20001 | except Exception: |
| 20002 | return None |
| 20003 | |
| 20004 | def _parse_iso6709(raw): |
no test coverage detected