mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-03-24 12:11:29 -07:00
feat: add app-owned YouTube subtitle flow with absPlayer-style parsing (#31)
* fix: harden preload argv parsing for popup windows * fix: align youtube playback with shared overlay startup * fix: unwrap mpv youtube streams for anki media mining * docs: update docs for youtube subtitle and mining flow * refactor: unify cli and runtime wiring for startup and youtube flow * feat: update subtitle sidebar overlay behavior * chore: add shared log-file source for diagnostics * fix(ci): add changelog fragment for immersion changes * fix: address CodeRabbit review feedback * fix: persist canonical title from youtube metadata * style: format stats library tab * fix: address latest review feedback * style: format stats library files * test: stub launcher youtube deps in CI * test: isolate launcher youtube flow deps * test: stub launcher youtube deps in failing case * test: force x11 backend in launcher ci harness * test: address latest review feedback * fix(launcher): preserve user YouTube ytdl raw options * docs(backlog): update task tracking notes * fix(immersion): special-case youtube media paths in runtime and tracking * feat(stats): improve YouTube media metadata and picker key handling * fix(ci): format stats media library hook * fix: address latest CodeRabbit review items * docs: update youtube release notes and docs * feat: auto-load youtube subtitles before manual picker * fix: restore app-owned youtube subtitle flow * docs: update youtube playback docs and config copy * refactor: remove legacy youtube launcher mode plumbing * fix: refine youtube subtitle startup binding * docs: clarify youtube subtitle startup behavior * fix: address PR #31 latest review follow-ups * fix: address PR #31 follow-up review comments * test: harden youtube picker test harness * udpate backlog * fix: add timeout to youtube metadata probe * docs: refresh youtube and stats docs * update backlog * update backlog * chore: release v0.9.0
This commit is contained in:
@@ -14,18 +14,6 @@ export interface JellyfinInvocation {
|
||||
logLevel?: string;
|
||||
}
|
||||
|
||||
export interface YtInvocation {
|
||||
target?: string;
|
||||
outDir?: string;
|
||||
keepTemp?: boolean;
|
||||
whisperBin?: string;
|
||||
whisperModel?: string;
|
||||
whisperVadModel?: string;
|
||||
whisperThreads?: number;
|
||||
ytSubgenAudioFormat?: string;
|
||||
logLevel?: string;
|
||||
}
|
||||
|
||||
export interface CommandActionInvocation {
|
||||
action: string;
|
||||
logLevel?: string;
|
||||
@@ -33,7 +21,6 @@ export interface CommandActionInvocation {
|
||||
|
||||
export interface CliInvocations {
|
||||
jellyfinInvocation: JellyfinInvocation | null;
|
||||
ytInvocation: YtInvocation | null;
|
||||
configInvocation: CommandActionInvocation | null;
|
||||
mpvInvocation: CommandActionInvocation | null;
|
||||
appInvocation: { appArgs: string[] } | null;
|
||||
@@ -89,8 +76,6 @@ function getTopLevelCommand(argv: string[]): { name: string; index: number } | n
|
||||
const commandNames = new Set([
|
||||
'jellyfin',
|
||||
'jf',
|
||||
'yt',
|
||||
'youtube',
|
||||
'doctor',
|
||||
'config',
|
||||
'mpv',
|
||||
@@ -142,7 +127,6 @@ export function parseCliPrograms(
|
||||
invocations: CliInvocations;
|
||||
} {
|
||||
let jellyfinInvocation: JellyfinInvocation | null = null;
|
||||
let ytInvocation: YtInvocation | null = null;
|
||||
let configInvocation: CommandActionInvocation | null = null;
|
||||
let mpvInvocation: CommandActionInvocation | null = null;
|
||||
let appInvocation: { appArgs: string[] } | null = null;
|
||||
@@ -217,38 +201,6 @@ export function parseCliPrograms(
|
||||
};
|
||||
});
|
||||
|
||||
commandProgram
|
||||
.command('yt')
|
||||
.alias('youtube')
|
||||
.description('YouTube workflows')
|
||||
.argument('[target]', 'YouTube URL or ytsearch: query')
|
||||
.option('-o, --out-dir <dir>', 'Subtitle output dir')
|
||||
.option('--keep-temp', 'Keep temp files')
|
||||
.option('--whisper-bin <path>', 'whisper.cpp CLI path')
|
||||
.option('--whisper-model <path>', 'whisper model path')
|
||||
.option('--whisper-vad-model <path>', 'whisper.cpp VAD model path')
|
||||
.option('--whisper-threads <n>', 'whisper.cpp thread count')
|
||||
.option('--yt-subgen-audio-format <format>', 'Audio extraction format')
|
||||
.option('--log-level <level>', 'Log level')
|
||||
.action((target: string | undefined, options: Record<string, unknown>) => {
|
||||
ytInvocation = {
|
||||
target,
|
||||
outDir: typeof options.outDir === 'string' ? options.outDir : undefined,
|
||||
keepTemp: options.keepTemp === true,
|
||||
whisperBin: typeof options.whisperBin === 'string' ? options.whisperBin : undefined,
|
||||
whisperModel: typeof options.whisperModel === 'string' ? options.whisperModel : undefined,
|
||||
whisperVadModel:
|
||||
typeof options.whisperVadModel === 'string' ? options.whisperVadModel : undefined,
|
||||
whisperThreads:
|
||||
typeof options.whisperThreads === 'number' && Number.isFinite(options.whisperThreads)
|
||||
? Math.floor(options.whisperThreads)
|
||||
: undefined,
|
||||
ytSubgenAudioFormat:
|
||||
typeof options.ytSubgenAudioFormat === 'string' ? options.ytSubgenAudioFormat : undefined,
|
||||
logLevel: typeof options.logLevel === 'string' ? options.logLevel : undefined,
|
||||
};
|
||||
});
|
||||
|
||||
commandProgram
|
||||
.command('dictionary')
|
||||
.alias('dict')
|
||||
@@ -382,7 +334,6 @@ export function parseCliPrograms(
|
||||
rootTarget: rootProgram.processedArgs[0],
|
||||
invocations: {
|
||||
jellyfinInvocation,
|
||||
ytInvocation,
|
||||
configInvocation,
|
||||
mpvInvocation,
|
||||
appInvocation,
|
||||
|
||||
Reference in New Issue
Block a user