Media segments are never extracted, so intro and credit skipping never appears #101

Closed
opened 2026-08-13 22:59:40 +02:00 by Claude · 1 comment
Collaborator

GET /MediaSegments/{itemId} is answered and reads the MediaSegments table; nothing in the workspace inserts a row. M7 named it, and the fixture has none of any so both servers answer the same nothing.

Upstream's MediaSegmentExtractionTask (Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs, key TaskExtractMediaSegments, 12 h) drives whatever IMediaSegmentProviders are registered over items that have not been analysed. In a stock 12.0 install the providers are plugins — which is the honest caveat here: a bare upstream extracts nothing either.

So the in-scope half is the plumbing: the task, the per-item "has been analysed" state, and the write path, so that a segment produced by anything at all can be stored and served. Whether this server ever ships a detector of its own is a separate decision, and probably a no under the no-plugins scope.

Worth confirming against the reference before writing anything: with no provider registered, does upstream still mark items analysed? That decides whether the table stays empty or fills with empty analyses, and a database diff will care.


Where to start

GET /MediaSegments/{itemId} is served out of crates/jellyfin-http/src/routes/library.rs
against the MediaSegments table; nothing writes it.

Upstream is Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs
(key TaskExtractMediaSegments, 12 h), which drives whatever IMediaSegmentProviders
are registered. In a stock 12.0 install those come from plugins — so a bare
upstream extracts nothing either, and this issue is the plumbing: the task,
the per-item analysed state, and the write path, so anything that produces a
segment can store one.

Settle this against the reference before writing code: with no provider
registered, does upstream still mark items analysed? The answer decides whether
the table stays empty or fills with empty analyses, and diff-db will care
either way.

How to know it is done

A segment handed to the write path is stored and served, diff-db agrees with
the reference about the analysed state, and the task appears in /ScheduledTasks
doing real work rather than as a name.

House rules

CLAUDE.md is the short version and these are the parts that bite: tests run
under cargo nextest; upstream's source is the checkout in upstream/ at the
pin
(v12.0-rc5, 6d501ba4) and not the clone beside the repository;
generated files are regenerated rather than edited; a comment says what the code
does, not how it got there; and Dn references stay out of code and comments.
ARCHITECTURE.md decides which crate a thing goes in and which dependency edges
are illegal, DECISIONS.md says why a rule exists.

The reference pair is cargo xtask reference up (and reference provision,
which is idempotent); a run is
cargo run -p jellyfin-harness -- replay --upstream URL --ours URL --scenario FILE --out DIR,
with diff-db for the two databases. crates/jellyfin-harness/README.md says
what a diff means and what an ignore entry has to carry — every entry needs a
reason and an expiry milestone, and an adds-only history is the smell the risk
table names.

`GET /MediaSegments/{itemId}` is answered and reads the `MediaSegments` table; nothing in the workspace inserts a row. M7 named it, and the fixture has none of any so both servers answer the same nothing. Upstream's `MediaSegmentExtractionTask` (`Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs`, key `TaskExtractMediaSegments`, 12 h) drives whatever `IMediaSegmentProvider`s are registered over items that have not been analysed. In a stock 12.0 install the providers are plugins — which is the honest caveat here: a bare upstream extracts nothing either. So the in-scope half is the **plumbing**: the task, the per-item "has been analysed" state, and the write path, so that a segment produced by anything at all can be stored and served. Whether this server ever ships a detector of its own is a separate decision, and probably a no under the no-plugins scope. Worth confirming against the reference before writing anything: with no provider registered, does upstream still mark items analysed? That decides whether the table stays empty or fills with empty analyses, and a database diff will care. --- ## Where to start `GET /MediaSegments/{itemId}` is served out of `crates/jellyfin-http/src/routes/library.rs` against the `MediaSegments` table; nothing writes it. Upstream is `Emby.Server.Implementations/ScheduledTasks/Tasks/MediaSegmentExtractionTask.cs` (key `TaskExtractMediaSegments`, 12 h), which drives whatever `IMediaSegmentProvider`s are registered. In a stock 12.0 install those come from plugins — so a bare upstream extracts nothing either, and this issue is the **plumbing**: the task, the per-item analysed state, and the write path, so anything that produces a segment can store one. **Settle this against the reference before writing code**: with no provider registered, does upstream still mark items analysed? The answer decides whether the table stays empty or fills with empty analyses, and `diff-db` will care either way. ## How to know it is done A segment handed to the write path is stored and served, `diff-db` agrees with the reference about the analysed state, and the task appears in `/ScheduledTasks` doing real work rather than as a name. ### House rules `CLAUDE.md` is the short version and these are the parts that bite: tests run under `cargo nextest`; upstream's source is the checkout in `upstream/` **at the pin** (`v12.0-rc5`, `6d501ba4`) and not the clone beside the repository; generated files are regenerated rather than edited; a comment says what the code does, not how it got there; and `Dn` references stay out of code and comments. `ARCHITECTURE.md` decides which crate a thing goes in and which dependency edges are illegal, `DECISIONS.md` says why a rule exists. The reference pair is `cargo xtask reference up` (and `reference provision`, which is idempotent); a run is `cargo run -p jellyfin-harness -- replay --upstream URL --ours URL --scenario FILE --out DIR`, with `diff-db` for the two databases. `crates/jellyfin-harness/README.md` says what a diff means and what an ignore entry has to carry — every entry needs a reason and an expiry milestone, and an adds-only history is the smell the risk table names.
Author
Collaborator

Settled: there is nothing to build, and that is the answer rather than a deferral.

Measured against upstream rather than argued from its source. With no provider registered, RunSegmentPluginProviders returns before it opens a context; there is no per-item analysed state anywhere in the schema; and running TaskExtractMediaSegments on a pinned upstream completed, wrote no row, and marked nothing.

So the table stays empty on both servers, diff-db agrees about it, and declaring the task here would be exactly the button crates/jellyfin-app/src/tasks.rs refuses in its own module doc — "one named here that did nothing would be a button an operator presses and watches succeed."

The plumbing this issue asked for turns out to be a write path with nothing upstream to write. Recorded in MILESTONES.md (618bbf3) so the next person reads the measurement rather than repeating it. If a segment provider is ever ported, this reopens with a producer attached.

Settled: **there is nothing to build**, and that is the answer rather than a deferral. Measured against upstream rather than argued from its source. With no provider registered, `RunSegmentPluginProviders` returns before it opens a context; there is **no per-item analysed state anywhere in the schema**; and running `TaskExtractMediaSegments` on a pinned upstream completed, wrote no row, and marked nothing. So the table stays empty on both servers, `diff-db` agrees about it, and declaring the task here would be exactly the button `crates/jellyfin-app/src/tasks.rs` refuses in its own module doc — *"one named here that did nothing would be a button an operator presses and watches succeed."* The plumbing this issue asked for turns out to be a write path with nothing upstream to write. Recorded in `MILESTONES.md` (`618bbf3`) so the next person reads the measurement rather than repeating it. If a segment provider is ever ported, this reopens with a producer attached.
Sign in to join this conversation.
No description provided.