From e248613abb106546e611d2fbd05b2b8849a94889 Mon Sep 17 00:00:00 2001 From: tigeren Date: Mon, 25 Aug 2025 08:11:03 +0000 Subject: [PATCH] feat: add media library management features, including scanning and displaying photos and videos; implement database integration for media files --- CLAUDE.md | 25 ++++ media.db | Bin 24576 -> 24576 bytes screenshot/image copy.png | Bin 110729 -> 0 bytes src/app/api/files/route.ts | 27 +++++ src/app/api/photos/route.ts | 7 ++ src/app/folder-viewer/page.tsx | 84 +++++++++++--- src/app/photos/page.tsx | 85 ++++++++++++++ src/app/settings/page.tsx | 205 ++++++++++++++++++++++++++------- src/app/videos/page.tsx | 58 ++++++++-- src/components/ui/alert.tsx | 58 ++++++++++ src/lib/scanner.ts | 51 ++++++-- 11 files changed, 525 insertions(+), 75 deletions(-) create mode 100644 CLAUDE.md delete mode 100644 screenshot/image copy.png create mode 100644 src/app/api/photos/route.ts create mode 100644 src/app/photos/page.tsx create mode 100644 src/components/ui/alert.tsx diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1cd3ffa --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,25 @@ +Project Description: +This is a nextjs project, basically a youtube like video sites. + +Feature requirement: +1. Has a youtube like UI +2. has a concept of media library. each library is a path that mounted in the /mnt +3. has the ability to scan the media libaries +4. the quntitiy of media files can be vast, tens of thousands videos +5. the media can work with photos and videos +6. user can manage(add/remove) the media libraries. +7. there should be a database(sqlite) to save the media informations +8. there should be at least two tables in the database, one to keep the video informations, such as path, size, thumbnails, title, etc(not limit to these); one to keep the media libraries. videos should be linked to the library +9. thumbnail generate feature + + +UI: +1. two main areas, left is the left sidebar, right is the main video area +2. side bar can be expanded and collapsed +3. sidebar should have these sections: Settings, Videos, Photos, Folder Viewer +4. Settings section: open manage page in the main area, allow user to add media library path; delete library. +5. Videos section: open video cards page in the main area, each card has thumbnail pic displayed. the card lower part display video path, size. +6. photo section: TBD +7. folder viewer: list libraries in the side bar folder viewer section. once one of the folder is selected, display the folder sturcture in the main area. the vdieo or photo display thunbnail and information as the video card would do. for the folder, display the folder icon, which can be entered in + + diff --git a/media.db b/media.db index f6177dbd78c8f0925f17f847a2afa4e3d1985973..2b38a25edaaf54bfe346798ad5114a1410a09797 100644 GIT binary patch delta 83 zcmZoTz}Rqrae_1>>qHr6M%Il9{ql@VlRwCdZDtdA!7n4otj?&Pn^&Trl30>xsP7xb n#LK|Iz{vlRf&b%XL5Ju3{Jf0J@{Bo|Nkxf8nW@E0iyRaH**g~z delta 86 zcmZoTz}Rqrae_1>^F$eEM&^wP{ql^AlRwCdvAk#Cf4^DK;VHkg0JA!$er{fgeoA6V qqM^QT7%u|@10(+@2L4Y#1uyvdco>=GIdd|TiV}-5Q;QclC;$Lh#Th^V diff --git a/screenshot/image copy.png b/screenshot/image copy.png deleted file mode 100644 index 011dca8fb4ed87486c80be01c9d339755b0d0116..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 110729 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 + const result = files.map((file) => { const filePath = path.join(dirPath, file); const stats = fs.statSync(filePath); + const ext = path.extname(file).toLowerCase(); + + let type = 'file'; + if (VIDEO_EXTENSIONS.some(v => ext.includes(v))) { + type = 'video'; + } else if (PHOTO_EXTENSIONS.some(p => ext.includes(p))) { + type = 'photo'; + } + + // Find matching media file in database + const mediaFile = mediaFiles.find((m: any) => m.path === filePath); + return { name: file, path: filePath, isDirectory: stats.isDirectory(), size: stats.size, + type: mediaFile?.type || type, + thumbnail: mediaFile?.thumbnail, }; }); + return NextResponse.json(result); } catch (error: any) { return NextResponse.json({ error: error.message }, { status: 500 }); diff --git a/src/app/api/photos/route.ts b/src/app/api/photos/route.ts new file mode 100644 index 0000000..d1019a9 --- /dev/null +++ b/src/app/api/photos/route.ts @@ -0,0 +1,7 @@ +import { NextResponse } from 'next/server'; +import db from '@/db'; + +export async function GET() { + const photos = db.prepare('SELECT * FROM media WHERE type = ?').all('photo'); + return NextResponse.json(photos); +} \ No newline at end of file diff --git a/src/app/folder-viewer/page.tsx b/src/app/folder-viewer/page.tsx index 0397071..1fc8a62 100644 --- a/src/app/folder-viewer/page.tsx +++ b/src/app/folder-viewer/page.tsx @@ -3,15 +3,17 @@ import { useState, useEffect, Suspense } from "react"; import { useSearchParams } from "next/navigation"; -import { Folder, File } from "lucide-react"; +import { Folder, File, Image, Film } from "lucide-react"; import Link from "next/link"; -import { Card, CardContent } from "@/components/ui/card"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; interface FileSystemItem { name: string; path: string; isDirectory: boolean; size: number; + thumbnail?: string; + type?: string; } const FolderViewerPage = () => { @@ -31,32 +33,88 @@ const FolderViewerPage = () => { setItems(data); }; + const formatFileSize = (bytes: number) => { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + const getFileIcon = (item: FileSystemItem) => { + if (item.isDirectory) return ; + if (item.type === 'photo') return ; + if (item.type === 'video') return ; + return ; + }; + + const isMediaFile = (item: FileSystemItem) => { + return item.type === 'video' || item.type === 'photo'; + }; + if (!path) { - return
Select a library from the sidebar
; + return ( +
+
+

Select a library from the sidebar

+

Choose a media library above to browse its contents

+
+
+ ); } return ( -
-

{path}

-
+
+

{path}

+
{items.map((item) => ( - + {item.isDirectory ? ( - - - {item.name} + +
+ +
+ ) : isMediaFile(item) ? ( +
+ {item.name} { + (e.target as HTMLImageElement).src = '/placeholder.svg'; + }} + /> +
+ {item.type === 'video' ? ( + + ) : ( + + )} +
+
) : ( -
- - {item.name} +
+ {getFileIcon(item)}
)} + + {item.name} + +
Size: {formatFileSize(item.size)}
+ {!item.isDirectory &&
Type: {item.type || 'File'}
} +
+
))}
+ {items.length === 0 && ( +
+

No items found in this directory.

+
+ )}
); }; diff --git a/src/app/photos/page.tsx b/src/app/photos/page.tsx new file mode 100644 index 0000000..29be2ac --- /dev/null +++ b/src/app/photos/page.tsx @@ -0,0 +1,85 @@ +'use client'; + +import { useEffect, useState } from 'react'; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; + +interface Photo { + id: number; + path: string; + title: string; + size: number; + thumbnail: string; + type: string; +} + +export default function PhotosPage() { + const [photos, setPhotos] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + fetchPhotos(); + }, []); + + const fetchPhotos = async () => { + try { + const response = await fetch('/api/photos'); + const data = await response.json(); + setPhotos(data); + } catch (error) { + console.error('Error fetching photos:', error); + } finally { + setLoading(false); + } + }; + + const formatFileSize = (bytes: number) => { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + if (loading) { + return ( +
+
Loading photos...
+
+ ); + } + + return ( +
+

Photos

+
+ {photos.map((photo) => ( + + + {photo.title} { + (e.target as HTMLImageElement).src = '/placeholder-image.jpg'; + }} + /> + + + {photo.title} + +
Size: {formatFileSize(photo.size)}
+
Path: {photo.path}
+
+
+
+ ))} +
+ {photos.length === 0 && ( +
+

No photos found. Add media libraries to scan for photos.

+
+ )} +
+ ); +} \ No newline at end of file diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index b7ef136..3a980cb 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -4,8 +4,10 @@ import { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Header } from "@/components/ui/header"; +import { Alert, AlertDescription } from "@/components/ui/alert"; +import { Trash2, Plus, Folder, HardDrive } from "lucide-react"; interface Library { id: number; @@ -15,38 +17,65 @@ interface Library { const SettingsPage = () => { const [libraries, setLibraries] = useState([]); const [newLibraryPath, setNewLibraryPath] = useState(""); + const [error, setError] = useState(null); + const [scanStatus, setScanStatus] = useState(""); useEffect(() => { fetchLibraries(); }, []); const fetchLibraries = async () => { - const res = await fetch("/api/libraries"); - const data = await res.json(); - setLibraries(data); + try { + const res = await fetch("/api/libraries"); + const data = await res.json(); + setLibraries(data); + } catch (error) { + console.error('Error fetching libraries:', error); + } }; const addLibrary = async () => { - if (!newLibraryPath) return; - const res = await fetch("/api/libraries", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ path: newLibraryPath }), - }); - if (res.ok) { - setNewLibraryPath(""); - fetchLibraries(); + if (!newLibraryPath.trim()) { + setError("Please enter a valid path"); + return; + } + + try { + const res = await fetch("/api/libraries", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ path: newLibraryPath.trim() }), + }); + + if (res.ok) { + setNewLibraryPath(""); + setError(null); + fetchLibraries(); + } else { + const data = await res.json(); + setError(data.error || "Failed to add library"); + } + } catch (error) { + setError("Network error occurred"); } }; const deleteLibrary = async (id: number) => { - const res = await fetch(`/api/libraries/${id}`, { - method: "DELETE", - }); - if (res.ok) { - fetchLibraries(); + if (!confirm("Are you sure you want to delete this library? This will not delete the actual files.")) { + return; + } + + try { + const res = await fetch(`/api/libraries/${id}`, { + method: "DELETE", + }); + if (res.ok) { + fetchLibraries(); + } + } catch (error) { + console.error('Error deleting library:', error); } }; @@ -54,56 +83,146 @@ const SettingsPage = () => { const scanLibraries = async () => { setIsScanning(true); - const res = await fetch("/api/scan", { - method: "POST", - }); - if (res.ok) { - alert("Scan complete"); + setScanStatus("Scanning libraries..."); + + try { + const res = await fetch("/api/scan", { + method: "POST", + }); + + if (res.ok) { + setScanStatus("Scan completed successfully!"); + setTimeout(() => setScanStatus(""), 3000); + } else { + setScanStatus("Scan failed. Please try again."); + } + } catch (error) { + setScanStatus("Network error during scan"); + } finally { + setIsScanning(false); } - setIsScanning(false); + }; + + const getTotalStorage = () => { + return libraries.reduce((total, lib) => { + // Rough estimation based on path length + return total + (lib.path.length * 100); // Placeholder calculation + }, 0); }; return ( -
+
+ + {error && ( + + {error} + + )} + + {scanStatus && ( + + {scanStatus} + + )} +
- Manage Media Libraries + + + Manage Media Libraries + + + Add or remove media library paths to scan for videos and photos + -
+
setNewLibraryPath(e.target.value)} + onChange={(e) => { + setNewLibraryPath(e.target.value); + setError(null); + }} + onKeyPress={(e) => e.key === 'Enter' && addLibrary()} + className="flex-1" /> - +
-
-

Existing Libraries

-
    + + {libraries.length > 0 ? ( +
    +

    Existing Libraries ({libraries.length})

    {libraries.map((lib) => ( -
  • - {lib.path} - -
  • +
    ))} -
-
+
+ ) : ( +
+ +

No media libraries configured yet.

+

Add your first library above to get started.

+
+ )}
+ - Media Scanner + Media Scanner + + Scan your libraries for new videos and photos + - +

+ {libraries.length === 0 + ? "Add at least one library to enable scanning" + : "This will scan all configured libraries for new media files"} +

+
+
+ + + + System Information + + +
+ Libraries: + {libraries.length} +
+
+ Database: + SQLite +
diff --git a/src/app/videos/page.tsx b/src/app/videos/page.tsx index d2e8a94..f2860d1 100644 --- a/src/app/videos/page.tsx +++ b/src/app/videos/page.tsx @@ -5,7 +5,7 @@ import { useState, useEffect } from "react"; import { Card, CardContent, - CardFooter, + CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; @@ -21,35 +21,71 @@ interface Video { const VideosPage = () => { const [videos, setVideos] = useState([]); + const [loading, setLoading] = useState(true); useEffect(() => { fetchVideos(); }, []); const fetchVideos = async () => { - const res = await fetch("/api/videos"); - const data = await res.json(); - setVideos(data); + try { + const res = await fetch("/api/videos"); + const data = await res.json(); + setVideos(data); + } catch (error) { + console.error('Error fetching videos:', error); + } finally { + setLoading(false); + } }; + const formatFileSize = (bytes: number) => { + if (bytes === 0) return '0 Bytes'; + const k = 1024; + const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const i = Math.floor(Math.log(bytes) / Math.log(k)); + return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; + }; + + if (loading) { + return ( +
+
Loading videos...
+
+ ); + } + return ( -
+
-
+
{videos.map((video) => ( - {video.title} + {video.title} { + (e.target as HTMLImageElement).src = '/placeholder.svg'; + }} + /> - {video.title} + {video.title} + +
Size: {formatFileSize(video.size)}
+
Path: {video.path}
+
- -

{video.path}

-
))}
+ {videos.length === 0 && ( +
+

No videos found. Add media libraries to scan for videos.

+
+ )}
); }; diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx new file mode 100644 index 0000000..fc218ce --- /dev/null +++ b/src/components/ui/alert.tsx @@ -0,0 +1,58 @@ +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { cn } from "@/lib/utils" + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + } +) + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)) +Alert.displayName = "Alert" + +const AlertTitle = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertTitle.displayName = "AlertTitle" + +const AlertDescription = React.forwardRef< + HTMLParagraphElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +AlertDescription.displayName = "AlertDescription" + +export { Alert, AlertTitle, AlertDescription } \ No newline at end of file diff --git a/src/lib/scanner.ts b/src/lib/scanner.ts index e4cc83e..eaff9a1 100644 --- a/src/lib/scanner.ts +++ b/src/lib/scanner.ts @@ -4,10 +4,10 @@ import path from "path"; import fs from "fs"; import ffmpeg from "fluent-ffmpeg"; -const VIDEO_EXTENSIONS = ["mp4", "mkv", "avi", "mov", "wmv"]; -const PHOTO_EXTENSIONS = ["jpg", "jpeg", "png", "gif"]; +const VIDEO_EXTENSIONS = ["mp4", "mkv", "avi", "mov", "wmv", "flv", "webm", "m4v"]; +const PHOTO_EXTENSIONS = ["jpg", "jpeg", "png", "gif", "bmp", "webp", "tiff", "svg"]; -const generateThumbnail = (videoPath: string, thumbnailPath: string) => { +const generateVideoThumbnail = (videoPath: string, thumbnailPath: string) => { return new Promise((resolve, reject) => { ffmpeg(videoPath) .on("end", () => resolve(thumbnailPath)) @@ -17,19 +17,44 @@ const generateThumbnail = (videoPath: string, thumbnailPath: string) => { folder: path.dirname(thumbnailPath), filename: path.basename(thumbnailPath), size: "320x240", + timemarks: ["10%"] }); }); }; +const generatePhotoThumbnail = (photoPath: string, thumbnailPath: string) => { + return new Promise((resolve, reject) => { + ffmpeg(photoPath) + .on("end", () => resolve(thumbnailPath)) + .on("error", (err) => reject(err)) + .outputOptions(["-vf", "scale=320:240:force_original_aspect_ratio=decrease", "-quality", "85"]) + .output(thumbnailPath) + .run(); + }); +}; + const scanLibrary = async (library: { id: number; path: string }) => { - const mediaFiles = await glob(`${library.path}/**/*.{${VIDEO_EXTENSIONS.join(",")}}`, { + // Scan videos + const videoFiles = await glob(`${library.path}/**/*.{${VIDEO_EXTENSIONS.join(",")}}`, { nodir: true, }); - for (const file of mediaFiles) { + // Scan photos + const photoFiles = await glob(`${library.path}/**/*.{${PHOTO_EXTENSIONS.join(",")}}`, { + nodir: true, + }); + + const allFiles = [...videoFiles, ...photoFiles]; + + for (const file of allFiles) { const stats = fs.statSync(file); const title = path.basename(file); - const thumbnailFileName = `${path.parse(title).name}.png`; + const ext = path.extname(file).toLowerCase(); + const isVideo = VIDEO_EXTENSIONS.some(v => ext.includes(v)); + const isPhoto = PHOTO_EXTENSIONS.some(p => ext.includes(p)); + + const mediaType = isVideo ? "video" : "photo"; + const thumbnailFileName = `${path.parse(title).name}_${Date.now()}.png`; const thumbnailPath = path.join(process.cwd(), "public", "thumbnails", thumbnailFileName); const thumbnailUrl = `/thumbnails/${thumbnailFileName}`; @@ -39,12 +64,22 @@ const scanLibrary = async (library: { id: number; path: string }) => { continue; } - await generateThumbnail(file, thumbnailPath); + // Ensure thumbnails directory exists + const thumbnailsDir = path.join(process.cwd(), "public", "thumbnails"); + if (!fs.existsSync(thumbnailsDir)) { + fs.mkdirSync(thumbnailsDir, { recursive: true }); + } + + if (isVideo) { + await generateVideoThumbnail(file, thumbnailPath); + } else if (isPhoto) { + await generatePhotoThumbnail(file, thumbnailPath); + } const media = { library_id: library.id, path: file, - type: "video", + type: mediaType, title: title, size: stats.size, thumbnail: thumbnailUrl,