Fix muxing
This commit is contained in:
40
dist/server/routes/config.js
vendored
40
dist/server/routes/config.js
vendored
@@ -2,10 +2,43 @@
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const jobStore_1 = require("../db/jobStore");
|
||||
const config_1 = require("../../config/config");
|
||||
const router = (0, express_1.Router)();
|
||||
// Optional .env overrides for the (long) prompt strings — keep getDefaultConfig()'s
|
||||
// hardcoded prompts as the final fallback. Users who want to tweak prompts without
|
||||
// editing source can set these in .env, or set them per-job in the Settings UI.
|
||||
const ENV_OVERRIDES = {
|
||||
defaultPrompt: process.env.AIDIO_DEFAULT_PROMPT,
|
||||
changePrompt: process.env.AIDIO_CHANGE_PROMPT,
|
||||
batchPrompt: process.env.AIDIO_BATCH_PROMPT,
|
||||
};
|
||||
// Fields in Config that are nested objects (provider configs, etc.) and shouldn't
|
||||
// be flattened into the form-facing config map. API keys live inside these — keep
|
||||
// them off the wire.
|
||||
const NESTED_FIELDS = new Set(['visionProviders', 'ttsProviders']);
|
||||
function buildLayeredConfig() {
|
||||
const defaults = (0, config_1.getDefaultConfig)();
|
||||
const db = (0, jobStore_1.getAllConfig)();
|
||||
const merged = {};
|
||||
for (const [key, value] of Object.entries(defaults)) {
|
||||
if (NESTED_FIELDS.has(key))
|
||||
continue;
|
||||
if (value === undefined || value === null)
|
||||
continue;
|
||||
merged[key] = String(value);
|
||||
}
|
||||
for (const [key, value] of Object.entries(ENV_OVERRIDES)) {
|
||||
if (value !== undefined && value !== '')
|
||||
merged[key] = value;
|
||||
}
|
||||
for (const [key, value] of Object.entries(db)) {
|
||||
if (value !== undefined && value !== '')
|
||||
merged[key] = value;
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
router.get('/', (_req, res) => {
|
||||
const config = (0, jobStore_1.getAllConfig)();
|
||||
res.json({ config });
|
||||
res.json({ config: buildLayeredConfig() });
|
||||
});
|
||||
router.put('/', (req, res) => {
|
||||
const updates = req.body;
|
||||
@@ -16,8 +49,7 @@ router.put('/', (req, res) => {
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
(0, jobStore_1.setConfigValue)(key, String(value));
|
||||
}
|
||||
const config = (0, jobStore_1.getAllConfig)();
|
||||
res.json({ config });
|
||||
res.json({ config: buildLayeredConfig() });
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=config.js.map
|
||||
2
dist/server/routes/config.js.map
vendored
2
dist/server/routes/config.js.map
vendored
@@ -1 +1 @@
|
||||
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/routes/config.ts"],"names":[],"mappings":";;AAAA,qCAAoD;AACpD,6CAA8D;AAE9D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IAC/C,MAAM,MAAM,GAAG,IAAA,uBAAY,GAAE,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;IACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAA,yBAAc,EAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,uBAAY,GAAE,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
|
||||
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/routes/config.ts"],"names":[],"mappings":";;AAAA,qCAAoD;AACpD,6CAA8D;AAC9D,gDAAuD;AAEvD,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,oFAAoF;AACpF,mFAAmF;AACnF,gFAAgF;AAChF,MAAM,aAAa,GAAuC;IACxD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,oBAAoB;IAC/C,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;IAC7C,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;CAC5C,CAAC;AAEF,kFAAkF;AAClF,kFAAkF;AAClF,qBAAqB;AACrB,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC,CAAC;AAEnE,SAAS,kBAAkB;IACzB,MAAM,QAAQ,GAAG,IAAA,yBAAgB,GAAwC,CAAC;IAC1E,MAAM,EAAE,GAAG,IAAA,uBAAY,GAAE,CAAC;IAE1B,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,IAAI,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACrC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QACpD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QACzD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/D,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAC/D,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;IACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAA,yBAAc,EAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
|
||||
72
dist/server/routes/files.js
vendored
72
dist/server/routes/files.js
vendored
@@ -65,23 +65,69 @@ router.get('/', (_req, res) => {
|
||||
.sort((a, b) => b.filePath.localeCompare(a.filePath));
|
||||
res.json({ files });
|
||||
});
|
||||
router.post('/youtube', (req, res) => {
|
||||
router.delete('/:filename', (req, res) => {
|
||||
const raw = req.params.filename;
|
||||
const requested = Array.isArray(raw) ? raw[0] : raw;
|
||||
if (!requested) {
|
||||
res.status(400).json({ error: 'filename is required' });
|
||||
return;
|
||||
}
|
||||
const resolved = path_1.default.resolve(UPLOADS_DIR, requested);
|
||||
const uploadsWithSep = UPLOADS_DIR.endsWith(path_1.default.sep) ? UPLOADS_DIR : UPLOADS_DIR + path_1.default.sep;
|
||||
if (!resolved.startsWith(uploadsWithSep)) {
|
||||
res.status(400).json({ error: 'Invalid filename' });
|
||||
return;
|
||||
}
|
||||
if (!fs_1.default.existsSync(resolved)) {
|
||||
res.status(404).json({ error: 'File not found' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
fs_1.default.unlinkSync(resolved);
|
||||
res.json({ ok: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(500).json({ error: `Failed to delete: ${err.message}` });
|
||||
}
|
||||
});
|
||||
// Stream yt-dlp download progress over SSE.
|
||||
// Returns events: {type:'progress', percent} ... {type:'done', filePath, filename, title}
|
||||
// or {type:'error', message}
|
||||
router.get('/youtube/stream', (req, res) => {
|
||||
const url = req.query.url || '';
|
||||
if (!url) {
|
||||
res.status(400).json({ error: 'url query param is required' });
|
||||
return;
|
||||
}
|
||||
if (!(0, ytDlp_1.isYtDlpAvailable)()) {
|
||||
res.status(400).json({ error: 'yt-dlp is not installed or not in PATH' });
|
||||
return;
|
||||
}
|
||||
const { url } = req.body;
|
||||
if (!url) {
|
||||
res.status(400).json({ error: 'URL is required' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = (0, ytDlp_1.downloadVideo)(url, UPLOADS_DIR);
|
||||
res.json(result);
|
||||
}
|
||||
catch (err) {
|
||||
res.status(500).json({ error: `Failed to download: ${err.message}` });
|
||||
}
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.setHeader('X-Accel-Buffering', 'no');
|
||||
res.flushHeaders?.();
|
||||
const send = (data) => {
|
||||
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
||||
};
|
||||
let clientGone = false;
|
||||
req.on('close', () => { clientGone = true; });
|
||||
(0, ytDlp_1.downloadVideo)(url, UPLOADS_DIR, (percent) => {
|
||||
if (clientGone)
|
||||
return;
|
||||
send({ type: 'progress', percent });
|
||||
}).then((result) => {
|
||||
if (clientGone)
|
||||
return;
|
||||
send({ type: 'done', ...result });
|
||||
res.end();
|
||||
}).catch((err) => {
|
||||
if (clientGone)
|
||||
return;
|
||||
send({ type: 'error', message: err.message });
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=files.js.map
|
||||
2
dist/server/routes/files.js.map
vendored
2
dist/server/routes/files.js.map
vendored
File diff suppressed because one or more lines are too long
7
dist/server/routes/jobs.js
vendored
7
dist/server/routes/jobs.js
vendored
@@ -145,10 +145,13 @@ function createJobsRouter(jobManager) {
|
||||
filePath = format === 'vtt' ? job.output_subtitles_vtt : job.output_subtitles_srt;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}_description.${format}`;
|
||||
break;
|
||||
case 'muxed':
|
||||
case 'muxed': {
|
||||
const opts = JSON.parse(job.output_options || '{}');
|
||||
const suffix = opts.muxMode === 'mixed' ? '_described_mixed' : '_described';
|
||||
filePath = job.output_muxed;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}_described.mkv`;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}${suffix}.mkv`;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
res.status(400).json({ error: 'Invalid download type' });
|
||||
return;
|
||||
|
||||
2
dist/server/routes/jobs.js.map
vendored
2
dist/server/routes/jobs.js.map
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user