mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-26 00:26:05 -07:00
refactor: move youtube primary subtitle config to youtube
This commit is contained in:
5
changes/youtube-primary-subtitle-config.md
Normal file
5
changes/youtube-primary-subtitle-config.md
Normal file
@@ -0,0 +1,5 @@
|
||||
type: changed
|
||||
area: launcher
|
||||
|
||||
Moved YouTube primary subtitle language defaults to `youtube.primarySubLanguages`.
|
||||
Removed the old `youtubeSubgen.primarySubLanguages` config path from the generated config and docs.
|
||||
@@ -417,20 +417,11 @@
|
||||
// YouTube Playback Settings
|
||||
// Defaults for SubMiner YouTube subtitle loading and languages.
|
||||
// ==========================================
|
||||
"youtubeSubgen": {
|
||||
"whisperBin": "", // Legacy compatibility path kept for external subtitle fallback tools; not used by default.
|
||||
"whisperModel": "", // Legacy compatibility model path kept for external subtitle fallback tooling; not used by default.
|
||||
"whisperVadModel": "", // Legacy compatibility VAD path kept for external subtitle fallback tooling; not used by default.
|
||||
"whisperThreads": 4, // Legacy thread tuning for subtitle fallback tooling; not used by default.
|
||||
"fixWithAi": false, // Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default. Values: true | false
|
||||
"ai": {
|
||||
"model": "", // Optional model override for legacy subtitle fallback post-processing; not used by default.
|
||||
"systemPrompt": "" // Optional system prompt override for legacy subtitle fallback post-processing; not used by default.
|
||||
}, // Ai setting.
|
||||
"youtube": {
|
||||
"primarySubLanguages": [
|
||||
"ja",
|
||||
"jpn"
|
||||
] // Comma-separated primary subtitle language priority used by the launcher.
|
||||
] // Comma-separated primary subtitle language priority for YouTube auto-loading.
|
||||
}, // Defaults for SubMiner YouTube subtitle loading and languages.
|
||||
|
||||
// ==========================================
|
||||
|
||||
@@ -29,6 +29,8 @@ test('parseLauncherYoutubeSubgenConfig keeps only valid typed values', () => {
|
||||
model: 'openrouter/subgen-model',
|
||||
systemPrompt: 'Fix subtitles only.',
|
||||
},
|
||||
},
|
||||
youtube: {
|
||||
primarySubLanguages: ['ja', 42, 'en'],
|
||||
},
|
||||
secondarySub: {
|
||||
|
||||
@@ -14,6 +14,9 @@ export function parseLauncherYoutubeSubgenConfig(
|
||||
youtubeSubgenRaw && typeof youtubeSubgenRaw === 'object'
|
||||
? (youtubeSubgenRaw as Record<string, unknown>)
|
||||
: null;
|
||||
const youtubeRaw = root.youtube;
|
||||
const youtube =
|
||||
youtubeRaw && typeof youtubeRaw === 'object' ? (youtubeRaw as Record<string, unknown>) : null;
|
||||
const secondarySubRaw = root.secondarySub;
|
||||
const secondarySub =
|
||||
secondarySubRaw && typeof secondarySubRaw === 'object'
|
||||
@@ -74,7 +77,7 @@ export function parseLauncherYoutubeSubgenConfig(
|
||||
}
|
||||
: undefined,
|
||||
),
|
||||
primarySubLanguages: asStringArray(youtubeSubgen?.primarySubLanguages),
|
||||
primarySubLanguages: asStringArray(youtube?.primarySubLanguages),
|
||||
secondarySubLanguages: asStringArray(secondarySub?.secondarySubLanguages),
|
||||
jimakuApiKey: typeof jimaku?.apiKey === 'string' ? jimaku.apiKey : undefined,
|
||||
jimakuApiKeyCommand:
|
||||
|
||||
@@ -919,7 +919,7 @@ test('accepts trailing commas in jsonc', () => {
|
||||
"enabled": "auto",
|
||||
"port": 7788,
|
||||
},
|
||||
"youtubeSubgen": {
|
||||
"youtube": {
|
||||
"primarySubLanguages": ["ja", "en",],
|
||||
},
|
||||
}`,
|
||||
@@ -929,7 +929,7 @@ test('accepts trailing commas in jsonc', () => {
|
||||
const service = new ConfigService(dir);
|
||||
const config = service.getConfig();
|
||||
assert.equal(config.websocket.port, 7788);
|
||||
assert.deepEqual(config.youtubeSubgen.primarySubLanguages, ['ja', 'en']);
|
||||
assert.deepEqual(config.youtube.primarySubLanguages, ['ja', 'en']);
|
||||
});
|
||||
|
||||
test('reloadConfigStrict rejects invalid jsonc and preserves previous config', () => {
|
||||
@@ -1149,8 +1149,10 @@ test('parses global shortcuts and startup settings', () => {
|
||||
"toggleVisibleOverlayGlobal": "Alt+Shift+U",
|
||||
"openJimaku": "Ctrl+Alt+J"
|
||||
},
|
||||
"youtube": {
|
||||
"primarySubLanguages": ["ja", "jpn", "jp"]
|
||||
},
|
||||
"youtubeSubgen": {
|
||||
"primarySubLanguages": ["ja", "jpn", "jp"],
|
||||
"whisperVadModel": "/models/vad.bin",
|
||||
"whisperThreads": 12,
|
||||
"fixWithAi": true
|
||||
@@ -1165,7 +1167,7 @@ test('parses global shortcuts and startup settings', () => {
|
||||
assert.equal(config.ai.apiKeyCommand, 'pass show subminer/ai');
|
||||
assert.equal(config.shortcuts.toggleVisibleOverlayGlobal, 'Alt+Shift+U');
|
||||
assert.equal(config.shortcuts.openJimaku, 'Ctrl+Alt+J');
|
||||
assert.deepEqual(config.youtubeSubgen.primarySubLanguages, ['ja', 'jpn', 'jp']);
|
||||
assert.deepEqual(config.youtube.primarySubLanguages, ['ja', 'jpn', 'jp']);
|
||||
assert.equal(config.youtubeSubgen.whisperVadModel, '/models/vad.bin');
|
||||
assert.equal(config.youtubeSubgen.whisperThreads, 12);
|
||||
assert.equal(config.youtubeSubgen.fixWithAi, true);
|
||||
@@ -2008,7 +2010,8 @@ test('template generator includes known keys', () => {
|
||||
assert.match(output, /"websocket":/);
|
||||
assert.match(output, /"discordPresence":/);
|
||||
assert.match(output, /"startupWarmups":/);
|
||||
assert.match(output, /"youtubeSubgen":/);
|
||||
assert.match(output, /"youtube":/);
|
||||
assert.doesNotMatch(output, /"youtubeSubgen":/);
|
||||
assert.match(output, /"characterDictionary":\s*\{/);
|
||||
assert.match(output, /"preserveLineBreaks": false/);
|
||||
assert.match(output, /"knownWords"\s*:\s*\{/);
|
||||
@@ -2074,17 +2077,11 @@ test('template generator includes known keys', () => {
|
||||
);
|
||||
assert.match(
|
||||
output,
|
||||
/"fixWithAi": false,? \/\/ Legacy subtitle fallback post-processing switch kept for compatibility; use is currently disabled by default\. Values: true \| false/,
|
||||
);
|
||||
assert.match(
|
||||
output,
|
||||
/"systemPrompt": "",? \/\/ Optional system prompt override for legacy subtitle fallback post-processing; not used by default\./,
|
||||
/"primarySubLanguages": \[\s*"ja",\s*"jpn"\s*\],? \/\/ Comma-separated primary subtitle language priority for YouTube auto-loading\./,
|
||||
);
|
||||
assert.doesNotMatch(output, /"mode": "automatic"/);
|
||||
assert.match(
|
||||
output,
|
||||
/"whisperThreads": 4,? \/\/ Legacy thread tuning for subtitle fallback tooling; not used by default\./,
|
||||
);
|
||||
assert.doesNotMatch(output, /"fixWithAi": false/);
|
||||
assert.doesNotMatch(output, /"whisperThreads": 4/);
|
||||
assert.match(
|
||||
output,
|
||||
/"launchAtStartup": true,? \/\/ Launch texthooker server automatically when SubMiner starts\. Values: true \| false/,
|
||||
|
||||
@@ -30,6 +30,7 @@ const {
|
||||
controller,
|
||||
shortcuts,
|
||||
secondarySub,
|
||||
youtube,
|
||||
subsync,
|
||||
startupWarmups,
|
||||
auto_start_overlay,
|
||||
@@ -51,6 +52,7 @@ export const DEFAULT_CONFIG: ResolvedConfig = {
|
||||
ankiConnect,
|
||||
shortcuts,
|
||||
secondarySub,
|
||||
youtube,
|
||||
subsync,
|
||||
startupWarmups,
|
||||
subtitleStyle,
|
||||
|
||||
@@ -11,6 +11,7 @@ export const CORE_DEFAULT_CONFIG: Pick<
|
||||
| 'controller'
|
||||
| 'shortcuts'
|
||||
| 'secondarySub'
|
||||
| 'youtube'
|
||||
| 'subsync'
|
||||
| 'startupWarmups'
|
||||
| 'auto_start_overlay'
|
||||
@@ -93,6 +94,9 @@ export const CORE_DEFAULT_CONFIG: Pick<
|
||||
autoLoadSecondarySub: false,
|
||||
defaultMode: 'hover',
|
||||
},
|
||||
youtube: {
|
||||
primarySubLanguages: ['ja', 'jpn'],
|
||||
},
|
||||
subsync: {
|
||||
defaultMode: 'auto',
|
||||
alass_path: '',
|
||||
|
||||
@@ -152,6 +152,5 @@ export const INTEGRATIONS_DEFAULT_CONFIG: Pick<
|
||||
model: '',
|
||||
systemPrompt: '',
|
||||
},
|
||||
primarySubLanguages: ['ja', 'jpn'],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ test('config option registry includes critical paths and has unique entries', ()
|
||||
'controller.enabled',
|
||||
'controller.scrollPixelsPerSecond',
|
||||
'startupWarmups.lowPowerMode',
|
||||
'youtube.primarySubLanguages',
|
||||
'subtitleStyle.enableJlpt',
|
||||
'subtitleStyle.autoPauseVideoOnYomitanPopup',
|
||||
'ankiConnect.enabled',
|
||||
@@ -43,6 +44,7 @@ test('config template sections include expected domains and unique keys', () =>
|
||||
'annotationWebsocket',
|
||||
'controller',
|
||||
'startupWarmups',
|
||||
'youtube',
|
||||
'subtitleStyle',
|
||||
'ankiConnect',
|
||||
'yomitan',
|
||||
|
||||
@@ -83,6 +83,12 @@ export function buildCoreConfigOptionRegistry(
|
||||
defaultValue: defaultConfig.logging.level,
|
||||
description: 'Minimum log level for runtime logging.',
|
||||
},
|
||||
{
|
||||
path: 'youtube.primarySubLanguages',
|
||||
kind: 'string',
|
||||
defaultValue: defaultConfig.youtube.primarySubLanguages.join(','),
|
||||
description: 'Comma-separated primary subtitle language priority for YouTube auto-loading.',
|
||||
},
|
||||
{
|
||||
path: 'controller.enabled',
|
||||
kind: 'boolean',
|
||||
|
||||
@@ -411,11 +411,5 @@ export function buildIntegrationConfigOptionRegistry(
|
||||
description:
|
||||
'Optional system prompt override for legacy subtitle fallback post-processing; not used by default.',
|
||||
},
|
||||
{
|
||||
path: 'youtubeSubgen.primarySubLanguages',
|
||||
kind: 'string',
|
||||
defaultValue: defaultConfig.youtubeSubgen.primarySubLanguages.join(','),
|
||||
description: 'Comma-separated primary subtitle language priority used by the launcher.',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ const INTEGRATION_TEMPLATE_SECTIONS: ConfigTemplateSection[] = [
|
||||
{
|
||||
title: 'YouTube Playback Settings',
|
||||
description: ['Defaults for SubMiner YouTube subtitle loading and languages.'],
|
||||
key: 'youtubeSubgen',
|
||||
key: 'youtube',
|
||||
},
|
||||
{
|
||||
title: 'Anilist',
|
||||
|
||||
@@ -524,6 +524,21 @@ export function applyCoreDomainConfig(context: ResolveContext): void {
|
||||
}
|
||||
}
|
||||
|
||||
if (isObject(src.youtube)) {
|
||||
if (Array.isArray(src.youtube.primarySubLanguages)) {
|
||||
resolved.youtube.primarySubLanguages = src.youtube.primarySubLanguages.filter(
|
||||
(item): item is string => typeof item === 'string',
|
||||
);
|
||||
} else if (src.youtube.primarySubLanguages !== undefined) {
|
||||
warn(
|
||||
'youtube.primarySubLanguages',
|
||||
src.youtube.primarySubLanguages,
|
||||
resolved.youtube.primarySubLanguages,
|
||||
'Expected string array.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isObject(src.subsync)) {
|
||||
const mode = src.subsync.defaultMode;
|
||||
if (mode === 'auto' || mode === 'manual') {
|
||||
|
||||
@@ -135,16 +135,12 @@ export function applySubtitleDomainConfig(context: ResolveContext): void {
|
||||
warn('youtubeSubgen.ai', src.youtubeSubgen.ai, resolved.youtubeSubgen.ai, 'Expected object.');
|
||||
}
|
||||
|
||||
if (Array.isArray(src.youtubeSubgen.primarySubLanguages)) {
|
||||
resolved.youtubeSubgen.primarySubLanguages = src.youtubeSubgen.primarySubLanguages.filter(
|
||||
(item): item is string => typeof item === 'string',
|
||||
);
|
||||
} else if (src.youtubeSubgen.primarySubLanguages !== undefined) {
|
||||
if (src.youtubeSubgen.primarySubLanguages !== undefined) {
|
||||
warn(
|
||||
'youtubeSubgen.primarySubLanguages',
|
||||
src.youtubeSubgen.primarySubLanguages,
|
||||
resolved.youtubeSubgen.primarySubLanguages,
|
||||
'Expected string array.',
|
||||
undefined,
|
||||
'Removed. Use youtube.primarySubLanguages instead.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1337,7 +1337,7 @@ const startupOsdSequencer = createStartupOsdSequencer({
|
||||
showOsd: (message) => showMpvOsd(message),
|
||||
});
|
||||
const youtubePrimarySubtitleNotificationRuntime = createYoutubePrimarySubtitleNotificationRuntime({
|
||||
getPrimarySubtitleLanguages: () => getResolvedConfig().youtubeSubgen.primarySubLanguages,
|
||||
getPrimarySubtitleLanguages: () => getResolvedConfig().youtube.primarySubLanguages,
|
||||
notifyFailure: (message) => reportYoutubeSubtitleFailure(message),
|
||||
schedule: (fn, delayMs) => setTimeout(fn, delayMs),
|
||||
clearSchedule: clearYoutubePrimarySubtitleNotificationTimer,
|
||||
|
||||
10
src/types.ts
10
src/types.ts
@@ -683,6 +683,10 @@ export interface AiConfig {
|
||||
requestTimeoutMs?: number;
|
||||
}
|
||||
|
||||
export interface YoutubeConfig {
|
||||
primarySubLanguages?: string[];
|
||||
}
|
||||
|
||||
export interface YoutubeSubgenConfig {
|
||||
whisperBin?: string;
|
||||
whisperModel?: string;
|
||||
@@ -690,7 +694,6 @@ export interface YoutubeSubgenConfig {
|
||||
whisperThreads?: number;
|
||||
fixWithAi?: boolean;
|
||||
ai?: AiFeatureConfig;
|
||||
primarySubLanguages?: string[];
|
||||
}
|
||||
|
||||
export interface StatsConfig {
|
||||
@@ -750,6 +753,7 @@ export interface Config {
|
||||
jellyfin?: JellyfinConfig;
|
||||
discordPresence?: DiscordPresenceConfig;
|
||||
ai?: AiConfig;
|
||||
youtube?: YoutubeConfig;
|
||||
youtubeSubgen?: YoutubeSubgenConfig;
|
||||
immersionTracking?: ImmersionTrackingConfig;
|
||||
stats?: StatsConfig;
|
||||
@@ -929,6 +933,9 @@ export interface ResolvedConfig {
|
||||
systemPrompt: string;
|
||||
requestTimeoutMs: number;
|
||||
};
|
||||
youtube: YoutubeConfig & {
|
||||
primarySubLanguages: string[];
|
||||
};
|
||||
youtubeSubgen: YoutubeSubgenConfig & {
|
||||
whisperBin: string;
|
||||
whisperModel: string;
|
||||
@@ -936,7 +943,6 @@ export interface ResolvedConfig {
|
||||
whisperThreads: number;
|
||||
fixWithAi: boolean;
|
||||
ai: AiFeatureConfig;
|
||||
primarySubLanguages: string[];
|
||||
};
|
||||
immersionTracking: {
|
||||
enabled: boolean;
|
||||
|
||||
Reference in New Issue
Block a user