Merge pull request #159865 from midchildan/update/epgstation

epgstation: 1.7.5 -> 2.6.20
This commit is contained in:
Kevin Cox 2022-03-12 13:42:49 -05:00 committed by GitHub
commit 3222d8665d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 5667 additions and 2876 deletions

View file

@ -826,6 +826,58 @@
include serif fonts.
</para>
</listitem>
<listitem>
<para>
<literal>pkgs.epgstation</literal> has been upgraded from v1
to v2, resulting in incompatible changes in the database
scheme and configuration format.
</para>
</listitem>
<listitem>
<para>
Some top-level settings under
<link linkend="opt-services.epgstation.enable">services.epgstation</link>
is now deprecated because it was redudant due to the same
options being present in
<link linkend="opt-services.epgstation.settings">services.epgstation.settings</link>.
</para>
</listitem>
<listitem>
<para>
The option <literal>services.epgstation.basicAuth</literal>
was removed because basic authentication support was dropped
by upstream.
</para>
</listitem>
<listitem>
<para>
The option
<link linkend="opt-services.epgstation.database.passwordFile">services.epgstation.database.passwordFile</link>
no longer has a default value. Make sure to set this option
explicitly before upgrading. Change the database password if
necessary.
</para>
</listitem>
<listitem>
<para>
The
<link linkend="opt-services.epgstation.settings">services.epgstation.settings</link>
option now expects options for <literal>config.yml</literal>
in EPGStation v2.
</para>
</listitem>
<listitem>
<para>
Existing data for the
<link linkend="opt-services.epgstation.enable">services.epgstation</link>
module would have to be backed up prior to the upgrade. To
back up exising data to
<literal>/tmp/epgstation.bak</literal>, run
<literal>sudo -u epgstation epgstation run backup /tmp/epgstation.bak</literal>.
To import that data after to the upgrade, run
<literal>sudo -u epgstation epgstation run v1migrate /tmp/epgstation.bak</literal>
</para>
</listitem>
<listitem>
<para>
<literal>switch-to-configuration</literal> (the script that is

View file

@ -321,6 +321,30 @@ In addition to numerous new and upgraded packages, this release has the followin
`pkgs.noto-fonts-cjk` is currently an alias of `pkgs.noto-fonts-cjk-sans` and
doesn't include serif fonts.
- `pkgs.epgstation` has been upgraded from v1 to v2, resulting in incompatible
changes in the database scheme and configuration format.
- Some top-level settings under [services.epgstation](#opt-services.epgstation.enable)
is now deprecated because it was redudant due to the same options being
present in [services.epgstation.settings](#opt-services.epgstation.settings).
- The option `services.epgstation.basicAuth` was removed because basic
authentication support was dropped by upstream.
- The option [services.epgstation.database.passwordFile](#opt-services.epgstation.database.passwordFile)
no longer has a default value. Make sure to set this option explicitly before
upgrading. Change the database password if necessary.
- The [services.epgstation.settings](#opt-services.epgstation.settings)
option now expects options for `config.yml` in EPGStation v2.
- Existing data for the [services.epgstation](#opt-services.epgstation.enable)
module would have to be backed up prior to the upgrade. To back up exising
data to `/tmp/epgstation.bak`, run
`sudo -u epgstation epgstation run backup /tmp/epgstation.bak`.
To import that data after to the upgrade, run
`sudo -u epgstation epgstation run v1migrate /tmp/epgstation.bak`
- `switch-to-configuration` (the script that is run when running `nixos-rebuild switch` for example) has been reworked
* The interface that allows activation scripts to restart units has been streamlined. Restarting and reloading is now done by a single file `/run/nixos/activation-restart-list` that honors `restartIfChanged` and `reloadIfChanged` of the units.
* Preferring to reload instead of restarting can still be achieved using `/run/nixos/activation-reload-list`.

View file

@ -1,30 +1,40 @@
{ config, lib, options, pkgs, ... }:
with lib;
let
cfg = config.services.epgstation;
opt = options.services.epgstation;
description = "EPGStation: DVR system for Mirakurun-managed TV tuners";
username = config.users.users.epgstation.name;
groupname = config.users.users.epgstation.group;
mirakurun = {
sock = config.services.mirakurun.unixSocket;
option = options.services.mirakurun.unixSocket;
};
settingsFmt = pkgs.formats.json {};
settingsTemplate = settingsFmt.generate "config.json" cfg.settings;
yaml = pkgs.formats.yaml { };
settingsTemplate = yaml.generate "config.yml" cfg.settings;
preStartScript = pkgs.writeScript "epgstation-prestart" ''
#!${pkgs.runtimeShell}
PASSWORD="$(head -n1 "${cfg.basicAuth.passwordFile}")"
DB_PASSWORD="$(head -n1 "${cfg.database.passwordFile}")"
DB_PASSWORD_FILE=${lib.escapeShellArg cfg.database.passwordFile}
if [[ ! -f "$DB_PASSWORD_FILE" ]]; then
printf "[FATAL] File containing the DB password was not found in '%s'. Double check the NixOS option '%s'." \
"$DB_PASSWORD_FILE" ${lib.escapeShellArg opt.database.passwordFile} >&2
exit 1
fi
DB_PASSWORD="$(head -n1 ${lib.escapeShellArg cfg.database.passwordFile})"
# setup configuration
touch /etc/epgstation/config.json
chmod 640 /etc/epgstation/config.json
touch /etc/epgstation/config.yml
chmod 640 /etc/epgstation/config.yml
sed \
-e "s,@password@,$PASSWORD,g" \
-e "s,@dbPassword@,$DB_PASSWORD,g" \
${settingsTemplate} > /etc/epgstation/config.json
chown "${username}:${groupname}" /etc/epgstation/config.json
${settingsTemplate} > /etc/epgstation/config.yml
chown "${username}:${groupname}" /etc/epgstation/config.yml
# NOTE: Use password authentication, since mysqljs does not yet support auth_socket
if [ ! -e /var/lib/epgstation/db-created ]; then
@ -35,7 +45,7 @@ let
'';
streamingConfig = lib.importJSON ./streaming.json;
logConfig = {
logConfig = yaml.generate "logConfig.yml" {
appenders.stdout.type = "stdout";
categories = {
default = { appenders = [ "stdout" ]; level = "info"; };
@ -45,53 +55,51 @@ let
};
};
defaultPassword = "INSECURE_GO_CHECK_CONFIGURATION_NIX\n";
# Deprecate top level options that are redundant.
deprecateTopLevelOption = config:
lib.mkRenamedOptionModule
([ "services" "epgstation" ] ++ config)
([ "services" "epgstation" "settings" ] ++ config);
removeOption = config: instruction:
lib.mkRemovedOptionModule
([ "services" "epgstation" ] ++ config)
instruction;
in
{
options.services.epgstation = {
enable = mkEnableOption "EPGStation: DTV Software in Japan";
meta.maintainers = with lib.maintainers; [ midchildan ];
usePreconfiguredStreaming = mkOption {
type = types.bool;
imports = [
(deprecateTopLevelOption [ "port" ])
(deprecateTopLevelOption [ "socketioPort" ])
(deprecateTopLevelOption [ "clientSocketioPort" ])
(removeOption [ "basicAuth" ]
"Use a TLS-terminated reverse proxy with authentication instead.")
];
options.services.epgstation = {
enable = lib.mkEnableOption description;
package = lib.mkOption {
default = pkgs.epgstation;
type = lib.types.package;
defaultText = lib.literalExpression "pkgs.epgstation";
description = "epgstation package to use";
};
usePreconfiguredStreaming = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Use preconfigured default streaming options.
Upstream defaults:
<link xlink:href="https://github.com/l3tnun/EPGStation/blob/master/config/config.sample.json"/>
<link xlink:href="https://github.com/l3tnun/EPGStation/blob/master/config/config.yml.template"/>
'';
};
port = mkOption {
type = types.port;
default = 20772;
description = ''
HTTP port for EPGStation to listen on.
'';
};
socketioPort = mkOption {
type = types.port;
default = cfg.port + 1;
defaultText = literalExpression "config.${opt.port} + 1";
description = ''
Socket.io port for EPGStation to listen on.
'';
};
clientSocketioPort = mkOption {
type = types.port;
default = cfg.socketioPort;
defaultText = literalExpression "config.${opt.socketioPort}";
description = ''
Socket.io port that the web client is going to connect to. This may be
different from <option>socketioPort</option> if EPGStation is hidden
behind a reverse proxy.
'';
};
openFirewall = mkOption {
type = types.bool;
openFirewall = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Open ports in the firewall for the EPGStation web interface.
@ -106,50 +114,17 @@ in
'';
};
basicAuth = {
user = mkOption {
type = with types; nullOr str;
default = null;
example = "epgstation";
description = ''
Basic auth username for EPGStation. If <literal>null</literal>, basic
auth will be disabled.
<warning>
<para>
Basic authentication has known weaknesses, the most critical being
that it sends passwords over the network in clear text. Use this
feature to control access to EPGStation within your family and
friends, but don't rely on it for security.
</para>
</warning>
'';
};
passwordFile = mkOption {
type = types.path;
default = pkgs.writeText "epgstation-password" defaultPassword;
defaultText = literalDocBook ''a file containing <literal>${defaultPassword}</literal>'';
example = "/run/keys/epgstation-password";
description = ''
A file containing the password for <option>basicAuth.user</option>.
'';
};
};
database = {
name = mkOption {
type = types.str;
database = {
name = lib.mkOption {
type = lib.types.str;
default = "epgstation";
description = ''
Name of the MySQL database that holds EPGStation's data.
'';
};
passwordFile = mkOption {
type = types.path;
default = pkgs.writeText "epgstation-db-password" defaultPassword;
defaultText = literalDocBook ''a file containing <literal>${defaultPassword}</literal>'';
passwordFile = lib.mkOption {
type = lib.types.path;
example = "/run/keys/epgstation-db-password";
description = ''
A file containing the password for the database named
@ -158,69 +133,106 @@ in
};
};
settings = mkOption {
# The defaults for some options come from the upstream template
# configuration, which is the one that users would get if they follow the
# upstream instructions. This is, in some cases, different from the
# application defaults. Some options like encodeProcessNum and
# concurrentEncodeNum doesn't have an optimal default value that works for
# all hardware setups and/or performance requirements. For those kind of
# options, the application default wouldn't always result in the expected
# out-of-the-box behavior because it's the responsibility of the user to
# configure them according to their needs. In these cases, the value in the
# upstream template configuration should serve as a "good enough" default.
settings = lib.mkOption {
description = ''
Options to add to config.json.
Options to add to config.yml.
Documentation:
<link xlink:href="https://github.com/l3tnun/EPGStation/blob/master/doc/conf-manual.md"/>
'';
default = {};
default = { };
example = {
recPriority = 20;
conflictPriority = 10;
};
type = types.submodule {
freeformType = settingsFmt.type;
type = lib.types.submodule {
freeformType = yaml.type;
options.readOnlyOnce = mkOption {
type = types.bool;
default = false;
description = "Don't reload configuration files at runtime.";
options.port = lib.mkOption {
type = lib.types.port;
default = 20772;
description = ''
HTTP port for EPGStation to listen on.
'';
};
options.mirakurunPath = mkOption (let
sockPath = config.services.mirakurun.unixSocket;
in {
type = types.str;
default = "http+unix://${replaceStrings ["/"] ["%2F"] sockPath}";
defaultText = literalExpression ''
"http+unix://''${replaceStrings ["/"] ["%2F"] config.${options.services.mirakurun.unixSocket}}"
options.socketioPort = lib.mkOption {
type = lib.types.port;
default = cfg.settings.port + 1;
defaultText = lib.literalExpression "config.${opt.settings}.port + 1";
description = ''
Socket.io port for EPGStation to listen on. It is valid to share
ports with <option>${opt.settings}.port</option>.
'';
};
options.clientSocketioPort = lib.mkOption {
type = lib.types.port;
default = cfg.settings.socketioPort;
defaultText = lib.literalExpression "config.${opt.settings}.socketioPort";
description = ''
Socket.io port that the web client is going to connect to. This may
be different from <option>${opt.settings}.socketioPort</option> if
EPGStation is hidden behind a reverse proxy.
'';
};
options.mirakurunPath = with mirakurun; lib.mkOption {
type = lib.types.str;
default = "http+unix://${lib.replaceStrings ["/"] ["%2F"] sock}";
defaultText = lib.literalExpression ''
"http+unix://''${lib.replaceStrings ["/"] ["%2F"] config.${option}}"
'';
example = "http://localhost:40772";
description = "URL to connect to Mirakurun.";
});
};
options.encode = mkOption {
type = with types; listOf attrs;
options.encodeProcessNum = lib.mkOption {
type = lib.types.ints.positive;
default = 4;
description = ''
The maximum number of processes that EPGStation would allow to run
at the same time for encoding or streaming videos.
'';
};
options.concurrentEncodeNum = lib.mkOption {
type = lib.types.ints.positive;
default = 1;
description = ''
The maximum number of encoding jobs that EPGStation would run at the
same time.
'';
};
options.encode = lib.mkOption {
type = with lib.types; listOf attrs;
description = "Encoding presets for recorded videos.";
default = [
{
name = "H264";
cmd = "${pkgs.epgstation}/libexec/enc.sh main";
name = "H.264";
cmd = "%NODE% ${cfg.package}/libexec/enc.js";
suffix = ".mp4";
default = true;
}
{
name = "H264-sub";
cmd = "${pkgs.epgstation}/libexec/enc.sh sub";
suffix = "-sub.mp4";
}
];
defaultText = literalExpression ''
defaultText = lib.literalExpression ''
[
{
name = "H264";
cmd = "''${pkgs.epgstation}/libexec/enc.sh main";
name = "H.264";
cmd = "%NODE% config.${opt.package}/libexec/enc.js";
suffix = ".mp4";
default = true;
}
{
name = "H264-sub";
cmd = "''${pkgs.epgstation}/libexec/enc.sh sub";
suffix = "-sub.mp4";
}
]
'';
@ -229,14 +241,25 @@ in
};
};
config = mkIf cfg.enable {
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = !(lib.hasAttr "readOnlyOnce" cfg.settings);
message = ''
The option config.${opt.settings}.readOnlyOnce can no longer be used
since it's been removed. No replacements are available.
'';
}
];
environment.etc = {
"epgstation/operatorLogConfig.json".text = builtins.toJSON logConfig;
"epgstation/serviceLogConfig.json".text = builtins.toJSON logConfig;
"epgstation/epgUpdaterLogConfig.yml".source = logConfig;
"epgstation/operatorLogConfig.yml".source = logConfig;
"epgstation/serviceLogConfig.yml".source = logConfig;
};
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = with cfg; [ port socketioPort ];
networking.firewall = lib.mkIf cfg.openFirewall {
allowedTCPPorts = with cfg.settings; [ port socketioPort ];
};
users.users.epgstation = {
@ -245,13 +268,13 @@ in
isSystemUser = true;
};
users.groups.epgstation = {};
users.groups.epgstation = { };
services.mirakurun.enable = mkDefault true;
services.mirakurun.enable = lib.mkDefault true;
services.mysql = {
enable = mkDefault true;
package = mkDefault pkgs.mariadb;
enable = lib.mkDefault true;
package = lib.mkDefault pkgs.mariadb;
ensureDatabases = [ cfg.database.name ];
# FIXME: enable once mysqljs supports auth_socket
# ensureUsers = [ {
@ -260,39 +283,28 @@ in
# } ];
};
services.epgstation.settings = let
defaultSettings = {
serverPort = cfg.port;
socketioPort = cfg.socketioPort;
clientSocketioPort = cfg.clientSocketioPort;
services.epgstation.settings =
let
defaultSettings = {
dbtype = lib.mkDefault "mysql";
mysql = {
socketPath = lib.mkDefault "/run/mysqld/mysqld.sock";
user = username;
password = lib.mkDefault "@dbPassword@";
database = cfg.database.name;
};
dbType = mkDefault "mysql";
mysql = {
user = username;
database = cfg.database.name;
socketPath = mkDefault "/run/mysqld/mysqld.sock";
password = mkDefault "@dbPassword@";
connectTimeout = mkDefault 1000;
connectionLimit = mkDefault 10;
ffmpeg = lib.mkDefault "${pkgs.ffmpeg-full}/bin/ffmpeg";
ffprobe = lib.mkDefault "${pkgs.ffmpeg-full}/bin/ffprobe";
# for disambiguation with TypeScript files
recordedFileExtension = lib.mkDefault ".m2ts";
};
basicAuth = mkIf (cfg.basicAuth.user != null) {
user = mkDefault cfg.basicAuth.user;
password = mkDefault "@password@";
};
ffmpeg = mkDefault "${pkgs.ffmpeg-full}/bin/ffmpeg";
ffprobe = mkDefault "${pkgs.ffmpeg-full}/bin/ffprobe";
fileExtension = mkDefault ".m2ts";
maxEncode = mkDefault 2;
maxStreaming = mkDefault 2;
};
in
mkMerge [
defaultSettings
(mkIf cfg.usePreconfiguredStreaming streamingConfig)
];
in
lib.mkMerge [
defaultSettings
(lib.mkIf cfg.usePreconfiguredStreaming streamingConfig)
];
systemd.tmpfiles.rules = [
"d '/var/lib/epgstation/streamfiles' - ${username} ${groupname} - -"
@ -301,15 +313,15 @@ in
];
systemd.services.epgstation = {
description = pkgs.epgstation.meta.description;
inherit description;
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
] ++ optional config.services.mirakurun.enable "mirakurun.service"
++ optional config.services.mysql.enable "mysql.service";
after = [ "network.target" ]
++ lib.optional config.services.mirakurun.enable "mirakurun.service"
++ lib.optional config.services.mysql.enable "mysql.service";
serviceConfig = {
ExecStart = "${pkgs.epgstation}/bin/epgstation start";
ExecStart = "${cfg.package}/bin/epgstation start";
ExecStartPre = "+${preStartScript}";
User = username;
Group = groupname;

View file

@ -1,119 +1,140 @@
{
"liveHLS": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 17 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
"urlscheme": {
"m2ts": {
"ios": "vlc-x-callback://x-callback-url/stream?url=PROTOCOL://ADDRESS",
"android": "intent://ADDRESS#Intent;package=org.videolan.vlc;type=video;scheme=PROTOCOL;end"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 17 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -flags +loop-global_header %OUTPUT%"
"video": {
"ios": "infuse://x-callback-url/play?url=PROTOCOL://ADDRESS",
"android": "intent://ADDRESS#Intent;package=com.mxtech.videoplayer.ad;type=video;scheme=PROTOCOL;end"
},
{
"name": "180p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 17 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -c:a aac -ar 48000 -b:a 48k -ac 2 -c:v libx264 -vf yadif,scale=-2:180 -b:v 100k -preset veryfast -maxrate 110k -bufsize 1000k -flags +loop-global_header %OUTPUT%"
"download": {
"ios": "vlc-x-callback://x-callback-url/download?url=PROTOCOL://ADDRESS&filename=FILENAME"
}
],
"liveMP4": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
}
],
"liveWebM": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 192k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:720 -b:v 3000k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 2 -c:a libvorbis -ar 48000 -b:a 128k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:480 -b:v 1500k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
}
],
"mpegTsStreaming": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -y -f mpegts pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -y -f mpegts pipe:1"
},
{
"name": "Original"
}
],
"mpegTsViewer": {
"ios": "vlc-x-callback://x-callback-url/stream?url=http://ADDRESS",
"android": "intent://ADDRESS#Intent;package=com.mxtech.videoplayer.ad;type=video;scheme=http;end"
},
"recordedDownloader": {
"ios": "vlc-x-callback://x-callback-url/download?url=http://ADDRESS&filename=FILENAME",
"android": "intent://ADDRESS#Intent;package=com.dv.adm;type=video;scheme=http;end"
},
"recordedStreaming": {
"webm": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 3 -c:a libvorbis -ar 48000 -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:720 %VB% %VBUFFER% %AB% %ABUFFER% -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1",
"vb": "3000k",
"ab": "192k"
},
{
"name": "360p",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 2 -c:a libvorbis -ar 48000 -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:360 %VB% %VBUFFER% %AB% %ABUFFER% -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1",
"vb": "1500k",
"ab": "128k"
"stream": {
"live": {
"ts": {
"m2ts": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -y -f mpegts pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -y -f mpegts pipe:1"
},
{
"name": "無変換"
}
],
"m2tsll": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -f mpegts -analyzeduration 500000 -i pipe:0 -map 0 -c:s copy -c:d copy -ignore_unknown -fflags nobuffer -flags low_delay -max_delay 250000 -max_interleave_delta 1 -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -flags +cgop -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -y -f mpegts pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -f mpegts -analyzeduration 500000 -i pipe:0 -map 0 -c:s copy -c:d copy -ignore_unknown -fflags nobuffer -flags low_delay -max_delay 250000 -max_interleave_delta 1 -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -flags +cgop -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -y -f mpegts pipe:1"
}
],
"webm": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 192k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:720 -b:v 3000k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 2 -c:a libvorbis -ar 48000 -b:a 128k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:480 -b:v 1500k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
}
],
"mp4": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
}
],
"hls": [
{
"name": "720p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -map 0 -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 17 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
},
{
"name": "480p",
"cmd": "%FFMPEG% -re -dual_mono_mode main -i pipe:0 -sn -map 0 -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 17 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -flags +loop-global_header %OUTPUT%"
}
]
}
],
"mp4": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -ac 2 -c:v libx264 -vf yadif,scale=-2:720 %VB% %VBUFFER% %AB% %ABUFFER% -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1",
"vb": "3000k",
"ab": "192k"
},
{
"name": "360p",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -ac 2 -c:v libx264 -vf yadif,scale=-2:360 %VB% %VBUFFER% %AB% %ABUFFER% -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1",
"vb": "1500k",
"ab": "128k"
}
],
"mpegTs": [
{
"name": "720p (H.264)",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -ac 2 -c:v libx264 -vf yadif,scale=-2:720 %VB% %VBUFFER% %AB% %ABUFFER% -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -y -f mpegts pipe:1",
"vb": "3000k",
"ab": "192k"
},
{
"name": "360p (H.264)",
"cmd": "%FFMPEG% -dual_mono_mode main %RE% -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -ac 2 -c:v libx264 -vf yadif,scale=-2:360 %VB% %VBUFFER% %AB% %ABUFFER% -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -y -f mpegts pipe:1",
"vb": "1500k",
"ab": "128k"
}
]
},
"recordedHLS": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -i %INPUT% -sn -threads 0 -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -i %INPUT% -sn -threads 0 -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -flags +loop-global_header %OUTPUT%"
},
{
"name": "480p(h265)",
"cmd": "%FFMPEG% -dual_mono_mode main -i %INPUT% -sn -map 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_type fmp4 -hls_fmp4_init_filename stream%streamNum%-init.mp4 -hls_segment_filename stream%streamNum%-%09d.m4s -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx265 -vf yadif,scale=-2:480 -b:v 350k -preset veryfast -tag:v hvc1 %OUTPUT%"
"recorded": {
"ts": {
"webm": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 192k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:720 -b:v 3000k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 128k -ac 2 -c:v libvpx-vp9 -vf yadif,scale=-2:480 -b:v 1500k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
}
],
"mp4": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
}
],
"hls": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -map 0 -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf yadif,scale=-2:720 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -i pipe:0 -sn -map 0 -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf yadif,scale=-2:480 -b:v 1500k -preset veryfast -flags +loop-global_header %OUTPUT%"
}
]
},
"encoded": {
"webm": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 192k -ac 2 -c:v libvpx-vp9 -vf scale=-2:720 -b:v 3000k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 3 -c:a libvorbis -ar 48000 -b:a 128k -ac 2 -c:v libvpx-vp9 -vf scale=-2:480 -b:v 1500k -deadline realtime -speed 4 -cpu-used -8 -y -f webm pipe:1"
}
],
"mp4": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 0 -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf scale=-2:720 -b:v 3000k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 0 -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf scale=-2:480 -b:v 1500k -profile:v baseline -preset veryfast -tune fastdecode,zerolatency -movflags frag_keyframe+empty_moov+faststart+default_base_moof -y -f mp4 pipe:1"
}
],
"hls": [
{
"name": "720p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 192k -ac 2 -c:v libx264 -vf scale=-2:720 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
},
{
"name": "480p",
"cmd": "%FFMPEG% -dual_mono_mode main -ss %SS% -i %INPUT% -sn -threads 0 -ignore_unknown -max_muxing_queue_size 1024 -f hls -hls_time 3 -hls_list_size 0 -hls_allow_cache 1 -hls_segment_filename %streamFileDir%/stream%streamNum%-%09d.ts -hls_flags delete_segments -c:a aac -ar 48000 -b:a 128k -ac 2 -c:v libx264 -vf scale=-2:480 -b:v 3000k -preset veryfast -flags +loop-global_header %OUTPUT%"
}
]
}
}
],
"recordedViewer": {
"ios": "infuse://x-callback-url/play?url=http://ADDRESS",
"android": "intent://ADDRESS#Intent;package=com.mxtech.videoplayer.ad;type=video;scheme=http;end"
}
}

