NX-Cast is a Nintendo Switch homebrew DLNA receiver and IPTV player for Atmosphere.
It accepts media URLs from phones, desktop players, and TV apps as a generic DLNA DMR, and it can independently browse and play local or remote M3U IPTV sources. Both paths use the same hardware-accelerated libmpv playback session.
The current baseline includes:
- DLNA discovery through
SSDP - runtime
Description.xmland serviceSCPD SOAPactions forSetAVTransportURI,Play,Pause,Stop,Seek, and volumeGENAevent subscriptions andLastChange- protocol state synced from the real playback session
libmpvbackend withao=hosdeko3d/libmpv render APIas the preferred video path- runtime
hwdec=nvtegrapreference when the installed media toolchain supports it - static home screen with cast instructions and last-error display
- local/remote M3U source management, SD cache, and direct IPTV URL input
- channel groups, search, favorites, recent history, logo cache, and XMLTV now/next EPG
- controller and touch playback overlay
- Docker and GitHub Actions release builds
This project is still experimental Switch homebrew. Current development is focused on DLNA interoperability, playback stability, and the player UI.
NX-Cast is not currently:
- a DLNA media server (
DMS) - a DLNA media controller (
DMC) - an AirPlay receiver
- a source-native app or channel provider for iQiyi, MangoTV, CCTV, or Bilibili
- a DRM bypass or site login implementation
The playback path intentionally stays thin: DLNA provides the URL, then libmpv/FFmpeg handles probing, networking, demuxing, decoding, and playback.
IPTV is a supported release feature, not a separate experimental build. NX-Cast can import local or remote M3U/M3U8 playlists, classify channel lists versus direct HLS streams, cache remote sources on the SD card, and browse channels from the Home screen or over a playing video.
The IPTV browser includes playlist groups, search, Favorites, Recent, persistent source management, asynchronous logo caching, and plain/gzip XMLTV current/next programme information. Users provide their own authorized playlists and optional programme-guide URLs; NX-Cast does not bundle subscription access or bypass DRM.
See docs/iptv.md for supported formats, SD-card paths, source configuration, controls, and current limitations.
Use the SD card package when possible:
- Download
NX-Cast-sdmc.zipfrom the GitHub Release. - Extract it to the root of the Switch SD card.
- Launch
switch/NX-Cast/NX-Cast.nrofromhbmenu.
The package layout is:
switch/
NX-Cast/
NX-Cast.nro
dlna/
fonts/
iptv/
NX-Cast-sdmc.zip is already laid out like the SD card. Extract it directly to the SD root; do not put it inside an extra nested folder.
switch/NX-Cast/dlna/ contains runtime DLNA XML, CSV, HTML, and icon assets. switch/NX-Cast/fonts/ contains the packaged UI font and license notices. Put local .m3u or .m3u8 playlists in switch/NX-Cast/iptv/.
For full install and troubleshooting details, see docs/install.md.
When idle, the app shows a home screen with basic casting instructions, runtime status, and only the latest error. Full log history is kept for debugging but is not shown as the release foreground UI.
On the home screen:
Xor either stick click: open IPTV; inside IPTV,Xswitches between Channels and SourcesA: return to the active player from Home, or play the selected IPTV channelUp/Downor either stick vertically: select a channelLeft/Right, either stick horizontally, orL/R: move one pageY: favorite a channel, add a remote source, or refresh all sources from HomeZL/ZR: cycle channel filters;ZRconfigures XMLTV on SourcesL3/R3: search channels / clear search-: open a media or M3U URL; playlist URLs are imported into Channels instead of played as one streamB: close the IPTV browser- touch: tap a row to select it, tap it again or tap
PLAY CHANNELto play; swipe the list or use the on-screen arrows to change page
NX-Cast accepts input from every connected standard controller. A single horizontal Joy-Con can browse with its stick, click the stick to open IPTV, use SR to confirm, and use SL to return. A paired Joy-Con set, handheld controls, Pro Controller, and touch screen can each complete channel selection independently.
During video playback:
A: play / pauseB: return to Home without stopping playbackXor either stick click: open the IPTV channel menu over the current video;Aswitches channel andBcloses the menu+: exit the app-: show controlsLorLeft: seek backward 10 secondsRorRight: seek forward 10 secondsUp/Down: volume up / down- left or right stick horizontal: seek
- left or right stick vertical: volume
- touch screen tap: show controls
- touch center button while controls are visible: play / pause
- touch and drag the progress bar: preview target time, release to seek
main
-> iptv
-> local/remote M3U cache and classification
-> channel filters, favorites, logos, and XMLTV EPG
-> protocol/dlna
-> discovery
-> description
-> control
-> protocol_state
-> protocol/http
-> player
-> core
-> backend
-> render
-> ui
Important state flow:
SetAVTransportURI
-> renderer_set_uri
-> libmpv loadfile
-> libmpv properties/events
-> PlayerSnapshot / PlayerEvent
-> protocol_state
-> SOAP query / GENA notify
Protocol commands go down to the player. Real runtime state comes back up from the player and becomes the protocol-observed state.
This is the easiest path. It uses the same media packages as GitHub Actions and produces a release-ready SD package.
./scripts/docker_build_release.shOutputs:
dist/NX-Cast.nro
dist/NX-Cast-sdmc.zip
The Docker build installs the current recommended wiliwili media packages:
libuamswitch-ffmpegswitch-libmpv_deko3d
Requirements:
devkitProdevkitA64libnxswitch-libmpv_deko3dswitch-ffmpeglibuam
Install the current recommended prebuilt media packages:
base_url="https://github.com/xfangfang/wiliwili/releases/download/v0.1.0"
sudo dkp-pacman -U \
"$base_url/libuam-f8c9eef01ffe06334d530393d636d69e2b52744b-1-any.pkg.tar.zst" \
"$base_url/switch-ffmpeg-7.1-1-any.pkg.tar.zst" \
"$base_url/switch-libmpv_deko3d-0.36.0-2-any.pkg.tar.zst"Build:
source /opt/devkitpro/switchvars.sh
make NXCAST_USE_IMGUI_UI=1 NXCAST_REQUIRE_LIBMPV=1 NXCAST_REQUIRE_DEKO3D=1 -j2
NXCAST_MIN_NRO_SIZE=5000000 ./scripts/package_release.shNXCAST_USE_IMGUI_UI=1 enables the Dear ImGui + deko3d player overlay. Omit it to build the legacy C overlay path for fallback debugging. The strict flags prevent accidentally producing a tiny mock/fallback NRO without libmpv/deko3d.
Trace build for playback/input debugging:
source /opt/devkitpro/switchvars.sh
make TRACE_MEDIA=1 TRACE_INPUT=1 NXCAST_USE_IMGUI_UI=1 NXCAST_REQUIRE_LIBMPV=1 NXCAST_REQUIRE_DEKO3D=1 -j2The trace flags are optional build variables, not the default build mode. Use them for reproducing UI stutter, touch handling, SOAP/player state drift, or hard-to-read playback failures.
GitHub Actions uses the same Dockerfile and media package versions as local Docker builds.
Development build:
git pushAny branch push builds the project and updates the rolling prerelease:
- Release name:
NX-Cast Continuous - Tag:
continuous - Assets:
NX-Cast.nro,NX-Cast-sdmc.zip
Formal release:
git tag -a v0.2.0 -m "NX-Cast v0.2.0"
git push origin v0.2.0The release workflow requires libmpv/deko3d and rejects obviously invalid small NRO outputs.
See CHANGELOG.md for version history and release details.
assets/
dlna/ runtime DLNA templates copied to SD
icon/ NRO icon sources
iptv/ IPTV source examples and packaged presets
docs/ design notes and implementation plans
scripts/ build, packaging, nxlink, smoke tests
source/
iptv/
log/
player/
backend/
core/
render/
ui/
protocol/
dlna/
http/
Generated directories are ignored:
build/
dist/
sdmc/
artifacts/
logs/
Start with docs/README.md.
Recommended order:
- docs/dmr-implementation.md
- docs/player-layer.md
- docs/render-design.md
- docs/scpd-module.md
- docs/iptv.md
- docs/iptv-gui-plan.md
If documentation and source disagree, the current source/ tree is authoritative.