-
Notifications
You must be signed in to change notification settings - Fork 1
tvtimes
tvtimes is the companion self-hosted TV-guide web app. It aggregates several IPTV/tuner sources (M3U, Xtream, Stalker, HDHomeRun) into one de-duplicated line-up and one XMLTV guide whose times are already corrected per channel, then publishes both behind a single rotatable token.
Point tvdinner at it and you get that whole merged line-up, guide included, as one source — the natural split being tvtimes is where you plan, tvdinner is where you watch.
tvtimes://host[:port]?token=...
Use tvtimess:// if the server is served over https — the usual case
behind a reverse proxy. A base path is kept if tvtimes sits under a
sub-path on your proxy:
tvtimess://example.com/tv?token=...
In tvtimes: Settings → Export feeds → Generate feed links. Alongside
the M3U and XMLTV URLs there's an Open in tvdinner row carrying the
tvtimes:// URL ready-made.
-
Click it — after
tvdinner default-handler(see the README), the browser handstvtimes:/tvtimess:links straight to tvdinner, same as it already does for thetvdinner:Play links. -
Or copy it and run
tvdinner 'tvtimess://…', or save it as a bookmark so it's one keystroke next time.
The token is shown once. Rotating it in tvtimes invalidates the old one, so a saved bookmark needs updating after a rotate.
This is sugar, not a new protocol. The URL expands to that account's two export feeds:
<base>/api/exports/playlist.m3u?token=...
<base>/api/exports/epg.xml?token=...
and from there it's an ordinary M3U playlist with an XMLTV guide — so the program guide, favorites, recording and scheduling, bookmarks and the EPG cache all behave exactly as they do for any other M3U + XMLTV pair. There is no tvtimes-specific code past the URL expansion.
Two details worth knowing:
-
The guide URL comes from the host you typed, not from the
url-tvg=header inside the playlist. tvtimes builds that header from its own configured public origin, which needn't be the address this machine reaches it on (a LAN IP vs the proxied hostname). An explicit--epgstill overrides both. -
Per-channel clock shifts are already applied server-side. tvtimes
writes corrected times into its XMLTV, so you shouldn't need
--time-shift/--epg-shiftson a tvtimes source — if a channel still looks off, fix it in tvtimes so every downstream player benefits.
Add --record-watchlist and tvdinner polls the account's watchlist every
15 minutes, scheduling a recording for each upcoming airing anyone on it
has flagged:
tvdinner 'tvtimess://tv.example.com?token=...' --record-watchlist
Press Remind me (or Watch this title) in the tvtimes web app — from your phone, on the bus — and the box at home records it. Its scheduled-recording engine does the actual work; this just feeds it.
- The watchlist is per user but the export token is per account, so a shared household account records what anyone on it flagged, de-duplicated per broadcast.
- Entries created this way are tagged in
schedule.jsonand reconciled on every poll — un-watchlist something in tvtimes and its pending recording disappears too. - Recordings you scheduled by hand from the guide are never touched, and if one already covers an airing the watchlist also wants, no duplicate is added beside it.
- Times arrive already clock-shift corrected, so they line up with the guide rather than with raw feed time.
- The usual caveat: there's no background service, so tvdinner has to still be running when the recording's time comes.
A failed poll (server down, box off the network) is logged and retried on the next tick — it never drops recordings already scheduled.
--report-watch-state posts what you watch on this source back to the
tvtimes account every 15 minutes, so its web guide dims and ticks the
programmes you've already seen:
tvdinner 'tvtimess://tv.example.com?token=...' --report-watch-state \
--device-name 'living room'
- Only live-channel watches from this feed are sent. A local file, a YouTube video, a Plex episode or a channel from another playlist has no tvtimes channel to attribute to and is skipped.
- What goes over the wire is plain start/stop intervals, never "programme X was watched". tvtimes derives which programmes those cover by overlapping them against its own guide — so a guide refresh, or correcting a channel's clock shift, updates the answer with nothing re-reported.
- A programme counts as watched once half of it, or 30 minutes, is covered. Flicking past doesn't count; half a three-hour film isn't demanded either.
- The last week of history is resent on every tick rather than tracked as "already sent". tvtimes de-duplicates, so a restart or a spell offline catches up by itself with no local bookkeeping to fall out of step.
-
--device-namelabels the box, so a household with more than one player can tell them apart.
This is the only thing the export token can write, and it stays narrow — it appends intervals for channels already on the account and nothing else. Leave the flag off and nothing is ever written.
tvdinner 'tvtimess://tv.example.com?token=...' --sync-favourites
Stars set in the tvtimes web app appear in tvdinner's guide, read from that account's favourites feed at startup.
Additive and one-way. Un-starring in tvtimes never removes a
favourite here. favorites.json records only channel names, with no note
of where each came from, so a two-way reconcile couldn't tell "removed
upstream" from "added locally" -- and quietly deleting a favourite you
set yourself is the worse failure of the two. Press h to un-star it
here.
T (shift-t) opens the tvtimes web app for whatever's on the current
channel -- the reverse of tvtimes' own Play button.
It lands on tvtimes' search page for the programme title rather than the exact guide cell. tvtimes' grid is virtualised, so pointing at one cell would need scroll-to-row support there; finding the thing by name is what you actually want from this end, and it needs nothing. With no EPG data for the channel it just opens tvtimes itself.
tvdinner 'tvtimess://tv.example.com?token=...' \
--record-watchlist \
--report-watch-state --device-name 'living room' \
--sync-favourites
Every one of these rides the same export token -- there's no second credential and no per-feature pairing. The feeds behind them are ordinary HTTP and are documented as OpenAPI, if you want to build something else against the same account: tvtimes Export API. tvtimes' own Pairing with tvdinner page covers the other side of each.
tvtimes' Play button on a programme emits a tvdinner: link that
carries just that one channel (plus its own guide). That's a different,
lighter hand-off — see the
README.
Use tvtimes:// when you want the whole line-up; use Play when you just
want to watch the thing you're looking at.
Like the Xtream/Stalker/Plex
cases, a tvtimes:// URL's token is stored as plain text wherever the
source URL itself is stored (bookmarks.json, backup archives), and is
redacted before it reaches the log file. Anyone holding it can read your
line-up and stream through it — treat it as a password.