diff --git a/.dockerignore b/.dockerignore index db5a59e..5621cea 100644 --- a/.dockerignore +++ b/.dockerignore @@ -64,3 +64,5 @@ coverage # Temporary folders tmp temp + +public/thumbnails \ No newline at end of file diff --git a/.gitignore b/.gitignore index df36e21..a63b2a6 100644 --- a/.gitignore +++ b/.gitignore @@ -41,4 +41,6 @@ yarn-error.log* next-env.d.ts public/thumbnails +docker/public/thumbnails + screenshots \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 88f208a..1946fc2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,10 @@ WORKDIR /app ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 -# No additional packages needed for production +# Install FFmpeg for media file analysis +RUN apt-get update && apt-get install -y \ + ffmpeg \ + && rm -rf /var/lib/apt/lists/* RUN groupadd --system --gid 1001 nodejs RUN useradd --system --uid 1001 --gid nodejs nextjs @@ -56,7 +59,7 @@ RUN mkdir -p /app/data /app/media RUN chown -R nextjs:nodejs /app/data /app/media # Copy built application -COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/public ./public COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static # Copy node_modules to ensure native bindings are available diff --git a/data/media.db b/data/media.db new file mode 100644 index 0000000..3c45987 Binary files /dev/null and b/data/media.db differ diff --git a/docker/data/media.db b/docker/data/media.db index 647789c..45e8f66 100644 Binary files a/docker/data/media.db and b/docker/data/media.db differ diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 21ef6d5..4c0324f 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -10,6 +10,7 @@ services: volumes: - ${DB_PATH:-./data}:/app/data - ${MEDIA_PATH:-./media}:/app/media + - ${THUMBNAILS_PATH:-./public/thumbnails}:/app/public/thumbnails - /mnt/data1:/mnt/data1 command: node server.js environment: diff --git a/next.config.ts b/next.config.ts index 225e495..41cbf2e 100644 --- a/next.config.ts +++ b/next.config.ts @@ -2,6 +2,14 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: 'standalone', + async rewrites() { + return [ + { + source: '/thumbnails/:filename*', + destination: '/api/thumbnails/:filename*', + }, + ]; + }, }; export default nextConfig; diff --git a/src/app/api/thumbnails/[filename]/route.ts b/src/app/api/thumbnails/[filename]/route.ts new file mode 100644 index 0000000..e7bde96 --- /dev/null +++ b/src/app/api/thumbnails/[filename]/route.ts @@ -0,0 +1,34 @@ +import { NextRequest, NextResponse } from 'next/server'; +import fs from 'fs'; +import path from 'path'; + +export async function GET( + request: NextRequest, + { params }: { params: Promise<{ filename: string }> } +) { + try { + const { filename } = await params; + + // Construct the path to the thumbnail file + const thumbnailPath = path.join(process.cwd(), 'public', 'thumbnails', filename); + + // Check if the file exists + if (!fs.existsSync(thumbnailPath)) { + return NextResponse.json({ error: 'Thumbnail not found' }, { status: 404 }); + } + + // Read the file + const fileBuffer = fs.readFileSync(thumbnailPath); + + // Return the image with appropriate headers + return new NextResponse(fileBuffer, { + headers: { + 'Content-Type': 'image/png', + 'Cache-Control': 'public, max-age=31536000, immutable', + }, + }); + } catch (error) { + console.error('Error serving thumbnail:', error); + return NextResponse.json({ error: 'Internal server error' }, { status: 500 }); + } +}