Add Dockerfile for application setup, update next.config.ts for standalone output, enhance documentation for FFMPEG_PATH, and implement ffmpeg location flag in download functionality
This commit is contained in:
55
Dockerfile
Normal file
55
Dockerfile
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
# Install dependencies needed for yt-dlp and ffmpeg
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
python3 \
|
||||||
|
ffmpeg \
|
||||||
|
ca-certificates \
|
||||||
|
&& wget https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp -O /usr/local/bin/yt-dlp \
|
||||||
|
&& chmod a+rx /usr/local/bin/yt-dlp
|
||||||
|
|
||||||
|
# Set environment variables
|
||||||
|
ENV YT_DLP_PATH=/usr/local/bin/yt-dlp
|
||||||
|
ENV FFMPEG_PATH=/usr/bin/ffmpeg
|
||||||
|
|
||||||
|
# Install dependencies only when needed
|
||||||
|
FROM base AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production image
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
# Create downloads directories
|
||||||
|
RUN mkdir -p /app/downloads /app/public/downloads \
|
||||||
|
&& chown -R nextjs:nodejs /app
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
|
||||||
|
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT=3000
|
||||||
|
ENV HOSTNAME="0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
@@ -37,14 +37,19 @@ which yt-dlp
|
|||||||
### Optional Configuration
|
### Optional Configuration
|
||||||
|
|
||||||
#### FFMPEG_PATH
|
#### FFMPEG_PATH
|
||||||
**Optional - Reserved for future use**
|
**Optional - For custom ffmpeg location**
|
||||||
|
|
||||||
Full path to ffmpeg executable (currently not used, but reserved for future configuration).
|
Full path to the ffmpeg executable. Passed to yt-dlp via `--ffmpeg-location` flag. Only needed if ffmpeg is not in your system PATH.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
FFMPEG_PATH=/usr/local/bin/ffmpeg
|
FFMPEG_PATH=/usr/local/bin/ffmpeg
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**When to set this:**
|
||||||
|
- ffmpeg is not installed via package manager
|
||||||
|
- ffmpeg is in a custom location (e.g., Docker, Coolify deployments)
|
||||||
|
- You're using a standalone ffmpeg binary
|
||||||
|
|
||||||
## Configuration Examples
|
## Configuration Examples
|
||||||
|
|
||||||
### Example 1: yt-dlp in Custom Location
|
### Example 1: yt-dlp in Custom Location
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ function getYtDlpPath(): string {
|
|||||||
return process.env.YT_DLP_PATH || 'yt-dlp';
|
return process.env.YT_DLP_PATH || 'yt-dlp';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get ffmpeg location flag for yt-dlp (optional)
|
||||||
|
function getFfmpegLocationFlag(): string {
|
||||||
|
const ffmpegPath = process.env.FFMPEG_PATH;
|
||||||
|
return ffmpegPath ? `--ffmpeg-location "${ffmpegPath}"` : '';
|
||||||
|
}
|
||||||
|
|
||||||
const DOWNLOADS_DIR = path.join(process.cwd(), 'downloads');
|
const DOWNLOADS_DIR = path.join(process.cwd(), 'downloads');
|
||||||
const PUBLIC_DOWNLOADS_DIR = path.join(process.cwd(), 'public', 'downloads');
|
const PUBLIC_DOWNLOADS_DIR = path.join(process.cwd(), 'public', 'downloads');
|
||||||
|
|
||||||
@@ -102,19 +108,21 @@ export async function downloadVideo(
|
|||||||
const outputPath = path.join(DOWNLOADS_DIR, `${fileId}.%(ext)s`);
|
const outputPath = path.join(DOWNLOADS_DIR, `${fileId}.%(ext)s`);
|
||||||
const finalPath = path.join(PUBLIC_DOWNLOADS_DIR, `${fileId}.${outputExt}`);
|
const finalPath = path.join(PUBLIC_DOWNLOADS_DIR, `${fileId}.${outputExt}`);
|
||||||
|
|
||||||
// Get yt-dlp path at runtime
|
// Get yt-dlp path and ffmpeg location at runtime
|
||||||
const ytDlpPath = getYtDlpPath();
|
const ytDlpPath = getYtDlpPath();
|
||||||
|
const ffmpegFlag = getFfmpegLocationFlag();
|
||||||
console.log('[downloadVideo] Using yt-dlp path:', ytDlpPath);
|
console.log('[downloadVideo] Using yt-dlp path:', ytDlpPath);
|
||||||
|
if (ffmpegFlag) console.log('[downloadVideo] Using ffmpeg location flag:', ffmpegFlag);
|
||||||
|
|
||||||
// Download with yt-dlp
|
// Download with yt-dlp
|
||||||
let command = `"${ytDlpPath}" -f "${ytDlpFormat}" -o "${outputPath}" "${url}"`;
|
let command = `"${ytDlpPath}" ${ffmpegFlag} -f "${ytDlpFormat}" -o "${outputPath}" "${url}"`;
|
||||||
|
|
||||||
if (formatType === 'audio' && format === 'mp3') {
|
if (formatType === 'audio' && format === 'mp3') {
|
||||||
// For MP3, we need to extract audio and convert
|
// For MP3, we need to extract audio and convert
|
||||||
command = `"${ytDlpPath}" -f "bestaudio[ext=m4a]/bestaudio" -x --audio-format mp3 --audio-quality 0 -o "${outputPath}" "${url}"`;
|
command = `"${ytDlpPath}" ${ffmpegFlag} -f "bestaudio[ext=m4a]/bestaudio" -x --audio-format mp3 --audio-quality 0 -o "${outputPath}" "${url}"`;
|
||||||
} else if (formatType === 'audio' && format === 'wav') {
|
} else if (formatType === 'audio' && format === 'wav') {
|
||||||
// For WAV, extract and convert
|
// For WAV, extract and convert
|
||||||
command = `"${ytDlpPath}" -f "bestaudio[ext=m4a]/bestaudio" -x --audio-format wav -o "${outputPath}" "${url}"`;
|
command = `"${ytDlpPath}" ${ffmpegFlag} -f "bestaudio[ext=m4a]/bestaudio" -x --audio-format wav -o "${outputPath}" "${url}"`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Increase maxBuffer for downloads as well
|
// Increase maxBuffer for downloads as well
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
output: "standalone",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user