- Python 93.9%
- Nix 4.4%
- Just 0.9%
- Shell 0.8%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| resources | ||
| tests | ||
| tools | ||
| .gitignore | ||
| addon.xml | ||
| changelog.txt | ||
| default.nix | ||
| flake.lock | ||
| flake.nix | ||
| justfile | ||
| LICENSE | ||
| main.py | ||
| package.nix | ||
| README.md | ||
| shell.nix | ||
NRK TV for Kodi
A Kodi addon for NRK TV, built on the same API that powers the NRK website.
The goal is to make NRK's catalogue browsable. Existing addons expose NRK as a tree of menus, which is fine if you already know what you want to watch but useless for finding out what is actually available. This addon gives you the real front page, the editorial sections, and — most importantly — a complete A–Z overview of every series NRK currently offers, rendered as a poster wall with plots, artwork and cast information.
At the time of writing that A–Z contains 1663 series, built in about 2.5 seconds.
Features
- Complete series overview. "Alle serier A–Å" across the whole catalogue,
and a per-category equivalent on every genre page. De-duplicated and sorted
using Norwegian collation (Æ/Ø/Å last, but
Á/Šfiled under A/S so Sami titles do not get exiled to the end). - NRK's own front page and editorial sections — "Mest sett", "Krim", "Klassiske NRK-serier" and so on.
- Proper Kodi metadata.
tvshow/season/episodemedia types, plots, posters, fanart, clearlogos, duration, production year, age rating, premiere date, and cast/director/writer. This is what makes skins render poster walls and lets Kodi track watched state. - Live TV with the current programme shown per channel.
- Search, with persistent history (typing on a remote is miserable).
- Adaptive streaming through
inputstream.adaptive, with an optional resolution cap for low-powered devices. - Norwegian subtitles, with a choice of regular or hard-of-hearing.
Requirements
- Kodi 19 (Matrix) or newer. Tested against Kodi 21 (Omega).
script.module.requests,script.module.routing,script.module.inputstreamhelper— all in the official Kodi repository.inputstream.adaptive(recommended, not strictly required).
NRK geo-restricts most content to Norway.
Installation
On NixOS
The addon ships as a Nix package, which is the only sane route on NixOS since Kodi's addon directory is read-only in the store.
With flakes, add the input:
inputs.nrk-plugin.url = "github:blund/nrk-plugin";
# or, while developing locally:
# inputs.nrk-plugin.url = "path:/home/blund/prosjekt/nrk2";
then bundle it into your Kodi package. With the apps.kodi module in
rpi-cluster:
{ inputs, pkgs, ... }:
{
apps.kodi.enable = true;
apps.kodi.package = pkgs.kodi-gbm.withPackages (kodiPkgs: [
inputs.nrk-plugin.packages.${pkgs.system}.nrk-plugin
]);
}
withPackages pulls in requests, routing, inputstreamhelper and
inputstream-adaptive automatically — they are declared as propagated inputs.
Without flakes, using callPackage:
{ pkgs, ... }:
let
nrk-plugin = pkgs.callPackage (fetchGit {
url = "https://github.com/blund/nrk-plugin";
ref = "main";
}) { };
in
{
apps.kodi.package = pkgs.kodi-gbm.withPackages (_: [ nrk-plugin ]);
}
Then rebuild and restart Kodi:
sudo nixos-rebuild switch --flake .#<host>
sudo systemctl restart kodi
Note on the Raspberry Pi.
pkgs.rpi.kodi-gbm(thenixos-raspberrypituned build) is not in the binary cache and will build from source. Plainpkgs.kodi-gbmsubstitutes fine and is whatapps.kodidefaults to. On a Pi, also consider setting the addon's Maximum resolution to 1080p.
On any other Kodi (LibreELEC, Windows, macOS, generic Linux)
Build a zip and install it from the Kodi UI:
just package # or: ./tools/package.sh
This writes dist/plugin.video.nrk-plugin-<version>.zip. Then, in Kodi:
Settings → Add-ons → Install from zip file, and point it at the zip. You will need "Unknown sources" enabled under Settings → System → Add-ons.
Alternatively copy the addon directory straight into your Kodi profile:
cp -r . ~/.kodi/addons/plugin.video.nrk-plugin
and restart Kodi. Install script.module.requests, script.module.routing and
script.module.inputstreamhelper from the official repository first.
Settings
| Setting | Default | Notes |
|---|---|---|
| Enable subtitles | on | |
| Subtitle type | Regular | Regular / hard-of-hearing (SDH) / all |
| Use InputStream Adaptive | on | Better seeking and adaptive bitrate |
| Maximum resolution | Unlimited | Cap this on a Pi or similar |
| Open the NRK front page on start | off | Skip the main menu |
| Skip season list for single season series | on | |
| Hide unavailable programmes | off | Hides expired and not-yet-published items |
| Prefer poster artwork | on | Portrait posters instead of landscape stills |
| Cache API responses | on | Strongly recommended |
| Cache lifetime | 60 min |
Development
nix-shell # python + requests + pytest
pytest # 150 tests, no network needed
The addon is layered so that everything except the two Kodi-facing modules can be imported and tested outside Kodi:
| Module | Responsibility | Imports Kodi? |
|---|---|---|
api.py |
HTTP, TTL disk cache, parallel fetch | no |
models.py |
psapi JSON → Item / Section |
no |
browse.py |
aggregation, de-duplication, A–Z collation | no |
playback.py |
manifest → Stream, subtitle selection |
no |
history.py |
search history | no |
kodi.py |
settings, logging, ListItem construction |
yes |
addon.py |
routes | yes |
tests/stubs/ contains stand-ins for xbmc, xbmcgui, xbmcplugin,
xbmcaddon, xbmcvfs, routing and inputstreamhelper, so the full route
layer is exercised in CI without a device.
Tools
python tools/probe.py az # build the A-Z against the live API
python tools/probe.py page dokumentar # inspect one page's sections
python tools/probe.py series skam # seasons + episodes
python tools/smoke.py # walk every route against the live API
python tools/stress.py 80 # parse 80 random real series, report problems
python tools/record_fixtures.py # refresh tests/fixtures from live
tools/smoke.py and tools/stress.py are the ones to run after NRK changes
something: the fixture-based tests will keep passing against stale recordings,
but these hit the live service.
Notes on the NRK API
- The catalogue lives under
/tv/pages(categories) and/tv/pages/frontpage. Each page holds sections, each section holds plugs withtargetTypeofseries,episode,standaloneProgram,channel,liveChannelProgramorpage. /tv/catalog/series/<id>returns every season and every episode of asequentialseries in one response. Do not fetch per episode.- Series come in three shapes, and they behave differently:
sequential— numbered seasons, episodes embedded.standard— seasons are years, episodes not embedded, so each season needs its own request. Årsrevyen has 47 of them.news— "seasons" are calendar months (202608), which is useless for browsing; use/instalmentsinstead.
- Playback manifests are tokenised and short-lived. Never cache them, and only fetch them when the user actually presses play.
- Image lists come in three different shapes depending on endpoint
(
uri/width,imageUrl/pixelWidth,url/width).
Licence
GPL-3.0-or-later. Not affiliated with or endorsed by NRK.