| … | … | @@ -533,7 +533,7 @@ TV_GENRES = [ |
| 533 | 533 | |
| 534 | 534 | MANIFEST = { |
| 535 | 535 | "id": "org.tabertron.vsembed", |
| 536 | | "version": "0.12.0", |
| 536 | "version": "0.12.1", |
| 537 | 537 | "name": "Tabertron VsEmbed", |
| 538 | 538 | "description": "Self-hosted HLS extractor with TMDB browse + search, played via vidcore", |
| 539 | 539 | "types": ["movie", "series"], |
| … | … | @@ -1454,6 +1454,29 @@ def _ensure_ingest(kind: str, ident: str, season: int = 0, episode: int = 0, |
| 1454 | 1454 | _start_mp4_job(kind, ident, season, episode, height) |
| 1455 | 1455 | |
| 1456 | 1456 | |
| 1457 | def _ingest_progress(kind: str, ident: str, season: int = 0, |
| 1458 | episode: int = 0) -> Optional[int]: |
| 1459 | """Bytes written so far for an in-flight copy, or None if none is running. |
| 1460 | |
| 1461 | Read off the .part file rather than parsed out of ffmpeg: it is exact, needs |
| 1462 | no -progress plumbing, and cannot drift from reality — the bytes on disk ARE |
| 1463 | the progress. |
| 1464 | |
| 1465 | A percentage is deliberately not offered. It would need a total size we do |
| 1466 | not know up front (the variant's BANDWIDTH is a ceiling, not a measurement), |
| 1467 | and a confidently wrong percentage reads worse than an honest byte count. |
| 1468 | """ |
| 1469 | meta = _library_meta(kind, ident, season, episode) |
| 1470 | if not meta: |
| 1471 | return None |
| 1472 | dest = _library_path(kind, meta["title"], meta["year"], meta["tmdb_id"], |
| 1473 | season, episode, meta["episode_title"]) |
| 1474 | try: |
| 1475 | return os.path.getsize(_part_path(dest)) |
| 1476 | except OSError: |
| 1477 | return None |
| 1478 | |
| 1479 | |
| 1457 | 1480 | def _next_episode(tmdb_id: str, season: int, |
| 1458 | 1481 | episode: int) -> Optional[tuple[int, int]]: |
| 1459 | 1482 | """What follows this episode per TMDB, or None if nothing does. |
| … | … | @@ -1598,7 +1621,11 @@ def _append_mp4_row(out: list, kind: str, ident: Optional[str], |
| 1598 | 1621 | return # cannot be named, so the row would be a lie |
| 1599 | 1622 | running = _mp4_jobs.get( |
| 1600 | 1623 | _mp4_key(kind, ident, season, episode, VIDCORE_MAX_HEIGHT)) == "running" |
| 1601 | | row("saving to library…" if running else "play & keep", VIDCORE_MAX_HEIGHT) |
| 1624 | if not running: |
| 1625 | return row("play & keep", VIDCORE_MAX_HEIGHT) |
| 1626 | done = _ingest_progress(kind, ident, season, episode) |
| 1627 | row(f"saving to library… {done / 1e6:.0f} MB" if done |
| 1628 | else "saving to library…", VIDCORE_MAX_HEIGHT) |
| 1602 | 1629 | |
| 1603 | 1630 | |
| 1604 | 1631 | def _append_vidcore_row(out: list, kind: str, ident: Optional[str], |