Use downloads path rather than direct webdav
This commit is contained in:
parent
a8988b00ac
commit
e16d95eacd
|
|
@ -89,7 +89,8 @@ export function initDatabase() {
|
||||||
intervalMinutes: '180', // 180 minutes = 3 hours
|
intervalMinutes: '180', // 180 minutes = 3 hours
|
||||||
varianceMinutes: '30',
|
varianceMinutes: '30',
|
||||||
maxConcurrentDownloads: '1',
|
maxConcurrentDownloads: '1',
|
||||||
enabled: 'true'
|
enabled: 'true',
|
||||||
|
downloadsPath: path.join(__dirname, '../../downloads')
|
||||||
};
|
};
|
||||||
|
|
||||||
const insertConfig = db.prepare(
|
const insertConfig = db.prepare(
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import express from 'express';
|
import express from 'express';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { initDatabase } from './db/database';
|
import { initDatabase, configOperations } from './db/database';
|
||||||
import { startScheduler } from './services/scheduler';
|
import { startScheduler } from './services/scheduler';
|
||||||
import channelsRouter from './routes/channels';
|
import channelsRouter from './routes/channels';
|
||||||
import playlistsRouter from './routes/playlists';
|
import playlistsRouter from './routes/playlists';
|
||||||
|
|
@ -24,8 +24,9 @@ app.use('/api/playlists', playlistsRouter);
|
||||||
app.use('/api/videos', videosRouter);
|
app.use('/api/videos', videosRouter);
|
||||||
app.use('/api/config', configRouter);
|
app.use('/api/config', configRouter);
|
||||||
|
|
||||||
// Serve downloaded videos
|
// Serve downloaded videos from configured path
|
||||||
app.use('/downloads', express.static(path.join(__dirname, '../downloads')));
|
const downloadsPath = configOperations.get('downloadsPath') || path.join(__dirname, '../downloads');
|
||||||
|
app.use('/downloads', express.static(downloadsPath));
|
||||||
|
|
||||||
// Health check
|
// Health check
|
||||||
app.get('/api/health', (req, res) => {
|
app.get('/api/health', (req, res) => {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,19 @@
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { configOperations } from '../db/database';
|
||||||
|
|
||||||
const DOWNLOADS_DIR = path.join(__dirname, '../../downloads');
|
// Get downloads directory from config
|
||||||
|
function getDownloadsDir(): string {
|
||||||
|
const downloadsPath = configOperations.get('downloadsPath');
|
||||||
|
const dir = downloadsPath || path.join(__dirname, '../../downloads');
|
||||||
|
|
||||||
// Ensure downloads directory exists
|
// Ensure downloads directory exists
|
||||||
if (!fs.existsSync(DOWNLOADS_DIR)) {
|
if (!fs.existsSync(dir)) {
|
||||||
fs.mkdirSync(DOWNLOADS_DIR, { recursive: true });
|
fs.mkdirSync(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Path to cookies file (optional, for additional authentication)
|
// Path to cookies file (optional, for additional authentication)
|
||||||
|
|
@ -296,7 +303,8 @@ export async function downloadVideo(
|
||||||
options: DownloadOptions = {}
|
options: DownloadOptions = {}
|
||||||
): Promise<{ filePath: string; fileSize: number }> {
|
): Promise<{ filePath: string; fileSize: number }> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const outputTemplate = path.join(DOWNLOADS_DIR, `${videoId}.%(ext)s`);
|
const downloadsDir = getDownloadsDir();
|
||||||
|
const outputTemplate = path.join(downloadsDir, `${videoId}.%(ext)s`);
|
||||||
|
|
||||||
const args = [
|
const args = [
|
||||||
...getCommonArgs(),
|
...getCommonArgs(),
|
||||||
|
|
@ -360,10 +368,10 @@ export async function downloadVideo(
|
||||||
|
|
||||||
// Find the downloaded file
|
// Find the downloaded file
|
||||||
if (!outputPath) {
|
if (!outputPath) {
|
||||||
const files = fs.readdirSync(DOWNLOADS_DIR);
|
const files = fs.readdirSync(downloadsDir);
|
||||||
const videoFile = files.find(f => f.startsWith(videoId) && f.endsWith('.mp4'));
|
const videoFile = files.find(f => f.startsWith(videoId) && f.endsWith('.mp4'));
|
||||||
if (videoFile) {
|
if (videoFile) {
|
||||||
outputPath = path.join(DOWNLOADS_DIR, videoFile);
|
outputPath = path.join(downloadsDir, videoFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -224,6 +224,22 @@ function SettingsPage() {
|
||||||
Number of videos to download simultaneously (recommended: 1)
|
Number of videos to download simultaneously (recommended: 1)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||||
|
Downloads Directory Path
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
value={config.downloadsPath || ''}
|
||||||
|
onChange={(e) => handleChange('downloadsPath', e.target.value)}
|
||||||
|
className="mt-1 block w-full rounded-md border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
||||||
|
placeholder="/var/www/vidrip/downloads"
|
||||||
|
/>
|
||||||
|
<p className="mt-1 text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
Absolute path where downloaded videos will be saved. Can point to a mounted WebDAV directory.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-6 flex justify-end">
|
<div className="mt-6 flex justify-end">
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ export interface Config {
|
||||||
varianceMinutes: string;
|
varianceMinutes: string;
|
||||||
maxConcurrentDownloads: string;
|
maxConcurrentDownloads: string;
|
||||||
enabled: string;
|
enabled: string;
|
||||||
|
downloadsPath: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SchedulerStatus {
|
export interface SchedulerStatus {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue