OverviewFilesCommitsIssuesDocsReleasesPeers

stremio-vsembed commits / 10cb6d0

Progress from the .part file, not from ffmpeg (0.12.1)
The row read "saving to library…" indefinitely with no sign of life. It now carries the bytes written so far. Taken from the .part file's size rather than parsed out of ffmpeg -progress: exact, no Popen rewrite, and it cannot drift from reality, because the bytes on disk ARE the progress. No percentage. It would need a total we do not know up front -- the variant's BANDWIDTH is a ceiling, not a measurement -- and a confidently wrong percentage reads worse than an honest byte count. 4 new tests, 134 pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
10cb6d095228b519a1f7aebd80f4b499808c0bd6
by plankatron <fleeky@gmail.com> · 2026-08-11T15:13:25.000Z

Changed files (2) +72 -2

addon.py +29 -2
……@@ -533,7 +533,7 @@ TV_GENRES = [
533533
534534MANIFEST = {
535535 "id": "org.tabertron.vsembed",
536 "version": "0.12.0",
536 "version": "0.12.1",
537537 "name": "Tabertron VsEmbed",
538538 "description": "Self-hosted HLS extractor with TMDB browse + search, played via vidcore",
539539 "types": ["movie", "series"],
……@@ -1454,6 +1454,29 @@ def _ensure_ingest(kind: str, ident: str, season: int = 0, episode: int = 0,
14541454 _start_mp4_job(kind, ident, season, episode, height)
14551455
14561456
1457def _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
14571480def _next_episode(tmdb_id: str, season: int,
14581481 episode: int) -> Optional[tuple[int, int]]:
14591482 """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],
15981621 return # cannot be named, so the row would be a lie
15991622 running = _mp4_jobs.get(
16001623 _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)
16021629
16031630
16041631def _append_vidcore_row(out: list, kind: str, ident: Optional[str],
test_ingest_queue.py +43 -0
……@@ -133,6 +133,49 @@ def test_a_resume_rehydrates_finished_state_and_restarts_live_ones(resumed):
133133
134134# --- the real job path writes state ----------------------------------------
135135
136# --- progress ---------------------------------------------------------------
137# Read off the .part file rather than parsed out of ffmpeg. It is exact, needs
138# no -progress plumbing or Popen rewrite, and it cannot drift from reality --
139# the bytes on disk ARE the progress. A percentage is deliberately not offered:
140# it would need a total size we do not reliably know up front, and a wrong
141# percentage reads worse than an honest byte count.
142
143@pytest.fixture
144def part_of(tmdb_stub, monkeypatch):
145 dest = addon._library_path("series", "Show", "2020", "1",
146 season=1, episode=1, episode_title="Pilot")
147 os.makedirs(os.path.dirname(dest), exist_ok=True)
148 return dest
149
150
151@pytest.fixture
152def tmdb_stub(monkeypatch):
153 monkeypatch.setattr(addon, "_library_meta", lambda *a, **k: {
154 "tmdb_id": "1", "title": "Show", "year": "2020",
155 "episode_title": "Pilot"})
156
157
158def test_no_partial_means_no_progress(part_of):
159 assert addon._ingest_progress("series", "tmdb:1", 1, 1) is None
160
161
162def test_a_partial_reports_its_size(part_of):
163 with open(addon._part_path(part_of), "wb") as f:
164 f.write(b"x" * (3 * 1024 * 1024))
165 assert addon._ingest_progress("series", "tmdb:1", 1, 1) == 3 * 1024 * 1024
166
167
168def test_progress_is_not_reported_once_the_copy_is_finished(part_of):
169 with open(part_of, "wb") as f:
170 f.write(b"x" * 1024)
171 assert addon._ingest_progress("series", "tmdb:1", 1, 1) is None
172
173
174def test_progress_survives_an_unidentifiable_title(monkeypatch):
175 monkeypatch.setattr(addon, "_library_meta", lambda *a, **k: None)
176 assert addon._ingest_progress("series", "tmdb:9", 1, 1) is None
177
178
136179def test_start_mp4_job_records_its_arguments(monkeypatch):
137180 """So that a restart mid-remux can pick it up again."""
138181 monkeypatch.setattr(addon, "_run_ingest", lambda *a, **k: "done")