Files
Varaverk/Media/Manual-Media.md
T
Gmer4Lfe 8a2707ee37 Correct and extend folder docs for Docker Essentials, Watchdogs, Media and Arrs Stack
The docs had drifted from the scripts — a script that no longer exists, three wrong variable
names, a reversed run order, and seven scheduled scripts that were never documented at all.
2026-08-01 22:59:07 -04:00

239 lines
8.2 KiB
Markdown

# ━━━━━ MEDIA — Manual ━━━━━
Config reference, procedures, operational workflows for Media/ scripts.
For overview see README-Media.md. For per-script detail see script headers.
For arr stack config and procedures (cleanup, release fixer, sync, discovery) see
`Arrs_Stack/Manual-Arrs_Stack.md`.
---
## ━━━ PERMISSIONS MODEL ━━━
```
Directories: 755 nobody:users
Owner (nobody) — rwx enter, list, create files
Group (users) — r-x enter and list
Others — r-x Samba guests can browse
No world-write — prevents accidental deletion by unauthenticated access
Files: 664 nobody:users
Owner (nobody) — rw read + write
Group (users) — rw arrs can import, rename, delete
Others — r Samba guests can read
No execute bit — media files are never executable
```
**Two separate passes — not a single recursive chmod.** Directories need the execute bit
to enter. Files must never have the execute bit. A single `chmod -R 664` would break
directory entry. The script runs `find -type d` and `find -type f` separately.
**If this script corrects many files on every run**, a container has wrong PUID/PGID.
Correct values on unRAID: `PUID=99 (nobody)` `PGID=100 (users)`. Add to each container's
environment in its Docker template. Common culprits: SABnzbd, qBittorrent, slskd.
Once fixed, this script corrects 0 files per run — it becomes a pure daily failsafe.
---
## ━━━ CONFIGURATION — master.conf ━━━
### Permissions
```bash
PERMISSIONS_DIR_MODE="755"
PERMISSIONS_FILE_MODE="664"
PERMISSIONS_OWNER="nobody:users"
```
---
### Media Cleaner — File Patterns
```bash
ANIME_FILE_PATTERNS=(
"*.sfv" # checksum verification — useless after download verified
"*.md5" "*.sha1" # other checksum formats
"*.nfo" # scene info file — not library metadata
"*.url" "*.lnk" # website shortcuts
"*.rar" "*.zip" # source archives kept by some clients after extraction
"*.info" # tool output files
"*.torrent" # torrent descriptor left by some clients
"*.sample*" # scene preview clip
"*.proof*" # screenshot proving encode quality
"*sync-conflict*" # Syncthing conflict copies
"*.scr" "*.exe" # executables — should never be in a media folder
"*.srr" # scene recovery record
"*.log" # tool/client logs
"*.json" # metadata or tool output
)
MEDIA_FILE_PATTERNS=(
"${ANIME_FILE_PATTERNS[@]}" # all anime patterns plus:
"*.iso" # disc images after ripping
"*.lrc" # lyric files in media folders
)
```
> **DO NOT add patterns that match media you want to keep:**
> `*.mkv *.mp4 *.avi *.m4v` — video files
> `*.flac *.mp3 *.m4a` — audio files
> `*.srt *.sub *.ass` — subtitle files (Bazarr managed)
> `*.jpg *.png` — artwork
> Always use `--dry-run` when adding new patterns.
---
### Play State Sync
```bash
PLAY_SYNC_ENABLED=true # toggle entire sync
PLAY_SYNC_REMOTE=true # sync across hosts via Tailscale
# false = local servers only (this host's Emby + Jellyfin)
PLAY_SYNC_TYPES="Movie,Episode" # item types to sync — Audio excluded, music library too large
PLAY_SYNC_FAV_TYPES="MusicArtist,MusicAlbum,Movie,Series" # favourites, union sync, never unmarks
PLAY_SYNC_PROBE=true # skip per-item work when nothing changed since last run
PLAY_SYNC_PROBE_MAX_AGE_HOURS=24 # force a full comparison when the fingerprint is older
PLAY_SYNC_HANDBACK_RETRIES=5 # fallback handback: attempts before DNS cutover proceeds
PLAY_SYNC_HANDBACK_RETRY_DELAY=60 # seconds between those attempts
```
> **There is no date/lookback filter, and one must not be re-added.** An earlier version
> gated on played-date; it was removed once the real cost was measured — the 30-minute
> runtime was fork overhead per item, not API volume or item count. The fix was jq epoch
> parsing plus the response-hash probe below. Re-introducing a date window would reduce
> correctness (older items silently stop syncing) without meaningfully reducing runtime.
Emby and Jellyfin servers configured per-host:
```bash
# host*.conf
HOST1_EMBY_URL="http://192.168.50.2:8096"
HOST1_EMBY_API_KEY="..."
HOST1_JELLYFIN_URL="" # empty = skip Jellyfin on this host
HOST1_JELLYFIN_API_KEY=""
```
---
## ━━━ CONFIGURATION — host*.conf ━━━
```bash
# Shares this server applies permissions to
HOST1_MEDIA_PERMISSION_SHARES=(
"/mnt/user/Movies"
"/mnt/user/Tv_Shows"
"/mnt/user/Music"
"/mnt/user/Kids_Movies"
"/mnt/user/Kids_Tv_Shows"
"/mnt/user/Sports"
"/mnt/user/stand-up_comedy"
)
# Folders cleaned by each profile
HOST1_ANIME_CLEAN_FOLDERS=(
"/mnt/user/Anime_Movies"
"/mnt/user/Anime_Movies-Old"
"/mnt/user/Anime_Shows"
"/mnt/user/Anime_Shows-Old"
)
HOST1_MEDIA_CLEAN_FOLDERS=(
"/mnt/user/Kids_Movies"
"/mnt/user/Kids_Tv_Shows"
"/mnt/user/Movies"
"/mnt/user/Music"
"/mnt/user/Sports"
"/mnt/user/stand-up_comedy"
"/mnt/user/Tv_Shows"
)
```
---
## ━━━ OUTPUT TIERS ━━━
All scripts have two output levels controlled by `--log`.
Without `--log`, each script processes silently and concludes with a summary block.
Warnings and errors are always visible.
With `--log`, per-item detail appears — individual shares being processed, file counts,
per-server sync results.
---
## ━━━ FLAG REFERENCE ━━━
### media_shares_permissions.sh
`media_shares_permissions.sh`
Apply correct ownership and permissions to all configured media shares. Safe to run
manually at any time — idempotent, only changes what's wrong.
`media_shares_permissions.sh --dry-run`
Show how many files and directories would be corrected per share. If unexpectedly large,
check container PUID/PGID settings first (PUID=99 PGID=100).
`media_shares_permissions.sh --status`
Show configured share list and ownership of the share roots.
`media_shares_permissions.sh --log`
Show ownership correction count per share and per file (verbose).
> On large libraries this runs 20-30 minutes. This is expected — millions of files with
> recursive walk takes time. Designed to run overnight in the maintenance window.
---
### media_cleaner.sh
`media_cleaner.sh anime`
Remove junk files from anime share folders using ANIME_FILE_PATTERNS.
`media_cleaner.sh media`
Remove junk files from media share folders using MEDIA_FILE_PATTERNS.
`media_cleaner.sh [profile] --dry-run`
Show what would be deleted without removing anything. Always run first when adding new
patterns or folders.
`media_cleaner.sh [profile] --status`
Show folder list and file patterns for the profile.
`media_cleaner.sh [profile] --log`
Show every file examined, not just those removed.
---
### play_state_sync.sh
`play_state_sync.sh`
Sync played/unplayed state, resume positions and favourites across **every** configured Emby
and Jellyfin server — not just local→remote. Servers are discovered from every
`HOST*_TRANSCODE_SERVERS` entry, with remote hosts' localhost URLs rewritten to their
Tailscale IP. Newest `LastPlayedDate` wins; state only ever moves forward, never clears.
No age filter — every matched item is considered on every run. The **change probe** is what
keeps that cheap: the raw API responses are hashed and compared against the fingerprint from
the last successful run, and per-item processing is skipped entirely when nothing moved.
Fetches still happen every run, so nothing can be missed by the probe.
`play_state_sync.sh --full`
Bypass the change probe and force the full per-item comparison even when the fingerprint
matches. Use after a new Emby install or database restore, or when debugging a sync that
appears to be skipping work it should be doing.
`play_state_sync.sh --wait`
Wait for an in-progress run instead of exiting. For manual runs that would otherwise be
skipped by the scheduled every-30-minute pass. Used by `fallback.sh` during handback.
`play_state_sync.sh --dry-run`
Show what would be synced without writing any state.
`play_state_sync.sh --status`
Show configured servers, reachability, and user counts.
`play_state_sync.sh --log`
Verbose output — show each item comparison.