|
|
|
|
@@ -132,6 +132,8 @@ app.get('/api/favorites', (_request, response) => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.get('/api/local-videos', async (_request, response) => {
|
|
|
|
|
response.set('Cache-Control', 'no-store');
|
|
|
|
|
|
|
|
|
|
if (!LOCAL_VIDEOS_ROOT) {
|
|
|
|
|
response.json({ enabled: false, videos: [] });
|
|
|
|
|
return;
|
|
|
|
|
@@ -658,10 +660,13 @@ function getLocalVideosRealRoot() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!localVideosRealRootPromise) {
|
|
|
|
|
localVideosRealRootPromise = fs.realpath(LOCAL_VIDEOS_ROOT).catch((error) => {
|
|
|
|
|
localVideosRealRootPromise = null;
|
|
|
|
|
throw new Error(`Local videos directory is unavailable: ${error.message}`);
|
|
|
|
|
});
|
|
|
|
|
localVideosRealRootPromise = fs.realpath(LOCAL_VIDEOS_ROOT)
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
throw new Error(`Local videos directory is unavailable: ${error.message}`);
|
|
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
localVideosRealRootPromise = null;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return localVideosRealRootPromise;
|
|
|
|
|
@@ -2798,6 +2803,7 @@ function buildFrameArgs(session, inputUrl, inputOptions) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildInputArgs(inputUrl, { seekable = true, startTime = 0 } = {}) {
|
|
|
|
|
const isHttpInput = isHttpInputUrl(inputUrl);
|
|
|
|
|
const args = [
|
|
|
|
|
'-hide_banner',
|
|
|
|
|
'-nostdin',
|
|
|
|
|
@@ -2806,7 +2812,7 @@ function buildInputArgs(inputUrl, { seekable = true, startTime = 0 } = {}) {
|
|
|
|
|
'-nostats',
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
if (seekable) {
|
|
|
|
|
if (seekable && isHttpInput) {
|
|
|
|
|
args.push('-seekable', startTime > 0 ? '1' : FFMPEG_INPUT_SEEKABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2814,7 +2820,7 @@ function buildInputArgs(inputUrl, { seekable = true, startTime = 0 } = {}) {
|
|
|
|
|
args.push('-ss', formatFfmpegSeconds(startTime));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (FFMPEG_HTTP_RECONNECT && isHttpInputUrl(inputUrl)) {
|
|
|
|
|
if (FFMPEG_HTTP_RECONNECT && isHttpInput) {
|
|
|
|
|
args.push(
|
|
|
|
|
'-reconnect',
|
|
|
|
|
'1',
|
|
|
|
|
@@ -2849,7 +2855,7 @@ function formatFfmpegSeconds(seconds) {
|
|
|
|
|
|
|
|
|
|
function buildFrameOutputArgs(session, outputUrl) {
|
|
|
|
|
const { fps, quality, width } = session.options;
|
|
|
|
|
const videoFilter = `fps=${fps},scale=w='min(${width},iw)':h=-2:flags=bicubic:out_range=pc,format=yuvj420p`;
|
|
|
|
|
const videoFilter = `fps=${fps},scale=w='min(${width},iw)':h=-2:flags=bicubic:out_range=pc,format=yuvj420p,realtime`;
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'-an',
|
|
|
|
|
|