Fix muxing

This commit is contained in:
2026-05-15 04:10:06 +02:00
parent 05faf1ce3b
commit 6deb883472
26 changed files with 662 additions and 169 deletions

View File

@@ -13,6 +13,20 @@ const muxer_1 = require("./muxer");
const config_1 = require("../../config/config");
const mediaUtils_1 = require("../../utils/mediaUtils");
const events_1 = require("events");
function jobTempDir(baseTempDir, jobId) {
return path_1.default.join(baseTempDir, jobId);
}
function safeCleanupJobTmp(dir) {
try {
if (!fs_1.default.existsSync(dir))
return;
(0, mediaUtils_1.cleanupTempFiles)(dir);
fs_1.default.rmSync(dir, { recursive: true, force: true });
}
catch (err) {
console.warn(`Failed to clean up tmp dir ${dir}:`, err.message);
}
}
class JobManager {
constructor() {
this.queue = [];
@@ -33,12 +47,22 @@ class JobManager {
}
createJob(videoPath, configOverride = {}, outputOptions = {}) {
const baseConfig = (0, config_1.getDefaultConfig)();
const mergedConfig = { ...baseConfig, ...configOverride };
// Drop empty/undefined/null values so blank form fields don't clobber the
// baked-in defaults (a blank prompt textarea must NOT overwrite the real
// prompt with "").
const cleanedOverride = {};
for (const [k, v] of Object.entries(configOverride)) {
if (v === '' || v === null || v === undefined)
continue;
cleanedOverride[k] = v;
}
const mergedConfig = { ...baseConfig, ...cleanedOverride };
const filename = path_1.default.basename(videoPath);
const opts = {
audio: outputOptions.audio !== false,
subtitles: outputOptions.subtitles !== false,
muxed: outputOptions.muxed || false
muxed: outputOptions.muxed || false,
muxMode: outputOptions.muxMode === 'mixed' ? 'mixed' : 'separate'
};
return (0, jobStore_1.createJob)(videoPath, filename, mergedConfig, opts);
}
@@ -92,6 +116,18 @@ class JobManager {
throw new Error('Job not found');
if (job.status === 'processing')
throw new Error('Cannot delete a running job');
try {
const config = JSON.parse(job.config);
// job.config may contain either the base tempDir (older jobs) or the
// per-job tempDir (newer jobs). Trim a trailing job-id segment if present;
// otherwise compute the per-job dir from the stored base.
const stored = config.tempDir || './desc/tmp/';
const candidate = path_1.default.basename(stored) === jobId ? stored : jobTempDir(stored, jobId);
safeCleanupJobTmp(candidate);
}
catch {
// ignore: cleanup is best-effort and must not block deletion
}
(0, jobStore_1.deleteJob)(jobId);
}
listJobs() {
@@ -156,6 +192,14 @@ class JobManager {
this.emitProgress(job.id);
const config = JSON.parse(job.config);
const outputOptions = JSON.parse(job.output_options);
// Isolate this job's intermediates so concurrent jobs (or future resumes)
// don't collide on filenames like frame_00001.jpg / segment_3_std.wav.
// The pipeline already reads config.tempDir, so just override it here.
const baseTempDir = config.tempDir || './desc/tmp/';
if (path_1.default.basename(baseTempDir) !== job.id) {
config.tempDir = jobTempDir(baseTempDir, job.id);
}
fs_1.default.mkdirSync(config.tempDir, { recursive: true });
const existingSegments = JSON.parse(job.segments || '[]');
const lastContext = JSON.parse(job.last_context || '{}');
const startIndex = existingSegments.length > 0 ? job.current_index : 0;
@@ -209,8 +253,14 @@ class JobManager {
outputSubtitlesVtt = vttPath;
}
if (outputOptions.muxed && fs_1.default.existsSync(outputAudio)) {
const muxedPath = path_1.default.join(outputDir, `${baseName}_described.mkv`);
(0, muxer_1.muxAudioDescription)(job.video_path, outputAudio, muxedPath);
const isMixed = outputOptions.muxMode === 'mixed';
const muxedPath = path_1.default.join(outputDir, `${baseName}${isMixed ? '_described_mixed' : '_described'}.mkv`);
if (isMixed) {
(0, muxer_1.muxMixedAudioDescription)(job.video_path, outputAudio, muxedPath);
}
else {
(0, muxer_1.muxAudioDescription)(job.video_path, outputAudio, muxedPath);
}
outputMuxed = muxedPath;
}
(0, jobStore_1.saveJobOutputs)(job.id, {
@@ -222,9 +272,11 @@ class JobManager {
(0, jobStore_1.saveCheckpoint)(job.id, JSON.stringify(segments), totalUnits, totalUnits, 0, '{}', 100);
(0, jobStore_1.updateJobStatus)(job.id, 'completed');
this.emitProgress(job.id);
safeCleanupJobTmp(config.tempDir);
}
catch (err) {
if (err.message === 'JOB_PAUSED') {
// Keep config.tempDir intact — restart will resume into the same dir.
(0, jobStore_1.updateJobStatus)(job.id, 'paused');
this.emitProgress(job.id);
return;
@@ -232,6 +284,7 @@ class JobManager {
const errorMsg = err.message || 'Unknown error';
(0, jobStore_1.updateJobStatus)(job.id, 'failed', errorMsg);
this.emitProgress(job.id);
safeCleanupJobTmp(config.tempDir);
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -1 +1,2 @@
export declare function muxAudioDescription(videoPath: string, audioPath: string, outputPath: string): void;
export declare function muxMixedAudioDescription(videoPath: string, audioPath: string, outputPath: string): void;

View File

@@ -4,26 +4,80 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.muxAudioDescription = muxAudioDescription;
exports.muxMixedAudioDescription = muxMixedAudioDescription;
const child_process_1 = require("child_process");
const path_1 = __importDefault(require("path"));
const fs_1 = __importDefault(require("fs"));
function muxAudioDescription(videoPath, audioPath, outputPath) {
const ext = path_1.default.extname(outputPath).toLowerCase();
const isMkv = ext === '.mkv';
const cmd = [
'ffmpeg -v error',
`-i "${videoPath}"`,
`-i "${audioPath}"`,
'-map 0:v',
'-map 0:a?',
'-map 1:a',
'-c:v copy',
'-c:a copy',
isMkv
? '-metadata:s:a:1 title="Audio Description"'
: '-metadata:s:a:1 title="Audio Description"',
`"${outputPath}"`,
'-y'
].join(' ');
(0, child_process_1.execSync)(cmd);
if (!fs_1.default.existsSync(videoPath)) {
throw new Error(`mux: video not found: ${videoPath}`);
}
if (!fs_1.default.existsSync(audioPath)) {
throw new Error(`mux: audio not found: ${audioPath}`);
}
fs_1.default.mkdirSync(path_1.default.dirname(outputPath), { recursive: true });
// Argv form — no shell, no quoting issues, and -y is a global option (placed
// up front, not after the output). Stderr is captured so failures aren't
// silent.
const args = [
'-y',
'-v', 'error',
'-i', videoPath,
'-i', audioPath,
'-map', '0:v',
'-map', '0:a?',
'-map', '1:a',
'-c:v', 'copy',
'-c:a', 'copy',
'-metadata:s:a:1', 'title=Audio Description',
'-disposition:a:1', 'visual_impaired',
outputPath,
];
const result = (0, child_process_1.spawnSync)('ffmpeg', args, { shell: false, encoding: 'utf-8' });
if (result.error) {
throw new Error(`mux: ffmpeg failed to start: ${result.error.message}`);
}
if (result.status !== 0) {
const tail = (result.stderr || '').trim().split('\n').slice(-5).join(' | ');
throw new Error(`mux: ffmpeg exited ${result.status}: ${tail || '(no stderr)'}`);
}
}
function muxMixedAudioDescription(videoPath, audioPath, outputPath) {
if (!fs_1.default.existsSync(videoPath)) {
throw new Error(`mux: video not found: ${videoPath}`);
}
if (!fs_1.default.existsSync(audioPath)) {
throw new Error(`mux: audio not found: ${audioPath}`);
}
fs_1.default.mkdirSync(path_1.default.dirname(outputPath), { recursive: true });
// Sidechain-ducked mix: original audio dips when the AD track is speaking,
// then both are summed into a single output audio stream. The AD track is
// already a full-length file that is silent between description segments
// (built by combineAudioSegments), so asplit gives us one copy to drive the
// sidechain detector and another to mix in on top.
const filterGraph = '[1:a]asplit=2[ad_mix][ad_sc];' +
'[0:a][ad_sc]sidechaincompress=threshold=0.03:ratio=20:attack=5:release=300:level_sc=2[ducked];' +
'[ducked][ad_mix]amix=inputs=2:duration=first:dropout_transition=0:normalize=0[aout]';
const args = [
'-y',
'-v', 'error',
'-i', videoPath,
'-i', audioPath,
'-filter_complex', filterGraph,
'-map', '0:v',
'-map', '[aout]',
'-c:v', 'copy',
'-c:a', 'aac',
'-b:a', '192k',
outputPath,
];
const result = (0, child_process_1.spawnSync)('ffmpeg', args, { shell: false, encoding: 'utf-8' });
if (result.error) {
throw new Error(`mux: ffmpeg failed to start: ${result.error.message}`);
}
if (result.status !== 0) {
const tail = (result.stderr || '').trim().split('\n').slice(-5).join(' | ');
throw new Error(`mux: ffmpeg exited ${result.status}: ${tail || '(no stderr)'}`);
}
}
//# sourceMappingURL=muxer.js.map

View File

@@ -1 +1 @@
{"version":3,"file":"muxer.js","sourceRoot":"","sources":["../../../src/server/services/muxer.ts"],"names":[],"mappings":";;;;;AAGA,kDAyBC;AA5BD,iDAAyC;AACzC,gDAAwB;AAExB,SAAgB,mBAAmB,CACjC,SAAiB,EACjB,SAAiB,EACjB,UAAkB;IAElB,MAAM,GAAG,GAAG,cAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACnD,MAAM,KAAK,GAAG,GAAG,KAAK,MAAM,CAAC;IAE7B,MAAM,GAAG,GAAG;QACV,iBAAiB;QACjB,OAAO,SAAS,GAAG;QACnB,OAAO,SAAS,GAAG;QACnB,UAAU;QACV,WAAW;QACX,UAAU;QACV,WAAW;QACX,WAAW;QACX,KAAK;YACH,CAAC,CAAC,2CAA2C;YAC7C,CAAC,CAAC,2CAA2C;QAC/C,IAAI,UAAU,GAAG;QACjB,IAAI;KACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEZ,IAAA,wBAAQ,EAAC,GAAG,CAAC,CAAC;AAChB,CAAC"}
{"version":3,"file":"muxer.js","sourceRoot":"","sources":["../../../src/server/services/muxer.ts"],"names":[],"mappings":"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"}

View File

@@ -3,5 +3,6 @@ export interface YtDlpResult {
filename: string;
title: string;
}
export type YtDlpProgress = (percent: number) => void;
export declare function isYtDlpAvailable(): boolean;
export declare function downloadVideo(url: string, outputDir: string): YtDlpResult;
export declare function downloadVideo(url: string, outputDir: string, onProgress?: YtDlpProgress): Promise<YtDlpResult>;

View File

@@ -17,22 +17,98 @@ function isYtDlpAvailable() {
return false;
}
}
function downloadVideo(url, outputDir) {
if (!fs_1.default.existsSync(outputDir)) {
fs_1.default.mkdirSync(outputDir, { recursive: true });
}
const outputTemplate = path_1.default.join(outputDir, '%(title)s.%(ext)s');
const result = (0, child_process_1.execSync)(`yt-dlp -f "best[ext=mp4]/best" -o "${outputTemplate}" --print filename --print title "${url}"`, { encoding: 'utf-8', timeout: 600000 });
const lines = result.trim().split('\n');
const filename = lines[0]?.trim();
const title = lines[1]?.trim() || filename;
if (!filename) {
throw new Error('yt-dlp: Failed to parse downloaded filename');
}
const filePath = path_1.default.resolve(outputDir, filename);
if (!fs_1.default.existsSync(filePath)) {
throw new Error(`yt-dlp: Downloaded file not found at ${filePath}`);
}
return { filePath, filename, title };
const PROGRESS_PREFIX = 'PROG ';
function downloadVideo(url, outputDir, onProgress) {
return new Promise((resolve, reject) => {
if (!fs_1.default.existsSync(outputDir)) {
fs_1.default.mkdirSync(outputDir, { recursive: true });
}
const outputTemplate = path_1.default.join(outputDir, '%(title)s.%(ext)s');
// Pass arguments as an array — no shell, no quoting issues, no truncation
// on URLs containing & | % ^ etc. (the original execSync bug on Windows).
const args = [
'-f', 'best[ext=mp4]/best',
'-o', outputTemplate,
'--newline',
'--progress-template', `${PROGRESS_PREFIX}%(progress._percent_str)s`,
'--print', 'after_move:filepath',
'--print', 'title',
'--no-simulate',
url,
];
const child = (0, child_process_1.spawn)('yt-dlp', args, { shell: false });
const stderrLines = [];
const outputLines = [];
let stdoutBuf = '';
let stderrBuf = '';
const handleStdoutLine = (line) => {
if (!line)
return;
if (line.startsWith(PROGRESS_PREFIX)) {
const m = line.slice(PROGRESS_PREFIX.length).match(/([\d.]+)\s*%/);
if (m && onProgress) {
const pct = parseFloat(m[1]);
if (!isNaN(pct))
onProgress(pct);
}
return;
}
outputLines.push(line);
};
child.stdout.on('data', (chunk) => {
stdoutBuf += chunk.toString('utf-8');
let nl;
while ((nl = stdoutBuf.indexOf('\n')) !== -1) {
const line = stdoutBuf.slice(0, nl).replace(/\r$/, '');
stdoutBuf = stdoutBuf.slice(nl + 1);
handleStdoutLine(line.trim());
}
});
child.stderr.on('data', (chunk) => {
stderrBuf += chunk.toString('utf-8');
let nl;
while ((nl = stderrBuf.indexOf('\n')) !== -1) {
const line = stderrBuf.slice(0, nl).replace(/\r$/, '').trim();
stderrBuf = stderrBuf.slice(nl + 1);
if (line)
stderrLines.push(line);
}
});
child.on('error', (err) => {
reject(new Error(`yt-dlp failed to start: ${err.message}`));
});
const timeoutMs = 600000;
const timer = setTimeout(() => {
child.kill();
reject(new Error(`yt-dlp timed out after ${timeoutMs / 1000}s`));
}, timeoutMs);
child.on('close', (code) => {
clearTimeout(timer);
if (stdoutBuf.trim())
handleStdoutLine(stdoutBuf.trim());
if (stderrBuf.trim())
stderrLines.push(stderrBuf.trim());
if (code !== 0) {
const tail = stderrLines.slice(-3).join(' | ') || `exit code ${code}`;
reject(new Error(tail));
return;
}
const filePath = outputLines[0];
const title = outputLines[1] || (filePath ? path_1.default.basename(filePath) : '');
if (!filePath) {
reject(new Error('yt-dlp completed but did not report a filename'));
return;
}
if (!fs_1.default.existsSync(filePath)) {
reject(new Error(`yt-dlp reported success but file not found: ${filePath}`));
return;
}
resolve({
filePath: path_1.default.resolve(filePath),
filename: path_1.default.basename(filePath),
title,
});
});
});
}
//# sourceMappingURL=ytDlp.js.map

View File

@@ -1 +1 @@
{"version":3,"file":"ytDlp.js","sourceRoot":"","sources":["../../../src/server/services/ytDlp.ts"],"names":[],"mappings":";;;;;AAUA,4CAOC;AAED,sCA2BC;AA9CD,iDAAyC;AACzC,gDAAwB;AACxB,4CAAoB;AAQpB,SAAgB,gBAAgB;IAC9B,IAAI,CAAC;QACH,IAAA,wBAAQ,EAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAgB,aAAa,CAAC,GAAW,EAAE,SAAiB;IAC1D,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,YAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,cAAc,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC,CAAC;IAEjE,MAAM,MAAM,GAAG,IAAA,wBAAQ,EACrB,sCAAsC,cAAc,qCAAqC,GAAG,GAAG,EAC/F,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CACvC,CAAC;IAEF,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,QAAQ,CAAC;IAE3C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,QAAQ,GAAG,cAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEnD,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,wCAAwC,QAAQ,EAAE,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACvC,CAAC"}
{"version":3,"file":"ytDlp.js","sourceRoot":"","sources":["../../../src/server/services/ytDlp.ts"],"names":[],"mappings":"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"}