Add resumable admin deep search
This commit is contained in:
@@ -68,6 +68,7 @@ import { registerCatalogRoutes } from './recommendations.js';
|
||||
import QRCode from 'qrcode';
|
||||
import { createYtdlpPool } from './ytdlp-pool.js';
|
||||
import { createWarmQueue } from './warm-queue.js';
|
||||
import { registerDeepSearchRoutes } from './deep-search.js';
|
||||
import { dirname, join as pathJoin } from 'node:path';
|
||||
|
||||
// A media proxy must not die because one client's stream hit an edge case
|
||||
@@ -1113,10 +1114,11 @@ async function ytdlpDownloadResponse(videoId, fp, formatArgs, signal, sourceUrl
|
||||
const tmp = `${tmpdir()}/${tmpBase}.mp4`;
|
||||
const ctl = new AbortController();
|
||||
entry = { waiters: 0, tmpBase, ctl };
|
||||
entry.promise = withSaveSlot(() => {
|
||||
entry.promise = withSaveSlot(async () => {
|
||||
if (ctl.signal.aborted) throw new Error('save cancelled');
|
||||
const url = sourceUrl || await videoCatalog.getSourceUrl(videoId) || `https://www.youtube.com/watch?v=${videoId}`;
|
||||
return runYtdlpResilient([
|
||||
sourceUrl || await videoCatalog.getSourceUrl(videoId) || `https://www.youtube.com/watch?v=${videoId}`,
|
||||
url,
|
||||
'--no-warnings', '--no-playlist',
|
||||
...formatArgs,
|
||||
'--limit-rate', DOWNLOAD_RATE,
|
||||
@@ -1186,14 +1188,16 @@ async function ytdlpEditedDownloadResponse(videoId, fp, keep, signal, cachedSrc
|
||||
try {
|
||||
// 1) Grab the full source (video+audio merged) so ffmpeg has both streams
|
||||
// — unless the server cache already holds it.
|
||||
if (!cachedSrc) await withSaveSlot(() => runYtdlpResilient([
|
||||
await videoCatalog.getSourceUrl(videoId) || `https://www.youtube.com/watch?v=${videoId}`,
|
||||
'--no-warnings', '--no-playlist',
|
||||
'-f', SAVE_MUX_FORMAT,
|
||||
'--merge-output-format', 'mp4',
|
||||
'--limit-rate', DOWNLOAD_RATE,
|
||||
'-o', srcTmp,
|
||||
], { signal }));
|
||||
if (!cachedSrc) await withSaveSlot(async () => {
|
||||
const url = await videoCatalog.getSourceUrl(videoId) || `https://www.youtube.com/watch?v=${videoId}`;
|
||||
return runYtdlpResilient([
|
||||
url, '--no-warnings', '--no-playlist',
|
||||
'-f', SAVE_MUX_FORMAT,
|
||||
'--merge-output-format', 'mp4',
|
||||
'--limit-rate', DOWNLOAD_RATE,
|
||||
'-o', srcTmp,
|
||||
], { signal });
|
||||
});
|
||||
// 2) Trim + concat the keep segments into the final custom video.
|
||||
await runFfmpeg([
|
||||
'-y', '-hide_banner', '-loglevel', 'error',
|
||||
@@ -2295,6 +2299,8 @@ app.get('/api/remote/qr/:code', async (c) => {
|
||||
// ============================================================================
|
||||
const notes = registerNoteRoutes(app, {
|
||||
db: notesDb,
|
||||
catalog: videoCatalog,
|
||||
media,
|
||||
getProfile,
|
||||
profileNameRe: PROFILE_NAME_RE,
|
||||
runYtdlp: runYtdlpResilient,
|
||||
@@ -2308,6 +2314,9 @@ const notes = registerNoteRoutes(app, {
|
||||
{ label: 'Database', path: dirname(process.env.DB_PATH || './data/ytplayer.db') },
|
||||
] },
|
||||
});
|
||||
const deepSearch = registerDeepSearchRoutes(app, { db: notesDb, adminAuth: notes.requireAdminOrToken, autoStart: false,
|
||||
searchDeep: innertube.searchDeep, related: innertube.related, browseUploads: innertube.browseUploads,
|
||||
ingest: collectVideoMetadata, putSearch: searchCacheDb.put });
|
||||
|
||||
// ============================================================================
|
||||
// Uploads — the server's own searchable media library (see uploads.js)
|
||||
@@ -2519,6 +2528,7 @@ app.get('/*', indexHtml);
|
||||
// ============================================================================
|
||||
async function main() {
|
||||
await initDb();
|
||||
deepSearch.start();
|
||||
startThumbnails();
|
||||
await p2pDb.initP2pSchema();
|
||||
console.log(`[ytplayer] DB ready`);
|
||||
|
||||
Reference in New Issue
Block a user