View file

@ -0,0 +1,57 @@
{
"name": "epgstation-client",
"version": "2.6.20",
"private": true,
"scripts": {
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"watch": "vue-cli-service build --watch --mode development"
},
"dependencies": {
"@mdi/font": "6.5.95",
"aribb24.js": "1.8.8",
"axios": "0.24.0",
"eventemitter2": "6.4.5",
"hls.js": "1.1.2",
"inversify": "6.0.1",
"json-stable-stringify": "1.0.1",
"lodash": "4.17.21",
"material-design-icons-iconfont": "6.1.1",
"mpegts.js": "1.6.10",
"reflect-metadata": "0.1.13",
"resize-observer-polyfill": "1.5.1",
"roboto-fontface": "*",
"smoothscroll-polyfill": "0.4.4",
"socket.io-client": "4.3.2",
"typeface-roboto": "1.1.13",
"vue": "2.6.14",
"vue-class-component": "7.2.6",
"vue-property-decorator": "9.1.2",
"vue-router": "3.5.3",
"vuetify": "2.5.10",
"vuetify-datetime-picker": "2.1.1",
"@types/hls.js": "0.13.3",
"@types/json-stable-stringify": "1.0.33",
"@types/lodash": "4.14.178",
"@types/smoothscroll-polyfill": "0.3.1",
"@types/socket.io-client": "1.4.36",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
"@vue/cli-plugin-eslint": "4.5.12",
"@vue/cli-plugin-typescript": "4.5.13",
"@vue/cli-plugin-vuex": "4.5.13",
"@vue/cli-service": "4.5.13",
"@vue/eslint-config-prettier": "6.0.0",
"@vue/eslint-config-typescript": "7.0.0",
"eslint": "7.32.0",
"eslint-plugin-prettier": "3.4.1",
"eslint-plugin-vue": "7.20.0",
"prettier": "2.4.1",
"sass": "1.32.12",
"sass-loader": "10.2.0",
"typescript": "4.4.4",
"vue-cli-plugin-vuetify": "2.4.3",
"vue-template-compiler": "2.6.14",
"vuetify-loader": "1.7.3"
}
}

