EPGStation: a browser front end for Mirakurun DTV recording on the Raspberry Pi
Mirakurun/mirakc を使用した録画管理ソフト
At a glance
- What is it?
- EPGStation is a TypeScript web application that sits in front of Mirakurun or mirakc and turns them into a recording and programme guide system with a mobile friendly interface, rules based reservations, subtitles and low latency live viewing. It suits a household server that records broadcast television, and it is a front end rather than a tuner stack, so it needs a working Mirakurun behind it.
- Who is it for?
- EPGStation fits a household or small office server that already runs Mirakurun or mirakc and wants a proper programme guide, rule based reservations and a phone friendly interface on top of it, and it does not fit someone who needs the tuner server itself, because the README assumes one of those is already there.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A front end, and the tuner stack it expects to find
EPGStation is a recording management application that uses Mirakurun, and the README is direct about the relationship. The project description calls it a recording management application using Mirakurun and mirakc, and the working environment section states that you need Mirakurun at ^3.8.0 or mirakc at ^3.1.10.
So the division of labour is clear. Mirakurun and mirakc are the pieces that talk to the DVB tuner and do the actual capture, and EPGStation is the layer that presents a programme guide, lets you schedule, and plays back what was recorded. That is a sensible split, because the tuner side is the hard and machine-specific part while the guide and reservation side is where a family or small office actually interacts.
The interface is the selling point. The README describes a mobile friendly web interface optimised for viewing on iOS and Android, and says it can also be operated from a PC with a modern UI. The screenshots in the README cover a dashboard, a live view, a programme detail, a recording screen, recorded programmes, reservations, rules and search, which is the full surface of a digital recorder.
The primary language is TypeScript, the licence is MIT, and the last push was on 2026-10-14 with no GitHub releases published, so the version to pin is the one in the package.json, which is 3.0.0-beta2.
There is a web API as well, with a document at docs/webapi.md, and the working environment section says you can check it with curl or wget against the config endpoint.
Reservations, rules, and the conflict warnings that matter
The feature list is grouped by what you do with a broadcast programme, and the first group is the one that decides whether the application is usable.
Everything is operated through a browser interface. The programme guide can be displayed, programmes can be searched, and reservations can be made per programme. The README lists three ways to make a reservation, and the distinction between them matters.
A manual reservation from the guide is the obvious one. A rule based automatic reservation is the useful one, since it captures the pattern rather than the instance. And the third item, warnings about conflicting or duplicated reservations, is the one that shows the author has thought about what happens when two rules both match the same slot.
That third item is where a recording system earns its keep, and it is the part that separates a real application from a thin wrapper. A rule that matches every Saturday evening anime and a manual reservation for a specific episode are the same reservation as far as the tuner is concerned, and the conflict has to be surfaced before it becomes a failed recording.
The rest of the group covers viewing. You can watch a programme that is currently on air with live viewing, and you can stream or download programmes that have already been recorded. Two browser side libraries do the work that would otherwise need a plugin, with aribb24.js providing subtitle and text super overlay display in the web, and mpegts.js providing the low latency live viewing function, with the setup documented separately at docs/caption-lowlatency-setup.md.
That choice matters technically. Rendering ARIB captions in a browser is a hard problem, because the format was designed for a television receiver's internal rendering, and doing it in JavaScript means the client does the work rather than a native player. The cost is that the low latency path depends on a specific library and its setup, and the benefit is that there is nothing to install on the viewing device, which for a phone is the whole point.
The database choice, and the recommended Docker build
The working environment section lists Node.js at 24.0.0 or later, FFmpeg, and one of two databases, and the database choice is not a small decision here.
SQLite3 is the default and needs no configuration, but the README is candid that it comes with limitations for the search function, and there is a separate document about enabling regular expression search with SQLite3. MySQL, with MariaDB as an alternative, is marked as recommended and does require configuration, with the character set set to utf8mb4, and there is a document about configuring it for Mirakurun 3.9.0-beta.24 and later. PostgreSQL is listed with a version requirement of 9.5 or above and struck through, which reads as a removed option rather than a deprecated one.
The nuance is that the search limitation is about regular expression support, not about search in general. If you mostly want to look up a programme by name, SQLite3 is workable. If you want to search the recorded archive with patterns, the MySQL route is the one the author has set up and documented.
For deployment, the README points at a prebuilt recommended environment, the docker-mirakurun-epgstation repository, and also links an example build with nvenc in a docker environment contributed by kazuki0824.
Two platform notes are worth carrying. The operating systems are listed as Linux and macOS, with Windows struck through, and the setup manual for Windows is also struck through in the setup section. And the v3 Docker image is for linux/amd64 and linux/arm64 only, with no 32-bit ARM image, because Node.js 24 and later do not publish a build for 32-bit ARM.
That last point is a real constraint for anyone who considered a 32-bit ARM board, and it is the kind of thing the README states once and does not repeat.
Building, updating, and the migration from v2
The update procedure is three commands, and the README is careful to sequence them.
$ git pull
$ npm run all-install
$ npm run buildYou run those and then restart EPGStation. The all-install script is defined in the package.json as npm i --no-save in the root and then the same in the client directory, so the server and the client front end are installed together, and the build script runs the server build and then the client build.
The migration notes are where the care is. To go from v2 to v3 you need a backup of the database and of config/, an update to Node.js 24 or later, and an update to config/enc.js, changing require to import. The details are in docs/migration-v2-to-v3.md, and the README asks you to check that document before updating from v2. There is a separate document for the v1 to v2 move at docs/v1migrate.md.
The last change is the interesting one, and it is a signal about the direction of the project. The package.json sets type to module, which is what makes import work at all in the config file, and it means the whole server is now an ES module project rather than a CommonJS one. That is a breaking change for anyone with a custom config or a plugin that expects require, and it is why the migration document exists.
The test and CI story is also described, for developers. The prerequisites are Docker, rootful with buildx, mise with a mise.toml pinning Node 24.21.0 and 26.11.1, a timezone of Asia/Tokyo, and git user configuration. The build uses npm run all-install and npm run build. Tests are split into server and client, with npm run test:server for the server and cd client && npm run test:run for the client, and npm run ci for both. The full check is npm run preflight -- --all, and the README explains that you confirm every step exited with 0 in the summary.tsv file in the log directory, which is what runs when accepting a pull request and before a public release.
Logs, backups, and what a backup actually covers
The operational detail in this README is better than most, and two parts of it deserve attention.
The logging section names the directories and the files in them. logs/EPGUpdater holds logs from the EPG update function, with system.log carrying access logs to Mirakurun and programme information update logs, while access.log and stream.log are essentially empty files. EPGStation/logs/Operator holds the recording management logs, with system.log covering access to Mirakurun, command execution and recording. EPGStation/logs/Service holds the web interface logs, with access.log for web interface access, stream.log for streaming delivery, system.log for the web server and encode.log for encoding.
The backup section is the one with a genuine trap. A database backup can include reservation information, recorded programme information, recording history, and recording reservation rules. The backup data does not depend on the database, so you can back it up with MySQL and restore it into SQLite3, which is genuinely useful for a migration.
But then there is the list of what is not included, and it is substantial: recorded files, thumbnails, drop logs, logs, and the config.yml configuration file. All of those need to be backed up separately by hand.
So a backup is two operations, not one, and the half that people forget is the half with the recordings in it.
npm run backup FILENAMEThe restore is the mirror image, and it has a precondition that is easy to miss. You write the new database configuration into config.yml first, and only then run the restore.
npm run restore FILENAMEFor a person running this on a home server, that is the difference between a system they can rebuild and a system that loses a season of recordings to a disk failure.
Client configuration, Kodi, and an Android performance note
Three smaller features round out the project, and the Android note is the most useful of them.
The client side configuration section covers URL scheme handling, so that video playback in EPGStation can be handed off to an application on the operating system. The configuration lives in config.yml, with the link in the configuration manual, and there are separate setup documents for macOS and for Windows. On the phone side, you install the app configured in config.yml, and for any environment not covered by those, the README says to configure it per browser through the web interface settings.
Kodi integration is supported, documented at docs/kodi.md, which matters for anyone with a home theatre setup who wants the recordings to appear in their media centre rather than in a browser.
The Android note is about a performance problem rather than a feature. If you have turned on a service that monitors operations under Android settings, accessibility, then the programme guide becomes markedly slower, and the examples given are LMT Launcher and Pie Control. The advice is to turn the service off, and if that is not possible, to try using Firefox instead.
That is a specific and honest piece of troubleshooting. It tells you the slowdown is not EPGStation's fault, it names the accessibility services that cause it, and it gives a browser workaround rather than only telling you to change a setting on the phone.
The remaining development files in the repository are worth a mention because they show how the project is built and tested: an api.yml with an api.d.ts beside it, an ormconfig.js for TypeORM, a set of vitest configuration files including mutation testing configurations, Stryker configs for the server, the database and delivery, an eslint configuration, a mise.toml pinning the Node versions, a .gitleaksignore and .devcontainer directory. The mutation testing setup in particular is a signal that the project treats its own regression risk as worth measuring.
Editorial conclusion
EPGStation fits a household or small office server that already runs Mirakurun or mirakc and wants a proper programme guide, rule based reservations and a phone friendly interface on top of it, and it does not fit someone who needs the tuner server itself, because the README assumes one of those is already there. Before deploying it, decide on the database, since SQLite3 is the default but is described as limited for search and MySQL is the recommended option, and read the v2 to v3 migration document, because the upgrade needs a database and config/ backup, Node.js 24 or later, and a change to config/enc.js from require to import.
Frequently asked questions
What does EPGStation need to run?
It needs Node.js 24.0.0 or later, FFmpeg, and either Mirakurun at ^3.8.0 or mirakc at ^3.1.10 providing the tuner side, plus one of the supported databases. SQLite3 is the default with no configuration but limited regular expression search, and MySQL or MariaDB is the recommended option.
How do I update EPGStation?
Run git pull, then npm run all-install, then npm run build, and restart EPGStation. If you are coming from v2, the README asks you to read docs/migration-v2-to-v3.md first, because the upgrade needs a database and config/ backup, Node.js 24 or later, and config/enc.js changed from require to import.
What is included in an EPGStation database backup?
Reservation information, recorded programme information, recording history and recording reservation rules. The recorded files, thumbnails, drop logs, logs and config.yml are not included and have to be backed up separately, and the backup data does not depend on the database, so a MySQL backup can be restored into SQLite3.
How are captions and low latency live viewing handled in EPGStation?
Both are done in the browser rather than by a native player. aribb24.js provides the subtitle and text super overlay display, and mpegts.js provides the low latency live viewing function, with the setup documented at docs/caption-lowlatency-setup.md.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/l3tnun-epgstation)Was this useful?