docs(33): import 2 YT videos to stock Jellyfin Education
Single-video imports per playbook §1d (collectionType=movies): - Johnny Harris — Why the US is deporting so many people (20251031) - The Guardian — NSA whistleblower Edward Snowden (20130709) Snowden run exposed Jellyfin's single-file channel folder caveat: MovieResolver parses folder name as item title when only one media file exists. Worked around with PUT /Items/<id> Name + LockData=true. Documented in the run log for future hardening into playbook §1d.
This commit is contained in:
parent
c391447a9f
commit
c8a1305da4
2 changed files with 205 additions and 0 deletions
|
|
@ -0,0 +1,83 @@
|
||||||
|
# johnny-harris-why-us-deporting-20251031
|
||||||
|
|
||||||
|
Single-video YouTube import into the **STOCK** Jellyfin at `tv.s8n.ru`
|
||||||
|
(container `jellyfin-stock`), **Education** library
|
||||||
|
(`collectionType=movies`, internet providers disabled).
|
||||||
|
|
||||||
|
Channel "Johnny Harris" folder already existed with 4 prior videos. This run
|
||||||
|
adds the 2025-10-31 release "Why the US is deporting so many people".
|
||||||
|
|
||||||
|
## Provenance
|
||||||
|
|
||||||
|
- **Source:** YouTube — `https://www.youtube.com/watch?v=aDbtrdfYqBc`
|
||||||
|
- **Channel:** Johnny Harris
|
||||||
|
- **Tool:** `yt-dlp` on onyx
|
||||||
|
- **Format selector:** `bv*[height<=1080][ext=mp4]+ba[ext=m4a]/b[height<=1080][ext=mp4]/bv*[height<=1080]+ba/b[height<=1080]/b` → `--merge-output-format mp4` (source available up to 2160p, capped to 1080p per playbook §1e)
|
||||||
|
- **Subs:** `--write-subs --sub-langs 'en' --embed-subs --convert-subs srt` — user-uploaded English subs present, embedded into mp4 AND written as sidecar `.en.srt`
|
||||||
|
- **Thumbnail:** `--write-thumbnail --convert-thumbnails jpg` → sidecar `.jpg` used as Primary by Local Posters plugin
|
||||||
|
- **Staging path on onyx:** `/home/admin/staging-jelly/Johnny Harris/`
|
||||||
|
|
||||||
|
## Target
|
||||||
|
|
||||||
|
- **Server:** `jellyfin-stock` on nullstone, public URL `https://tv.s8n.ru`
|
||||||
|
- **Library:** Education (`collectionType=movies`, `EnableInternetProviders=false`)
|
||||||
|
- **Path on host:** `/home/user/media/education/Johnny Harris/Why the US is deporting so many people — 20251031.mp4`
|
||||||
|
- **Container view:** `/media/education/Johnny Harris/Why the US is deporting so many people — 20251031.mp4`
|
||||||
|
- **Item ID:** `6ba95c8325213da65c2d6f3c26a35a08`
|
||||||
|
|
||||||
|
### Sidecar files
|
||||||
|
|
||||||
|
| Kind | File |
|
||||||
|
|---|---|
|
||||||
|
| Media | `Why the US is deporting so many people — 20251031.mp4` (271,042,755 B, ~258 MiB) |
|
||||||
|
| Subtitle | `Why the US is deporting so many people — 20251031.en.srt` (83,161 B) |
|
||||||
|
| Thumbnail | `Why the US is deporting so many people — 20251031.jpg` (70,137 B) — Primary image via Local Posters |
|
||||||
|
|
||||||
|
## Counts
|
||||||
|
|
||||||
|
| | Before | After | Delta |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| Education / Johnny Harris items | 4 | 5 | +1 |
|
||||||
|
|
||||||
|
## Stream summary
|
||||||
|
|
||||||
|
```
|
||||||
|
Duration: 00:45:26.32, bitrate: 795 kb/s
|
||||||
|
Stream #0:0[0x1](und): Video: av1 (libdav1d) (Main), yuv420p(tv, bt709), 1920x1080, 662 kb/s, 23.98 fps
|
||||||
|
Stream #0:1[0x2](eng): Audio: aac (LC), 44100 Hz, stereo, fltp, 128 kb/s
|
||||||
|
Stream #0:2[0x3](eng): Subtitle: mov_text (tx3g)
|
||||||
|
```
|
||||||
|
|
||||||
|
AV1 1080p at ~0.66 Mb/s + stereo AAC + embedded English mov_text subs.
|
||||||
|
|
||||||
|
## Subtitle status
|
||||||
|
|
||||||
|
- Embedded: yes — one English `mov_text` track from yt-dlp `--embed-subs`.
|
||||||
|
- External sidecar: yes — `.en.srt` next to the mp4 (Jellyfin will register it
|
||||||
|
as a second selectable subtitle track).
|
||||||
|
- Action: none. Plain English, no SDH/MT/AI tag per ARRFLIX subtitle style.
|
||||||
|
|
||||||
|
## Verification checks
|
||||||
|
|
||||||
|
- [x] Folder/filename canonical (`<Channel>/<Title> — <YYYYMMDD>.mp4`, date as suffix).
|
||||||
|
- [x] No forbidden chars in path.
|
||||||
|
- [x] Permissions `user:user` 644 / 755 (chmod safety net run server-side).
|
||||||
|
- [x] `Scan Media Library` triggered via `/ScheduledTasks/Running/<id>`,
|
||||||
|
`State` returned to `Idle`.
|
||||||
|
- [x] `/Items?searchTerm=Why+the+US+is+deporting` returns the single expected
|
||||||
|
item with `ImageTags.Primary` present, `ProviderIds` empty (expected for
|
||||||
|
Education library).
|
||||||
|
- [x] Direct-play in client browser (AV1 supported by Chromium >= 90).
|
||||||
|
- [ ] Mobile / Smart-TV direct-play not exercised.
|
||||||
|
|
||||||
|
## Notes / surprises
|
||||||
|
|
||||||
|
- Source upload available in 2160p AV1; 1080p cap per playbook §1e mandatory
|
||||||
|
for long-form (~45min) content.
|
||||||
|
- No metadata refresh needed — Local Posters picked up `<basename>.jpg` as
|
||||||
|
Primary on first scan; no Screen Grabber fallback.
|
||||||
|
- Single-file channel folder caveat does **not** apply here because the
|
||||||
|
Johnny Harris folder already contained 4 prior files; Jellyfin's
|
||||||
|
"movie-in-own-folder" heuristic only fires when there's exactly one media
|
||||||
|
file. See `the-guardian-snowden-2013-20130709.md` for the workaround when
|
||||||
|
importing the first video into a brand-new channel folder.
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
# the-guardian-snowden-2013-20130709
|
||||||
|
|
||||||
|
Single-video YouTube import into the **STOCK** Jellyfin at `tv.s8n.ru`
|
||||||
|
(container `jellyfin-stock`), **Education** library
|
||||||
|
(`collectionType=movies`, internet providers disabled).
|
||||||
|
|
||||||
|
First import into a brand-new "The Guardian" channel folder. Exposed a
|
||||||
|
single-file folder caveat in Jellyfin movie parsing — see Notes.
|
||||||
|
|
||||||
|
## Provenance
|
||||||
|
|
||||||
|
- **Source:** YouTube — `https://www.youtube.com/watch?v=0hLjuVyIIrs`
|
||||||
|
- **Channel:** The Guardian
|
||||||
|
- **Tool:** `yt-dlp` on onyx
|
||||||
|
- **Format selector:** `bv*[height<=1080][ext=mp4]+ba[ext=m4a]/b[height<=1080][ext=mp4]/bv*[height<=1080]+ba/b[height<=1080]/b` → `--merge-output-format mp4` (source native 1080p)
|
||||||
|
- **Subs:** `--write-subs --sub-langs 'en' --embed-subs --convert-subs srt` — **no user-uploaded English subs available**; `[EmbedSubtitle] There aren't any subtitles to embed`
|
||||||
|
- **Thumbnail:** `--write-thumbnail --convert-thumbnails jpg` → sidecar `.jpg` used as Primary
|
||||||
|
- **Staging path on onyx:** `/home/admin/staging-jelly/The Guardian/`
|
||||||
|
|
||||||
|
### Filename normalisation
|
||||||
|
|
||||||
|
Raw YouTube title:
|
||||||
|
> `NSA whistleblower Edward Snowden: 'I don't want to live in a society that does these sort of things'`
|
||||||
|
|
||||||
|
yt-dlp's safe-name pass replaced the ASCII `:` with the fullwidth `:` (U+FF1A).
|
||||||
|
Per playbook §1f the canonical replacement is ASCII ` - `, so the file was
|
||||||
|
renamed before rsync to:
|
||||||
|
|
||||||
|
`NSA whistleblower Edward Snowden - 'I don't want to live in a society that does these sort of things' — 20130709.mp4`
|
||||||
|
|
||||||
|
Apostrophes preserved (playbook §1f: smart quotes and apostrophes pass).
|
||||||
|
|
||||||
|
## Target
|
||||||
|
|
||||||
|
- **Server:** `jellyfin-stock` on nullstone, public URL `https://tv.s8n.ru`
|
||||||
|
- **Library:** Education (`collectionType=movies`, `EnableInternetProviders=false`)
|
||||||
|
- **Path on host:** `/home/user/media/education/The Guardian/NSA whistleblower Edward Snowden - 'I don't want to live in a society that does these sort of things' — 20130709.mp4`
|
||||||
|
- **Container view:** same under `/media/education/`
|
||||||
|
- **Item ID:** `578da493fdcff4e8fde5137adbcaebdb`
|
||||||
|
|
||||||
|
### Sidecar files
|
||||||
|
|
||||||
|
| Kind | File |
|
||||||
|
|---|---|
|
||||||
|
| Media | `… — 20130709.mp4` (46,324,047 B, ~44 MiB) |
|
||||||
|
| Subtitle | none |
|
||||||
|
| Thumbnail | `… — 20130709.jpg` (34,895 B) — Primary via Local Posters |
|
||||||
|
|
||||||
|
## Counts
|
||||||
|
|
||||||
|
| | Before | After | Delta |
|
||||||
|
|---|---:|---:|---:|
|
||||||
|
| Education / The Guardian items | 0 | 1 | +1 |
|
||||||
|
| Education / The Guardian channel folders | 0 | 1 | +1 |
|
||||||
|
|
||||||
|
## Stream summary
|
||||||
|
|
||||||
|
```
|
||||||
|
Duration: 00:12:34.30, bitrate: 491 kb/s
|
||||||
|
Stream #0:0[0x1](und): Video: av1 (libdav1d) (Main), yuv420p(tv, bt709), 1920x1080, 358 kb/s, 25 fps
|
||||||
|
Stream #0:1[0x2](eng): Audio: aac (LC), 44100 Hz, stereo, fltp, 127 kb/s
|
||||||
|
```
|
||||||
|
|
||||||
|
AV1 1080p25 + stereo AAC. No subtitle streams.
|
||||||
|
|
||||||
|
## Subtitle status
|
||||||
|
|
||||||
|
- Embedded: no (channel does not publish user-uploaded en captions on this
|
||||||
|
video; auto-CC not requested by playbook).
|
||||||
|
- External sidecar: no.
|
||||||
|
- Action: deferred. If subs become required, follow `playbooks/subtitles/`
|
||||||
|
WhisperX pipeline (do **not** fall back to YouTube auto-CC; see
|
||||||
|
`feedback_subtitle_accuracy_priority`).
|
||||||
|
|
||||||
|
## Verification checks
|
||||||
|
|
||||||
|
- [x] Folder/filename canonical (`<Channel>/<Title> — <YYYYMMDD>.mp4`).
|
||||||
|
- [x] No forbidden chars in path (fullwidth `:` → ` - ` rename in staging).
|
||||||
|
- [x] Permissions `user:user` 644 / 755.
|
||||||
|
- [x] `Scan Media Library` triggered, `State=Idle`, ran twice (initial scan
|
||||||
|
did not pull file in until folder was visible to library monitor — see
|
||||||
|
Notes).
|
||||||
|
- [x] `/Items?searchTerm=NSA+whistleblower&IncludeItemTypes=Movie` returns
|
||||||
|
the expected single item after `Name` lock.
|
||||||
|
- [x] `ImageTags.Primary` present.
|
||||||
|
- [ ] Direct-play in mobile / Smart-TV client not exercised.
|
||||||
|
|
||||||
|
## Notes / surprises
|
||||||
|
|
||||||
|
### Single-file channel folder → Jellyfin parses folder name as title
|
||||||
|
|
||||||
|
Jellyfin's MovieResolver applies the "movie-in-own-folder" heuristic when a
|
||||||
|
folder under a `collectionType=movies` library contains **exactly one** media
|
||||||
|
file. The resulting `BaseItem.Name` is taken from the folder name, not the
|
||||||
|
filename — so the Snowden mp4 initially indexed with `Name="The Guardian"`
|
||||||
|
instead of the actual video title.
|
||||||
|
|
||||||
|
Workaround used (no playbook change required for this run):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull current item, set Name explicitly, LockData=true, POST back
|
||||||
|
ID=578da493fdcff4e8fde5137adbcaebdb
|
||||||
|
curl -sf -H "X-Emby-Token: $TOK" \
|
||||||
|
"$SERVER_URL/Users/$USER_ID/Items/$ID" \
|
||||||
|
| jq '.Name = "NSA whistleblower Edward Snowden - ..." | .LockData = true' \
|
||||||
|
| curl -sf -X POST -H "X-Emby-Token: $TOK" -H 'Content-Type: application/json' \
|
||||||
|
--data @- "$SERVER_URL/Items/$ID"
|
||||||
|
# expect HTTP 204; Name now locked so future refresh cannot revert it.
|
||||||
|
```
|
||||||
|
|
||||||
|
Generalises to any first-video import into a brand-new channel folder.
|
||||||
|
Recommend documenting in `playbooks/import-media/README.md` §1d as a known
|
||||||
|
caveat with the LockData fix; will propose a `playbooks/` PR after the
|
||||||
|
second occurrence to confirm reproducibility.
|
||||||
|
|
||||||
|
### Two scan passes required
|
||||||
|
|
||||||
|
First `POST /ScheduledTasks/Running/<scan-task-id>` returned to `Idle` while
|
||||||
|
the file was already on disk but reported no new Education item. A second
|
||||||
|
identical invocation indexed the file. Root cause unclear — possible
|
||||||
|
`LibraryMonitor` race during inotify pickup of the freshly created folder.
|
||||||
|
Documenting per playbook §5d / known-broken-trigger guidance.
|
||||||
Loading…
Reference in a new issue