View file

@ -10,17 +10,18 @@
, nodePackages
, gzip
, jq
, yq
}:
let
# NOTE: use updateScript to bump the package version
pname = "EPGStation";
version = "1.7.5";
version = "2.6.20";
src = fetchFromGitHub {
owner = "l3tnun";
repo = "EPGStation";
rev = "v${version}";
sha256 = "06yaf5yb5rp3q0kdhw33df7px7vyfby885ckb6bdzw3wnams5d8m";
sha256 = "K1cAvmqWEfS6EY4MKAtjXb388XLYHtouxNM70PWgFig=";
};
workaround-opencollective-buildfailures = stdenv.mkDerivation {
@ -35,19 +36,44 @@ let
'';
};
pkg = nodePackages.epgstation.override (drv: {
client = nodePackages.epgstation-client.override (drv: {
# FIXME: remove this option if possible
#
# Unsetting this option resulted NPM attempting to re-download packages.
dontNpmInstall = true;
meta = drv.meta // {
inherit (nodejs.meta) platforms;
};
});
server = nodePackages.epgstation.override (drv: {
inherit src;
bypassCache = false;
# This is set to false to keep devDependencies at build time. Build time
# dependencies are pruned afterwards.
production = false;
buildInputs = [ bash ];
nativeBuildInputs = [
nodejs
workaround-opencollective-buildfailures
makeWrapper
nodePackages.node-pre-gyp
];
] ++ (with nodePackages; [
node-pre-gyp
node-gyp-build
]);
preRebuild = ''
# Fix for not being able to connect to mysql using domain sockets.
patch -p1 ${./use-mysql-over-domain-socket.patch}
patch -p1 < ${./use-mysql-over-domain-socket.patch}
# Workaround for https://github.com/svanderburg/node2nix/issues/275
sed -i -e "s|#!/usr/bin/env node|#! ${nodejs}/bin/node|" node_modules/node-gyp-build/bin.js
find . -name package-lock.json -delete
'';
postInstall = let
@ -56,12 +82,19 @@ let
''
mkdir -p $out/{bin,libexec,share/doc/epgstation,share/man/man1}
pushd $out/lib/node_modules/EPGStation
pushd $out/lib/node_modules/epgstation
cp -r ${client}/lib/node_modules/epgstation-client/node_modules client/node_modules
chmod -R u+w client/node_modules
npm run build
npm prune --production
mv config/{enc.sh,enc.js} $out/libexec
npm prune --production
pushd client
npm prune --production
popd
mv config/enc.js.template $out/libexec/enc.js
mv LICENSE Readme.md $out/share/doc/epgstation
mv doc/* $out/share/doc/epgstation
sed 's/@DESCRIPTION@/${drv.meta.description}/g' ${./epgstation.1} \
@ -82,8 +115,9 @@ let
ln -sfT /var/lib/epgstation/thumbnail thumbnail
makeWrapper ${nodejs}/bin/npm $out/bin/epgstation \
--run "cd $out/lib/node_modules/EPGStation" \
--prefix PATH : ${lib.makeBinPath runtimeDeps}
--run "cd $out/lib/node_modules/epgstation" \
--prefix PATH : ${lib.makeBinPath runtimeDeps} \
--set APP_ROOT_PATH "$out/lib/node_modules/epgstation"
popd
'';
@ -99,22 +133,25 @@ let
common-updater-scripts
genericUpdater
writers
jq;
jq
yq;
};
# nodePackages.epgstation is a stub package to fetch npm dependencies and
# is marked as broken to prevent users from installing it directly. This
# technique ensures epgstation can share npm packages with the rest of
# nixpkgs while still allowing us to heavily customize the build. It also
# allows us to provide devDependencies for the epgstation build process
# without doing the same for all the other node packages.
meta = drv.meta // { broken = false; };
# its meta.platforms is made empty to prevent users from installing it
# directly. This technique ensures epgstation can share npm packages with
# the rest of nixpkgs while still allowing us to heavily customize the
# build. It also allows us to provide devDependencies for the epgstation
# build process without doing the same for all the other node packages.
meta = drv.meta // {
inherit (nodejs.meta) platforms;
};
});
in
pkg // {
server // {
name = "${pname}-${version}";
meta = with lib; pkg.meta // {
meta = with lib; server.meta // {
maintainers = with maintainers; [ midchildan ];
# NOTE: updateScript relies on this being correct

View file

@ -27,7 +27,7 @@ platforms, run
to start EPGStation.
.Sh FILES
.Bl -tag -width Ds -compact
.It Pa /etc/epgstation/config.json
.It Pa /etc/epgstation/config.yml
.Nm
configuration file.
.El
@ -48,5 +48,9 @@ Restore the EPGstation database.
.Pp
.Dl $ epgstation run restore /path/to/src
.Pp
Restore the EPGstation database from the prior v1 release.
.Pp
.Dl $ epgstation run v1migrate /path/to/src
.Pp
.Sh SEE ALSO
.Xr npm 1

View file

@ -1,85 +1,72 @@
{
"name": "EPGStation",
"version": "1.7.5",
"name": "epgstation",
"version": "2.6.20",
"description": "DTV Software in Japan.",
"repository": {
"type": "git",
"url": "https://github.com/l3tnun/EPGStation.git"
"url": "git+https://github.com/l3tnun/EPGStation-V2.git"
},
"author": "l3tnun",
"license": "MIT",
"bugs": {
"url": "https://github.com/l3tnun/EPGStation/issues"
},
"homepage": "https://github.com/l3tnun/EPGStation#readme",
"engines": {
"node": "^10.x.x < 11 || ^12.14.0 < 13 || ^14.5.0 < 15"
"url": "https://github.com/l3tnun/EPGStation-V2/issues"
},
"homepage": "https://github.com/l3tnun/EPGStation-V2#readme",
"dependencies": {
"aribts": "^2.1.12",
"b24.js": "1.0.3",
"basic-auth": "2.0.1",
"arib-subtitle-timedmetadater": "4.0.9",
"aribts": "2.1.12",
"axios": "0.24.0",
"body-parser": "1.19.0",
"chart.js": "2.9.3",
"css-ripple-effect": "1.0.5",
"diskusage": "1.1.3",
"cors": "2.8.5",
"diskusage-ng": "1.0.2",
"express": "4.17.1",
"express-openapi": "7.0.1",
"fs-extra": "9.0.1",
"hls-b24.js": "0.12.3",
"js-yaml": "3.14.0",
"lodash": "4.17.20",
"express-openapi": "9.3.0",
"file-type": "16.5.3",
"inversify": "5.1.1",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
"log4js": "6.3.0",
"material-design-icons": "3.0.1",
"material-design-lite": "1.3.0",
"minimist": "1.2.5",
"mirakurun": "3.3.1",
"mithril": "2.0.4",
"mirakurun": "3.9.0-beta.26",
"mkdirp": "1.0.4",
"multer": "1.4.2",
"multer": "1.4.3",
"mysql": "2.18.1",
"openapi-types": "7.0.1",
"pg": "8.3.3",
"request": "2.88.2",
"socket.io": "2.3.0",
"socket.io-client": "2.3.0",
"sqlite3": "5.0.0",
"swagger-ui-dist": "3.34.0",
"openapi-types": "9.3.0",
"reflect-metadata": "0.1.13",
"socket.io": "4.3.1",
"source-map-support": "0.5.20",
"sqlite3": "5.0.2",
"swagger-ui-dist": "3.52.5",
"typeorm": "0.2.38",
"url-join": "4.0.1",
"@types/basic-auth": "1.1.3",
"@types/body-parser": "1.19.0",
"@types/chart.js": "2.9.24",
"@types/express": "4.17.8",
"@types/hls.js": "0.13.1",
"@types/js-yaml": "3.12.5",
"@types/lodash": "4.14.161",
"@types/material-design-lite": "1.1.16",
"@types/minimist": "1.2.0",
"@types/mithril": "2.0.3",
"@types/mkdirp": "1.0.1",
"@types/multer": "1.4.4",
"@types/mysql": "2.15.15",
"@types/node": "14.11.1",
"@types/pg": "7.14.5",
"@types/request": "2.48.5",
"@types/socket.io": "2.1.11",
"@types/socket.io-client": "1.4.33",
"@types/sqlite3": "3.1.6",
"@types/url-join": "4.0.0",
"del": "5.1.0",
"@types/body-parser": "1.19.1",
"@types/express": "4.17.13",
"@types/file-type": "10.9.1",
"@types/js-yaml": "4.0.4",
"@types/lodash": "4.14.176",
"@types/minimist": "1.2.2",
"@types/mkdirp": "1.0.2",
"@types/mongodb": "4.0.6",
"@types/multer": "1.4.7",
"@types/node": "16.11.6",
"@types/socket.io": "3.0.1",
"@types/source-map-support": "0.5.4",
"@types/sqlite3": "3.1.7",
"@types/url-join": "4.0.1",
"@typescript-eslint/eslint-plugin": "4.33.0",
"@typescript-eslint/parser": "4.33.0",
"del": "6.0.0",
"eslint": "7.32.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-prettier": "3.4.1",
"gulp": "4.0.2",
"gulp-clean-css": "4.3.0",
"gulp-concat": "2.6.1",
"gulp-dart-sass": "1.0.2",
"gulp-eslint": "6.0.0",
"gulp-plumber": "1.2.1",
"gulp-sourcemaps": "2.6.5",
"gulp-tslint": "8.1.4",
"gulp-sourcemaps": "3.0.0",
"gulp-typescript": "5.0.1",
"terser-webpack-plugin": "4.2.2",
"ts-loader": "8.0.4",
"tslint": "6.1.3",
"typescript": "4.0.3",
"webpack": "4.44.2",
"webpack-stream": "6.1.0"
"prettier": "2.4.1",
"ts-loader": "9.2.6",
"ts-node": "10.4.0",
"typescript": "4.4.4"
}
}

View file

@ -6,6 +6,7 @@
, genericUpdater
, writers
, jq
, yq
}:
let
@ -40,6 +41,11 @@ in writers.writeBash "update-epgstation" ''
} | del(.devDependencies, .main, .scripts)' \
"$SRC/package.json" \
> package.json
${jq}/bin/jq '. + {
dependencies: (.dependencies + .devDependencies),
} | del(.devDependencies, .main, .scripts)' \
"$SRC/client/package.json" \
> client/package.json
# Regenerate node packages to update the pre-overriden epgstation derivation.
# This must come *after* package.json has been regenerated.
@ -49,18 +55,11 @@ in writers.writeBash "update-epgstation" ''
# Generate default streaming settings for the nixos module.
pushd ../../../../nixos/modules/services/video/epgstation
${jq}/bin/jq '
{ liveHLS
, liveMP4
, liveWebM
, mpegTsStreaming
, mpegTsViewer
, recordedDownloader
, recordedStreaming
, recordedHLS
, recordedViewer
}' \
"$SRC/config/config.sample.json" \
${yq}/bin/yq -j '{ urlscheme , stream }' \
"$SRC/config/config.yml.template" \
> streaming.json
# Fix generated output for EditorConfig compliance
printf '\n' >> streaming.json # rule: insert_final_newline
popd
''

View file

@ -1,17 +1,46 @@
diff --git a/src/server/ConfigInterface.ts b/src/server/ConfigInterface.ts
index d23badd..1dd2b98 100644
--- a/src/server/ConfigInterface.ts
+++ b/src/server/ConfigInterface.ts
@@ -11,9 +11,10 @@ interface ConfigInterface {
dbPath: string;
dbInfoPath: string;
mysql: {
diff --git a/ormconfig.js b/ormconfig.js
index 5591853b..838c06cb 100644
--- a/ormconfig.js
+++ b/ormconfig.js
@@ -38,8 +38,6 @@ switch (config.dbtype) {
case 'mysql':
ormConfig.type = 'mysql';
- ormConfig.host = config.mysql.host;
- ormConfig.port = config.mysql.port;
ormConfig.username = config.mysql.user;
ormConfig.password = config.mysql.password;
ormConfig.database = config.mysql.database;
@@ -49,6 +47,12 @@ switch (config.dbtype) {
} else {
ormConfig.charset = config.mysql.charset;
}
+ if (config.mysql.socketPath) {
+ ormConfig.socketPath = config.mysql.socketPath;
+ } else {
+ ormConfig.host = config.mysql.host;
+ ormConfig.port = config.mysql.port;
+ }
break;
case 'postgres':
diff --git a/src/model/IConfigFile.ts b/src/model/IConfigFile.ts
index 6a502e83..ba84a423 100644
--- a/src/model/IConfigFile.ts
+++ b/src/model/IConfigFile.ts
@@ -61,12 +61,13 @@ export default interface IConfigFile {
regexp?: boolean;
};
mysql?: {
- host: string;
+ host?: string;
+ socketPath?: string;
user: string;
- password: string;
+ password?: string;
- port: number;
+ port?: number;
password: string;
database: string;
connectTimeout: number;
connectionLimit: number;
charset?: string;
+ socketPath?: string;
};
postgres?: {
host: string;

View file

@ -127,7 +127,15 @@ let
# ../../applications/video/epgstation
epgstation = super."epgstation-../../applications/video/epgstation".override (drv: {
meta = drv.meta // {
broken = true; # not really broken, see the comment above
platforms = pkgs.lib.platforms.none;
};
});
# NOTE: this is a stub package to fetch npm dependencies for
# ../../applications/video/epgstation/client
epgstation-client = super."epgstation-client-../../applications/video/epgstation/client".override (drv: {
meta = drv.meta // {
platforms = pkgs.lib.platforms.none;
};
});
@ -270,6 +278,14 @@ let
url = "https://github.com/svanderburg/node2nix/commit/e4c951971df6c9f9584c7252971c13b55c369916.patch";
sha256 = "0w8fcyr12g2340rn06isv40jkmz2khmak81c95zpkjgipzx7hp7w";
})
# handle package alias in dependencies
# https://github.com/svanderburg/node2nix/pull/240
#
# TODO: remove after node2nix 1.10.0
(fetchpatch {
url = "https://github.com/svanderburg/node2nix/commit/644e90c0304038a446ed53efc97e9eb1e2831e71.patch";
sha256 = "sha256-sQgVf80H1ouUjzHq+2d9RO4a+o++kh+l+FOTNXfPBH0=";
})
];
};
postInstall = ''

View file

@ -114,6 +114,7 @@
, "emoj"
, "emojione"
, {"epgstation": "../../applications/video/epgstation"}
, {"epgstation-client": "../../applications/video/epgstation/client"}
, "escape-string-regexp"
, "eslint"
, "eslint_d"

File diff suppressed because it is too large Load diff