mirror of
https://github.com/BililiveRecorder/BililiveRecorder.git
synced 2024-11-15 19:22:19 +08:00
Update config docs
This commit is contained in:
parent
c9419bfa0a
commit
8ad4962cff
|
@ -1,109 +0,0 @@
|
|||
"use strict";
|
||||
import { spawn } from "child_process";
|
||||
import { stdout, stderr } from "process";
|
||||
import { writeFileSync } from "fs";
|
||||
import { resolve, dirname } from "path";
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
import data from "./config_data.js"
|
||||
|
||||
import generate_cli_configure from "./generate_cli_configure.js";
|
||||
import generate_json_schema from "./generate_json_schema.js"
|
||||
import generate_core_config from "./generate_core_config.js"
|
||||
import generate_web_config from "./generate_web_config.js"
|
||||
|
||||
const baseDirectory = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const DO_NOT_EDIT_COMMENT = `// ******************************
|
||||
// GENERATED CODE, DO NOT EDIT MANUALLY.
|
||||
// SEE .tools/build_config.js
|
||||
// ******************************\n\n`
|
||||
|
||||
// ---------------------------------------------
|
||||
// SCHEMA
|
||||
// ---------------------------------------------
|
||||
|
||||
console.log("[node] writing json schema...")
|
||||
|
||||
const json_schema_path = resolve(baseDirectory, '../configV2.schema.json');
|
||||
|
||||
const json_schema_code = generate_json_schema(data);
|
||||
|
||||
writeFileSync(json_schema_path, json_schema_code, {
|
||||
encoding: "utf8"
|
||||
});
|
||||
|
||||
// ---------------------------------------------
|
||||
// CORE
|
||||
// ---------------------------------------------
|
||||
|
||||
console.log("[node] writing core config...")
|
||||
|
||||
const core_config_path = resolve(baseDirectory, '../BililiveRecorder.Core/Config/V2/Config.gen.cs');
|
||||
|
||||
const core_config_code = generate_core_config(data);
|
||||
|
||||
writeFileSync(core_config_path, DO_NOT_EDIT_COMMENT + core_config_code, {
|
||||
encoding: "utf8"
|
||||
});
|
||||
|
||||
// ---------------------------------------------
|
||||
// CLI
|
||||
// ---------------------------------------------
|
||||
|
||||
console.log("[node] writing cli configure config...")
|
||||
|
||||
const cli_config_path = resolve(baseDirectory, '../BililiveRecorder.Cli/Configure/ConfigInstructions.gen.cs');
|
||||
|
||||
const cli_config_code = generate_cli_configure(data);
|
||||
|
||||
writeFileSync(cli_config_path, DO_NOT_EDIT_COMMENT + cli_config_code, {
|
||||
encoding: "utf8"
|
||||
});
|
||||
|
||||
// ---------------------------------------------
|
||||
// WEB
|
||||
// ---------------------------------------------
|
||||
/* disabled
|
||||
console.log("[node] writing web config...")
|
||||
|
||||
const web_config_path = resolve(baseDirectory, '../BililiveRecorder.Web.Schemas/Types/Config.gen.cs');
|
||||
|
||||
const web_config_code = generate_web_config(data);
|
||||
|
||||
writeFileSync(web_config_path, DO_NOT_EDIT_COMMENT + web_config_code, {
|
||||
encoding: "utf8"
|
||||
});
|
||||
*/
|
||||
// ---------------------------------------------
|
||||
// FORMAT
|
||||
// ---------------------------------------------
|
||||
|
||||
console.log("[node] formatting...")
|
||||
|
||||
let format = spawn('dotnet',
|
||||
[
|
||||
'tool',
|
||||
'run',
|
||||
'dotnet-format',
|
||||
'--',
|
||||
'--include',
|
||||
'./BililiveRecorder.Core/Config/V2/Config.gen.cs',
|
||||
'./BililiveRecorder.Cli/Configure/ConfigInstructions.gen.cs',
|
||||
// './BililiveRecorder.Web.Schemas/Types/Config.gen.cs'
|
||||
],
|
||||
{
|
||||
cwd: resolve(baseDirectory, "..")
|
||||
})
|
||||
|
||||
format.stdout.on('data', function (data) {
|
||||
stdout.write('[dotnet-format] ' + data.toString());
|
||||
});
|
||||
|
||||
format.stderr.on('data', function (data) {
|
||||
stderr.write('[dotnet-format] ' + data.toString());
|
||||
});
|
||||
|
||||
format.on('exit', function (code) {
|
||||
console.log('[node] format done code ' + code.toString());
|
||||
});
|
|
@ -1,128 +0,0 @@
|
|||
export default {
|
||||
"global": [{
|
||||
"name": "TimingStreamRetry",
|
||||
"type": "uint",
|
||||
"desc": "录制断开重连时间间隔 毫秒",
|
||||
"default": "6 * 1000"
|
||||
}, {
|
||||
"name": "TimingStreamConnect",
|
||||
"type": "uint",
|
||||
"desc": "连接直播服务器超时时间 毫秒",
|
||||
"default": "5 * 1000"
|
||||
}, {
|
||||
"name": "TimingDanmakuRetry",
|
||||
"type": "uint",
|
||||
"desc": "弹幕服务器重连时间间隔 毫秒",
|
||||
"default": "15 * 1000"
|
||||
}, {
|
||||
"name": "TimingCheckInterval",
|
||||
"type": "uint",
|
||||
"desc": "HTTP API 检查时间间隔 秒",
|
||||
"default": "10 * 60"
|
||||
}, {
|
||||
"name": "TimingWatchdogTimeout",
|
||||
"type": "uint",
|
||||
"desc": "最大未收到新直播数据时间 毫秒",
|
||||
"default": "10 * 1000"
|
||||
}, {
|
||||
"name": "RecordDanmakuFlushInterval",
|
||||
"type": "uint",
|
||||
"desc": "触发 <see cref=\"System.Xml.XmlWriter.Flush\"/> 的弹幕个数",
|
||||
"default": "20"
|
||||
}, {
|
||||
"name": "Cookie",
|
||||
"type": "string",
|
||||
"desc": "请求 API 时使用的 Cookie",
|
||||
"default": "string.Empty",
|
||||
"nullable": true
|
||||
}, {
|
||||
"name": "WebHookUrls",
|
||||
"type": "string",
|
||||
"desc": "录制文件写入结束 Webhook 地址 每行一个",
|
||||
"default": "string.Empty",
|
||||
"nullable": true
|
||||
}, {
|
||||
"name": "WebHookUrlsV2",
|
||||
"type": "string",
|
||||
"desc": "Webhook v2 地址 每行一个",
|
||||
"default": "string.Empty",
|
||||
"nullable": true
|
||||
}, {
|
||||
"name": "LiveApiHost",
|
||||
"type": "string",
|
||||
"desc": "替换 api.live.bilibili.com 服务器为其他反代,可以支持在云服务器上录制",
|
||||
"default": "\"https://api.live.bilibili.com\"",
|
||||
"nullable": true
|
||||
}, {
|
||||
"name": "RecordFilenameFormat",
|
||||
"type": "string",
|
||||
"desc": "录制文件名模板",
|
||||
"default": "@\"{roomid}-{name}/录制-{roomid}-{date}-{time}-{ms}-{title}.flv\"",
|
||||
"nullable": true
|
||||
}, {
|
||||
"name": "WpfShowTitleAndArea",
|
||||
"type": "bool",
|
||||
"desc": "是否显示直播间标题和分区",
|
||||
"default": "true",
|
||||
},],
|
||||
"room": [{
|
||||
"name": "RoomId",
|
||||
"type": "int",
|
||||
"desc": "房间号",
|
||||
"default": "default",
|
||||
"without_global": true,
|
||||
"web_readonly": true
|
||||
}, {
|
||||
"name": "AutoRecord",
|
||||
"type": "bool",
|
||||
"desc": "是否启用自动录制",
|
||||
"default": "default",
|
||||
"without_global": true,
|
||||
}, {
|
||||
"name": "RecordMode",
|
||||
"type": "RecordMode",
|
||||
"desc": "录制模式",
|
||||
"default": "RecordMode.Standard"
|
||||
}, {
|
||||
"name": "CuttingMode",
|
||||
"type": "CuttingMode",
|
||||
"desc": "录制文件自动切割模式",
|
||||
"default": "CuttingMode.Disabled"
|
||||
}, {
|
||||
"name": "CuttingNumber",
|
||||
"type": "uint",
|
||||
"desc": "录制文件自动切割数值(分钟/MiB)",
|
||||
"default": "100"
|
||||
}, {
|
||||
"name": "RecordDanmaku",
|
||||
"type": "bool",
|
||||
"desc": "是否同时录制弹幕",
|
||||
"default": "false"
|
||||
}, {
|
||||
"name": "RecordDanmakuRaw",
|
||||
"type": "bool",
|
||||
"desc": "是否记录弹幕原始数据",
|
||||
"default": "false"
|
||||
}, {
|
||||
"name": "RecordDanmakuSuperChat",
|
||||
"type": "bool",
|
||||
"desc": "是否同时录制 SuperChat",
|
||||
"default": "true"
|
||||
}, {
|
||||
"name": "RecordDanmakuGift",
|
||||
"type": "bool",
|
||||
"desc": "是否同时录制 礼物",
|
||||
"default": "false"
|
||||
}, {
|
||||
"name": "RecordDanmakuGuard",
|
||||
"type": "bool",
|
||||
"desc": "是否同时录制 上船",
|
||||
"default": "true"
|
||||
}, {
|
||||
"name": "RecordingQuality",
|
||||
"type": "string",
|
||||
"desc": "录制的直播画质 qn 值,逗号分割,靠前的优先",
|
||||
"default": "\"10000\"",
|
||||
"nullable": true
|
||||
},]
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
export default function generate_cli_configure(data) {
|
||||
let result = `using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using BililiveRecorder.Core.Config.V2;
|
||||
|
||||
namespace BililiveRecorder.Cli.Configure
|
||||
{`;
|
||||
|
||||
result += `
|
||||
public enum GlobalConfigProperties
|
||||
{
|
||||
[Description("[grey]Exit[/]")]
|
||||
Exit,
|
||||
${data.global.concat(data.room.filter(x => !x.without_global)).map(x => x.name).join(",\n")}
|
||||
}`;
|
||||
|
||||
result += `
|
||||
public enum RoomConfigProperties
|
||||
{
|
||||
[Description("[grey]Exit[/]")]
|
||||
Exit,
|
||||
${data.room.map(x => x.name).join(",\n")}
|
||||
}`;
|
||||
|
||||
|
||||
result += `
|
||||
public static class ConfigInstructions
|
||||
{
|
||||
public static Dictionary<GlobalConfigProperties, ConfigInstructionBase<GlobalConfig>> GlobalConfig = new();
|
||||
public static Dictionary<RoomConfigProperties, ConfigInstructionBase<RoomConfig>> RoomConfig = new();
|
||||
|
||||
static ConfigInstructions()
|
||||
{
|
||||
${data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.map(r => `GlobalConfig.Add(GlobalConfigProperties.${r.name}, new ConfigInstruction<GlobalConfig, ${r.type}>(config => config.Has${r.name} = false, (config, value) => config.${r.name} = value) { Name = "${r.name}", CanBeOptional = true });`)
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
${data.room.map(r => `RoomConfig.Add(RoomConfigProperties.${r.name}, new ConfigInstruction<RoomConfig, ${r.type}>(config => config.Has${r.name} = false, (config, value) => config.${r.name} = value) { Name = "${r.name}", CanBeOptional = ${!r.without_global} });`).join("\n")}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
result += `\n}\n`;
|
||||
return result;
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
export default function generate_core_config(data) {
|
||||
let result = `using System.ComponentModel;
|
||||
using HierarchicalPropertyDefault;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
#nullable enable
|
||||
namespace BililiveRecorder.Core.Config.V2
|
||||
{
|
||||
`;
|
||||
|
||||
function write_property(r) {
|
||||
result += `/// <summary>\n/// ${r.desc}\n/// </summary>\n`;
|
||||
result += `public ${r.type}${!!r.nullable ? "?" : ""} ${r.name} { get => this.GetPropertyValue<${r.type}>(); set => this.SetPropertyValue(value); }\n`;
|
||||
result += `public bool Has${r.name} { get => this.GetPropertyHasValue(nameof(this.${r.name})); set => this.SetPropertyHasValue<${r.type}>(value, nameof(this.${r.name})); }\n`;
|
||||
result += `[JsonProperty(nameof(${r.name})), EditorBrowsable(EditorBrowsableState.Never)]\n`;
|
||||
result += `public Optional<${r.type}${!!r.nullable ? "?" : ""}> Optional${r.name} { get => this.GetPropertyValueOptional<${r.type}>(nameof(this.${r.name})); set => this.SetPropertyValueOptional(value, nameof(this.${r.name})); }\n\n`;
|
||||
}
|
||||
|
||||
function write_readonly_property(r) {
|
||||
result += `/// <summary>\n/// ${r.desc}\n/// </summary>\n`;
|
||||
result += `public ${r.type}${!!r.nullable ? "?" : ""} ${r.name} => this.GetPropertyValue<${r.type}>();\n\n`;
|
||||
}
|
||||
|
||||
{
|
||||
result += "[JsonObject(MemberSerialization.OptIn)]\n";
|
||||
result += "public sealed partial class RoomConfig : HierarchicalObject<GlobalConfig, RoomConfig>\n";
|
||||
result += "{\n";
|
||||
|
||||
data.room.forEach(r => write_property(r));
|
||||
data.global.forEach(r => write_readonly_property(r));
|
||||
|
||||
result += "}\n\n";
|
||||
}
|
||||
|
||||
{
|
||||
result += "[JsonObject(MemberSerialization.OptIn)]\n";
|
||||
result += "public sealed partial class GlobalConfig : HierarchicalObject<DefaultConfig, GlobalConfig>\n";
|
||||
result += "{\n";
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.forEach(r => write_property(r));
|
||||
|
||||
result += "}\n\n";
|
||||
}
|
||||
|
||||
{
|
||||
result += `public sealed partial class DefaultConfig
|
||||
{
|
||||
public static readonly DefaultConfig Instance = new DefaultConfig();
|
||||
private DefaultConfig() {}\n\n`;
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.forEach(r => {
|
||||
result += `public ${r.type} ${r.name} => ${r.default};\n\n`;
|
||||
});
|
||||
|
||||
result += "}\n\n";
|
||||
}
|
||||
|
||||
result += `}\n`;
|
||||
return result;
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
function tryEvalValue(str) {
|
||||
try {
|
||||
return eval(str);
|
||||
} catch {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
function mapTypeToJsonSchema(name, type, defVal) {
|
||||
switch (type) {
|
||||
case "RecordMode":
|
||||
return { type: "integer", default: 0, enum: [0, 1], "description": "0: Standard\n1: Raw" };
|
||||
case "CuttingMode":
|
||||
return { type: "integer", default: 0, enum: [0, 1, 2], "description": "0: 禁用\n1: 根据时间切割\n2: 根据文件大小切割" };
|
||||
case "uint":
|
||||
return { type: "integer", minimum: 0, maximum: 4294967295, default: tryEvalValue(defVal) };
|
||||
case "int":
|
||||
return { type: "integer", minimum: -2147483648, maximum: 2147483647, default: tryEvalValue(defVal) };
|
||||
case "bool":
|
||||
return { type: "boolean", default: tryEvalValue(defVal) };
|
||||
case "string":
|
||||
if (name === 'Cookie') {
|
||||
return { type: "string", pattern: "^(\S+=\S+;? ?)*$", maxLength: 4096, };
|
||||
}
|
||||
return { type: "string", default: defVal === 'string.Empty' ? '' : tryEvalValue(defVal.replace(/^@/, '')) };
|
||||
default:
|
||||
return { type, default: defVal };
|
||||
}
|
||||
}
|
||||
|
||||
function insert(target, { name, type, desc, default: defVal/*, nullable */ }) {
|
||||
const typeObj = mapTypeToJsonSchema(name, type, defVal);
|
||||
if (defVal === 'default') delete typeObj['default'];
|
||||
target[name] = {
|
||||
"description": desc,
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"HasValue": { "type": "boolean", "default": true }, "Value": typeObj
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function generate_json_schema(data) {
|
||||
const sharedConfig = {};
|
||||
const globalConfig = {};
|
||||
const roomConfig = {};
|
||||
|
||||
data.room.filter(x => !x.without_global).forEach(v => insert(sharedConfig, v));
|
||||
data.room.filter(x => x.without_global).forEach(v => insert(roomConfig, v));
|
||||
data.global.forEach(v => insert(globalConfig, v));
|
||||
|
||||
const schema = {
|
||||
"$comment": "GENERATED CODE, DO NOT EDIT MANUALLY.",
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"definitions": {
|
||||
"global-config": {
|
||||
"description": "全局配置",
|
||||
"additionalProperties": false,
|
||||
"properties": { ...globalConfig, ...sharedConfig }
|
||||
},
|
||||
"room-config": {
|
||||
"description": "单个房间配置",
|
||||
"additionalProperties": false,
|
||||
"properties": { ...roomConfig, ...sharedConfig }
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"$schema",
|
||||
"version"
|
||||
],
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"default": "https://raw.githubusercontent.com/Bililive/BililiveRecorder/dev-1.3/configV2.schema.json"
|
||||
},
|
||||
"version": {
|
||||
"const": 2
|
||||
},
|
||||
"global": {
|
||||
"$ref": "#/definitions/global-config"
|
||||
},
|
||||
"rooms": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/room-config"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JSON.stringify(schema, null, 2)
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
export default function generate_web_config(data) {
|
||||
let result = `using BililiveRecorder.Core.Config.V2;
|
||||
using GraphQL.Types;
|
||||
using HierarchicalPropertyDefault;
|
||||
|
||||
#nullable enable
|
||||
namespace BililiveRecorder.Web.Schemas.Types
|
||||
{
|
||||
`;
|
||||
|
||||
function write_query_graphType_property(r) {
|
||||
if (r.without_global) {
|
||||
result += `this.Field(x => x.${r.name});\n`;
|
||||
} else {
|
||||
result += `this.Field(x => x.Optional${r.name}, type: typeof(HierarchicalOptionalType<${r.type}>));\n`;
|
||||
}
|
||||
}
|
||||
|
||||
function write_mutation_graphType_property(r) {
|
||||
if (r.without_global) {
|
||||
result += `this.Field(x => x.${r.name}, nullable: true);\n`;
|
||||
} else {
|
||||
result += `this.Field(x => x.Optional${r.name}, nullable: true, type: typeof(HierarchicalOptionalInputType<${r.type}>));\n`;
|
||||
}
|
||||
}
|
||||
|
||||
function write_mutation_dataType_property(r) {
|
||||
if (r.without_global) {
|
||||
result += `public ${r.type + (r.nullable ? '?' : '')}? ${r.name} { get; set; }\n`;
|
||||
} else {
|
||||
result += `public Optional<${r.type + (r.nullable ? '?' : '')}>? Optional${r.name} { get; set; }\n`;
|
||||
}
|
||||
}
|
||||
|
||||
function write_mutation_apply_method(r) {
|
||||
if (r.without_global) {
|
||||
result += `if (this.${r.name}.HasValue) config.${r.name} = this.${r.name}.Value;\n`;
|
||||
} else {
|
||||
result += `if (this.Optional${r.name}.HasValue) config.Optional${r.name} = this.Optional${r.name}.Value;\n`;
|
||||
}
|
||||
}
|
||||
|
||||
{ // ====== RoomConfigType ======
|
||||
result += "internal class RoomConfigType : ObjectGraphType<RoomConfig>\n{\n";
|
||||
result += "public RoomConfigType()\n{\n"
|
||||
|
||||
data.room.forEach(r => write_query_graphType_property(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== GlobalConfigType ======
|
||||
result += "internal class GlobalConfigType : ObjectGraphType<GlobalConfig>\n{\n"
|
||||
result += "public GlobalConfigType()\n{\n";
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.forEach(r => write_query_graphType_property(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== DefaultConfigType ======
|
||||
result += "internal class DefaultConfigType : ObjectGraphType<DefaultConfig>\n{\n"
|
||||
result += "public DefaultConfigType()\n{\n";
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.forEach(r => {
|
||||
result += `this.Field(x => x.${r.name});\n`;
|
||||
});
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== SetRoomConfig ======
|
||||
result += "internal class SetRoomConfig\n{\n"
|
||||
|
||||
data.room.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_dataType_property(r));
|
||||
|
||||
result += "\npublic void ApplyTo(RoomConfig config)\n{\n";
|
||||
|
||||
data.room.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_apply_method(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== SetRoomConfigType ======
|
||||
result += "internal class SetRoomConfigType : InputObjectGraphType<SetRoomConfig>\n{\n"
|
||||
result += "public SetRoomConfigType()\n{\n";
|
||||
|
||||
data.room.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_graphType_property(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== SetGlobalConfig ======
|
||||
result += "internal class SetGlobalConfig\n{\n"
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_dataType_property(r));
|
||||
|
||||
result += "\npublic void ApplyTo(GlobalConfig config)\n{\n";
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_apply_method(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
{ // ====== SetGlobalConfigType ======
|
||||
result += "internal class SetGlobalConfigType : InputObjectGraphType<SetGlobalConfig>\n{\n"
|
||||
result += "public SetGlobalConfigType()\n{\n";
|
||||
|
||||
data.global
|
||||
.concat(data.room.filter(x => !x.without_global))
|
||||
.filter(x => !x.web_readonly)
|
||||
.forEach(r => write_mutation_graphType_property(r));
|
||||
|
||||
result += "}\n}\n\n";
|
||||
}
|
||||
|
||||
result += `}\n`;
|
||||
return result;
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"type": "module"
|
||||
}
|
|
@ -16,7 +16,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "roomOnly",
|
||||
defaultValue: "default",
|
||||
markdown: ""
|
||||
markdown: "设为 `true` 为启用自动录制,`false` 为不自动录制。"
|
||||
},
|
||||
{
|
||||
name: "RecordMode",
|
||||
|
@ -24,7 +24,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "RecordMode",
|
||||
configType: "room",
|
||||
defaultValue: "RecordMode.Standard",
|
||||
markdown: ""
|
||||
markdown: "本设置项是一个 enum,键值对应如下:\n\n| 键 | 值 |\n|:--:|:--:|\n| RecordMode.Standard | 0 |\n| RecordMode.RawData | 1 |\n\n关于录制模式的说明见 [录制模式](/docs/basic/record_mode/)"
|
||||
},
|
||||
{
|
||||
name: "CuttingMode",
|
||||
|
@ -32,7 +32,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "CuttingMode",
|
||||
configType: "room",
|
||||
defaultValue: "CuttingMode.Disabled",
|
||||
markdown: ""
|
||||
markdown: "本设置项是一个 enum,键值对应如下:\n\n| 键 | 值 |\n|:--:|:--:|\n| CuttingMode.Disabled | 0 |\n| CuttingMode.ByTime | 1 |\n| CuttingMode.BySize | 2 |"
|
||||
},
|
||||
{
|
||||
name: "CuttingNumber",
|
||||
|
@ -40,7 +40,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "uint",
|
||||
configType: "room",
|
||||
defaultValue: "100",
|
||||
markdown: "按时长分段时为分钟,按大小分段时为MiB"
|
||||
markdown: "根据 CuttingMode 设置的不同: \n当按时长分段时,本设置的单位为分钟。 \n当按大小分段时,本设置的单位为MiB。"
|
||||
},
|
||||
{
|
||||
name: "RecordDanmaku",
|
||||
|
@ -48,7 +48,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "room",
|
||||
defaultValue: "false",
|
||||
markdown: ""
|
||||
markdown: "是否录制弹幕,`true` 为录制,`false` 为不录制。\n\n本设置同时是所有“弹幕录制”的总开关,当本设置为 `false` 时其他所有“弹幕录制”设置无效,不会写入弹幕XML文件。"
|
||||
},
|
||||
{
|
||||
name: "RecordDanmakuRaw",
|
||||
|
@ -56,7 +56,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "room",
|
||||
defaultValue: "false",
|
||||
markdown: ""
|
||||
markdown: "是否记录原始 JSON 数据。\n\n弹幕原始数据会保存到 XML 文件每一条弹幕数据的 `raw` attribute 上。\n\n当 `RecordDanmaku` 为 `false` 时本项设置无效。"
|
||||
},
|
||||
{
|
||||
name: "RecordDanmakuSuperChat",
|
||||
|
@ -64,7 +64,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "room",
|
||||
defaultValue: "true",
|
||||
markdown: ""
|
||||
markdown: "是否记录 SuperChat。\n\n当 `RecordDanmaku` 为 `false` 时本项设置无效。"
|
||||
},
|
||||
{
|
||||
name: "RecordDanmakuGift",
|
||||
|
@ -72,7 +72,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "room",
|
||||
defaultValue: "false",
|
||||
markdown: ""
|
||||
markdown: "是否记录礼物。\n\n当 `RecordDanmaku` 为 `false` 时本项设置无效。"
|
||||
},
|
||||
{
|
||||
name: "RecordDanmakuGuard",
|
||||
|
@ -80,7 +80,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "room",
|
||||
defaultValue: "true",
|
||||
markdown: ""
|
||||
markdown: "是否记录上船(购买舰长)。\n\n当 `RecordDanmaku` 为 `false` 时本项设置无效。"
|
||||
},
|
||||
{
|
||||
name: "RecordingQuality",
|
||||
|
@ -89,7 +89,7 @@ export const data: Array<ConfigEntry> = [
|
|||
description: "直播画质",
|
||||
defaultValue: "\"10000\"",
|
||||
defaultValueDescription: "10000",
|
||||
markdown: "录制的直播画质 qn 值,逗号分割,靠前的优先"
|
||||
markdown: "录制的直播画质 qn 值,以英文逗号分割,靠前的优先。\n\n**注意**(从录播姬 1.3.10 开始):\n\n- 所有主播刚开播时都是只有“原画”的,如果选择不录原画会导致直播开头漏录。\n- 如果设置的录制画质里没有原画,但是主播只有原画画质,会导致不能录制直播。\n- 录播姬不会为了切换录制的画质主动断开录制。\n\n画质 | qn 值\n:--:|:--:\n4K | 20000\n原画 | 10000\n蓝光(杜比) | 401\n蓝光 | 400\n超清 | 250\n高清 | 150\n流畅 | 80"
|
||||
},
|
||||
{
|
||||
name: "RecordFilenameFormat",
|
||||
|
@ -97,7 +97,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "string?",
|
||||
configType: "globalOnly",
|
||||
defaultValue: "@\"{roomid}-{name}/录制-{roomid}-{date}-{time}-{ms}-{title}.flv\"",
|
||||
markdown: ""
|
||||
markdown: "- 只支持 FLV 格式\n- 所有大括号均为英文半角括号\n- 录制时如果出现文件名冲突,会使用一个默认文件名\n\n变量 | 含义\n:--:|:--:\n{date} | 当前日期(年月日)\n{time} | 当前时间(时分秒)\n{ms} | 当前时间毫秒\n{roomid} | 房间号\n{title} | 标题\n{name} | 主播名\n{parea} | 大分区\n{area} | 子分区\n{random} | 随机数字\n"
|
||||
},
|
||||
{
|
||||
name: "WebHookUrls",
|
||||
|
@ -106,7 +106,7 @@ export const data: Array<ConfigEntry> = [
|
|||
configType: "globalOnly",
|
||||
defaultValue: "string.Empty",
|
||||
xmlComment: "录制文件写入结束 Webhook 地址 每行一个",
|
||||
markdown: ""
|
||||
markdown: "具体文档见 [Webhook](/docs/basic/webhook/)"
|
||||
},
|
||||
{
|
||||
name: "WebHookUrlsV2",
|
||||
|
@ -115,7 +115,7 @@ export const data: Array<ConfigEntry> = [
|
|||
configType: "globalOnly",
|
||||
defaultValue: "string.Empty",
|
||||
xmlComment: "Webhook v2 地址 每行一个",
|
||||
markdown: ""
|
||||
markdown: "具体文档见 [Webhook](/docs/basic/webhook/)"
|
||||
},
|
||||
{
|
||||
name: "WpfShowTitleAndArea",
|
||||
|
@ -123,7 +123,7 @@ export const data: Array<ConfigEntry> = [
|
|||
type: "bool",
|
||||
configType: "globalOnly",
|
||||
defaultValue: "true",
|
||||
markdown: ""
|
||||
markdown: "只在桌面版(WPF版)有效"
|
||||
},
|
||||
{
|
||||
name: "Cookie",
|
||||
|
|
|
@ -41,6 +41,21 @@ ${x.markdown}
|
|||
`).join('\n')
|
||||
result += '\n\n'
|
||||
|
||||
// 高级设置说明
|
||||
result += "## 高级设置\n\n"
|
||||
result += "<span style=\"color:red\">重要说明</span>:一般用户通常不需要也不应该修改高级设置。 \n对各个 Timing 的修改可能会导致被B站服务器屏蔽、不能及时开始录制等问题。\n\n"
|
||||
result += "显示高级设置的方法:右键双击界面左下角的设置按钮\n\n"
|
||||
|
||||
// 高级设置项目列表
|
||||
result += data.filter(x => x.advancedConfig).map(x =>
|
||||
`### ${x.description}
|
||||
|
||||
键名: \`${x.name}\`
|
||||
类型: \`${trimEnd(x.type, '?')}\`
|
||||
默认设置: \`${x.defaultValueDescription ?? x.defaultValue}\`
|
||||
|
||||
${x.markdown}
|
||||
`).join('\n')
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
184
config_gen/package-lock.json
generated
184
config_gen/package-lock.json
generated
|
@ -1,6 +1,188 @@
|
|||
{
|
||||
"name": "config_gen",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"": {
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.6.1",
|
||||
"ts-node": "^10.2.0",
|
||||
"tslib": "^2.3.1",
|
||||
"typescript": "^4.3.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-consumer": {
|
||||
"version": "0.8.0",
|
||||
"resolved": "https://registry.nlark.com/@cspotcode/source-map-consumer/download/@cspotcode/source-map-consumer-0.8.0.tgz?cache=0&sync_timestamp=1628465044726&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40cspotcode%2Fsource-map-consumer%2Fdownload%2F%40cspotcode%2Fsource-map-consumer-0.8.0.tgz",
|
||||
"integrity": "sha1-M79LeznBeIIWBvZpu8RHpqYpeGs=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 12"
|
||||
}
|
||||
},
|
||||
"node_modules/@cspotcode/source-map-support": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.nlark.com/@cspotcode/source-map-support/download/@cspotcode/source-map-support-0.6.1.tgz?cache=0&sync_timestamp=1628465040948&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40cspotcode%2Fsource-map-support%2Fdownload%2F%40cspotcode%2Fsource-map-support-0.6.1.tgz",
|
||||
"integrity": "sha1-EYUR8xbi6H7kKUdhho4lTT2keWA=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-consumer": "0.8.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/@tsconfig/node10": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.nlark.com/@tsconfig/node10/download/@tsconfig/node10-1.0.8.tgz",
|
||||
"integrity": "sha1-weToDW+WT77LM1nEO9SLQPfK2tk=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node12": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.nlark.com/@tsconfig/node12/download/@tsconfig/node12-1.0.9.tgz",
|
||||
"integrity": "sha1-YsH23uLr2a6tgNw6+laBDljhoEw=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node14": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.nlark.com/@tsconfig/node14/download/@tsconfig/node14-1.0.1.tgz",
|
||||
"integrity": "sha1-lfLRZ/+5uNIGiwsjUwL6/U33EfI=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@tsconfig/node16": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.nlark.com/@tsconfig/node16/download/@tsconfig/node16-1.0.2.tgz",
|
||||
"integrity": "sha1-Qjx3h30Fadsg4fyAiFrEEYMUAQ4=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.6.1",
|
||||
"resolved": "https://registry.nlark.com/@types/node/download/@types/node-16.6.1.tgz?cache=0&sync_timestamp=1628800447602&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40types%2Fnode%2Fdownload%2F%40types%2Fnode-16.6.1.tgz",
|
||||
"integrity": "sha1-ruYse5ZvVfxmx7bfodWNsqYW2mE=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/acorn": {
|
||||
"version": "8.4.1",
|
||||
"resolved": "https://registry.nlark.com/acorn/download/acorn-8.4.1.tgz",
|
||||
"integrity": "sha1-VsNiUfx8q8cJatwY8Fr+gUMhoow=",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-walk": {
|
||||
"version": "8.1.1",
|
||||
"resolved": "https://registry.nlark.com/acorn-walk/download/acorn-walk-8.1.1.tgz",
|
||||
"integrity": "sha1-Pdq3+E5KfiMT9sQUxbfayF9OPrw=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/arg": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npm.taobao.org/arg/download/arg-4.1.3.tgz",
|
||||
"integrity": "sha1-Jp/HrVuOQstjyJbVZmAXJhwUQIk=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/create-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/create-require/download/create-require-1.1.1.tgz",
|
||||
"integrity": "sha1-wdfo8eX2z8n/ZfnNNS03NIdWwzM=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/diff/download/diff-4.0.2.tgz",
|
||||
"integrity": "sha1-YPOuy4nV+uUgwRqhnvwruYKq3n0=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"resolved": "https://registry.npm.taobao.org/make-error/download/make-error-1.3.6.tgz?cache=0&sync_timestamp=1582105487630&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmake-error%2Fdownload%2Fmake-error-1.3.6.tgz",
|
||||
"integrity": "sha1-LrLjfqm2fEiR9oShOUeZr0hM96I=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/ts-node": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.nlark.com/ts-node/download/ts-node-10.2.0.tgz?cache=0&sync_timestamp=1628464846072&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fts-node%2Fdownload%2Fts-node-10.2.0.tgz",
|
||||
"integrity": "sha1-8eiCSaAOJqqV6ak8UPcCQaihxLs=",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-support": "0.6.1",
|
||||
"@tsconfig/node10": "^1.0.7",
|
||||
"@tsconfig/node12": "^1.0.7",
|
||||
"@tsconfig/node14": "^1.0.0",
|
||||
"@tsconfig/node16": "^1.0.2",
|
||||
"acorn": "^8.4.1",
|
||||
"acorn-walk": "^8.1.1",
|
||||
"arg": "^4.1.0",
|
||||
"create-require": "^1.1.0",
|
||||
"diff": "^4.0.1",
|
||||
"make-error": "^1.1.1",
|
||||
"yn": "3.1.1"
|
||||
},
|
||||
"bin": {
|
||||
"ts-node": "dist/bin.js",
|
||||
"ts-node-cwd": "dist/bin-cwd.js",
|
||||
"ts-node-script": "dist/bin-script.js",
|
||||
"ts-node-transpile-only": "dist/bin-transpile.js",
|
||||
"ts-script": "dist/bin-script-deprecated.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": ">=1.2.50",
|
||||
"@swc/wasm": ">=1.2.50",
|
||||
"@types/node": "*",
|
||||
"typescript": ">=2.7"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
},
|
||||
"@swc/wasm": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.nlark.com/tslib/download/tslib-2.3.1.tgz",
|
||||
"integrity": "sha1-6KM1rdXOrlGqJh0ypJAVjvBC7wE=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.3.5",
|
||||
"resolved": "https://registry.nlark.com/typescript/download/typescript-4.3.5.tgz",
|
||||
"integrity": "sha1-TRw3zBbok5c8RaBohrcRMjTxGfQ=",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yn": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/yn/download/yn-3.1.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fyn%2Fdownload%2Fyn-3.1.1.tgz",
|
||||
"integrity": "sha1-HodAGgnXZ8HV6rJqbkwYUYLS61A=",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@cspotcode/source-map-consumer": {
|
||||
"version": "0.8.0",
|
||||
|
|
Loading…
Reference in New Issue
Block a user