From 87ad7e3537abe4b53b42047e6779d9f491580fc4 Mon Sep 17 00:00:00 2001 From: Dylan De Faoite <98231127+ThisBirchWood@users.noreply.github.com> Date: Thu, 17 Jul 2025 23:21:01 +0200 Subject: [PATCH] ADD thumbnail to database (#12) * ADD thumbnail to database * ADD thumbnail generation and retrieval functionality * ADD thumbnail availability check in VideoCard component * ADD ClipDTO to reduce exposed internals * REFactor move APIResponse and VideoMetadata to dto package * REMOVE unused props from VideoCard * ADD isThumbnailAvailable function --- frontend/src/components/video/VideoCard.tsx | 27 +++++++++------- frontend/src/pages/MyClips.tsx | 3 -- frontend/src/utils/endpoints.ts | 12 ++++++- frontend/src/utils/types.ts | 6 +--- pom.xml | 5 +++ .../vodsystem/controllers/AuthController.java | 2 +- .../vodsystem/controllers/ClipController.java | 28 ++++++++++++++--- .../controllers/DownloadController.java | 14 +++++++++ .../vodsystem/controllers/EditController.java | 5 ++- .../controllers/GlobalExceptionHandler.java | 2 +- .../controllers/MetadataController.java | 4 +-- .../controllers/UploadController.java | 2 +- .../{entities => dto}/APIResponse.java | 2 +- .../java/com/ddf/vodsystem/dto/ClipDTO.java | 15 +++++++++ .../{entities => dto}/VideoMetadata.java | 2 +- .../java/com/ddf/vodsystem/entities/Clip.java | 3 ++ .../java/com/ddf/vodsystem/entities/Job.java | 1 + .../ddf/vodsystem/services/ClipService.java | 20 ++++++++++-- .../vodsystem/services/DirectoryService.java | 27 +++++++++++++++- .../vodsystem/services/DownloadService.java | 15 +++++++++ .../ddf/vodsystem/services/EditService.java | 1 + .../ddf/vodsystem/services/FfmpegService.java | 31 ++++++++++++++++++- .../vodsystem/services/MetadataService.java | 2 +- .../ddf/vodsystem/services/UploadService.java | 2 +- src/main/resources/application.properties | 2 +- src/main/resources/db/schema.sql | 1 + 26 files changed, 190 insertions(+), 44 deletions(-) rename src/main/java/com/ddf/vodsystem/{entities => dto}/APIResponse.java (89%) create mode 100644 src/main/java/com/ddf/vodsystem/dto/ClipDTO.java rename src/main/java/com/ddf/vodsystem/{entities => dto}/VideoMetadata.java (88%) diff --git a/frontend/src/components/video/VideoCard.tsx b/frontend/src/components/video/VideoCard.tsx index 25c2767..745a77f 100644 --- a/frontend/src/components/video/VideoCard.tsx +++ b/frontend/src/components/video/VideoCard.tsx @@ -1,14 +1,13 @@ import clsx from "clsx"; import { formatTime, stringToDate, dateToTimeAgo } from "../../utils/utils.ts"; import { Link } from "react-router-dom"; -import { useState } from "react"; +import {useEffect, useState} from "react"; +import { isThumbnailAvailable } from "../../utils/endpoints.ts"; type VideoCardProps = { id: number, title: string, duration: number, - thumbnailPath: string | null, - videoPath: string, createdAt: string, className?: string } @@ -19,31 +18,35 @@ const VideoCard = ({ id, title, duration, - thumbnailPath, createdAt, className }: VideoCardProps) => { - const initialSrc = thumbnailPath && thumbnailPath.trim() !== "" ? thumbnailPath : fallbackThumbnail; - const [imgSrc, setImgSrc] = useState(initialSrc); const [timeAgo, setTimeAgo] = useState(dateToTimeAgo(stringToDate(createdAt))); + const [thumbnailAvailable, setThumbnailAvailable] = useState(true); setTimeout(() => { setTimeAgo(dateToTimeAgo(stringToDate(createdAt))) }, 1000); + useEffect(() => { + isThumbnailAvailable(id) + .then((available) => { + setThumbnailAvailable(available); + }) + .catch(() => { + setThumbnailAvailable(false); + }); + }); + + return (
Video Thumbnail { - if (imgSrc !== fallbackThumbnail) { - setImgSrc(fallbackThumbnail); - } - }} />

diff --git a/frontend/src/utils/endpoints.ts b/frontend/src/utils/endpoints.ts index c777edb..cb4924e 100644 --- a/frontend/src/utils/endpoints.ts +++ b/frontend/src/utils/endpoints.ts @@ -176,6 +176,15 @@ const getClipById = async (id: string): Promise => { } }; +const isThumbnailAvailable = async (id: number): Promise => { + const response = await fetch(`/api/v1/download/thumbnail/${id}`); + if (!response.ok) { + return false; + } + + return true; +} + export { uploadFile, editFile, @@ -184,5 +193,6 @@ export { getMetadata, getUser, getClips, - getClipById + getClipById, + isThumbnailAvailable }; \ No newline at end of file diff --git a/frontend/src/utils/types.ts b/frontend/src/utils/types.ts index 4036a90..54f2875 100644 --- a/frontend/src/utils/types.ts +++ b/frontend/src/utils/types.ts @@ -23,14 +23,10 @@ type User = { type Clip = { id: number, + userId: number, title: string, description: string, duration: number, - thumbnailPath: string, - videoPath: string, - fps: number, - width: number, - height: number, createdAt: string, } diff --git a/pom.xml b/pom.xml index d722517..33fdb83 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,11 @@ org.springframework.boot spring-boot-starter-security + + org.mapstruct + mapstruct + 1.5.5.Final + diff --git a/src/main/java/com/ddf/vodsystem/controllers/AuthController.java b/src/main/java/com/ddf/vodsystem/controllers/AuthController.java index 1197a6e..3f65892 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/AuthController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/AuthController.java @@ -1,6 +1,6 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.APIResponse; import com.ddf.vodsystem.exceptions.NotAuthenticated; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/ddf/vodsystem/controllers/ClipController.java b/src/main/java/com/ddf/vodsystem/controllers/ClipController.java index a20cceb..f484bef 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/ClipController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/ClipController.java @@ -1,6 +1,7 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.ClipDTO; +import com.ddf.vodsystem.dto.APIResponse; import com.ddf.vodsystem.entities.Clip; import com.ddf.vodsystem.exceptions.NotAuthenticated; import com.ddf.vodsystem.services.ClipService; @@ -24,19 +25,23 @@ public class ClipController { } @GetMapping("/") - public ResponseEntity>> getClips(@AuthenticationPrincipal OAuth2User principal) { + public ResponseEntity>> getClips(@AuthenticationPrincipal OAuth2User principal) { if (principal == null) { throw new NotAuthenticated("User is not authenticated"); } List clips = clipService.getClipsByUser(); + List clipDTOs = clips.stream() + .map(this::convertToDTO) + .toList(); + return ResponseEntity.ok( - new APIResponse<>("success", "Clips retrieved successfully", clips) + new APIResponse<>("success", "Clips retrieved successfully", clipDTOs) ); } @GetMapping("/{id}") - public ResponseEntity> getClipById(@AuthenticationPrincipal OAuth2User principal, @PathVariable Long id) { + public ResponseEntity> getClipById(@AuthenticationPrincipal OAuth2User principal, @PathVariable Long id) { if (principal == null) { throw new NotAuthenticated("User is not authenticated"); } @@ -46,8 +51,21 @@ public class ClipController { return ResponseEntity.notFound().build(); } + ClipDTO clipDTO = convertToDTO(clip); + return ResponseEntity.ok( - new APIResponse<>("success", "Clip retrieved successfully", clip) + new APIResponse<>("success", "Clip retrieved successfully", clipDTO) ); } + + private ClipDTO convertToDTO(Clip clip) { + ClipDTO dto = new ClipDTO(); + dto.setId(clip.getId()); + dto.setUserId(clip.getUser().getId()); + dto.setTitle(clip.getTitle()); + dto.setDescription(clip.getDescription()); + dto.setDuration(clip.getDuration()); + dto.setCreatedAt(clip.getCreatedAt()); + return dto; + } } diff --git a/src/main/java/com/ddf/vodsystem/controllers/DownloadController.java b/src/main/java/com/ddf/vodsystem/controllers/DownloadController.java index 26dce88..6d99c7e 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/DownloadController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/DownloadController.java @@ -65,4 +65,18 @@ public class DownloadController { .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM)) .body(resource); } + + @GetMapping("/thumbnail/{id}") + public ResponseEntity downloadThumbnail(@AuthenticationPrincipal OAuth2User principal, @PathVariable Long id) { + Resource resource = downloadService.downloadThumbnail(id); + + if (resource == null || !resource.exists()) { + return ResponseEntity.notFound().build(); + } + + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + resource.getFilename() + "\"") + .contentType(MediaTypeFactory.getMediaType(resource).orElse(MediaType.APPLICATION_OCTET_STREAM)) + .body(resource); + } } diff --git a/src/main/java/com/ddf/vodsystem/controllers/EditController.java b/src/main/java/com/ddf/vodsystem/controllers/EditController.java index d341902..9376aa9 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/EditController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/EditController.java @@ -1,12 +1,11 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.VideoMetadata; +import com.ddf.vodsystem.dto.VideoMetadata; import com.ddf.vodsystem.services.EditService; import lombok.AllArgsConstructor; import lombok.Data; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.APIResponse; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/ddf/vodsystem/controllers/GlobalExceptionHandler.java b/src/main/java/com/ddf/vodsystem/controllers/GlobalExceptionHandler.java index 12234f7..106abf8 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/GlobalExceptionHandler.java +++ b/src/main/java/com/ddf/vodsystem/controllers/GlobalExceptionHandler.java @@ -1,6 +1,6 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.APIResponse; import com.ddf.vodsystem.exceptions.FFMPEGException; import com.ddf.vodsystem.exceptions.JobNotFinished; import com.ddf.vodsystem.exceptions.JobNotFound; diff --git a/src/main/java/com/ddf/vodsystem/controllers/MetadataController.java b/src/main/java/com/ddf/vodsystem/controllers/MetadataController.java index a39b257..cc80ea4 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/MetadataController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/MetadataController.java @@ -1,7 +1,7 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.VideoMetadata; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.VideoMetadata; +import com.ddf.vodsystem.dto.APIResponse; import com.ddf.vodsystem.services.JobService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/main/java/com/ddf/vodsystem/controllers/UploadController.java b/src/main/java/com/ddf/vodsystem/controllers/UploadController.java index 501a0ea..01f2698 100644 --- a/src/main/java/com/ddf/vodsystem/controllers/UploadController.java +++ b/src/main/java/com/ddf/vodsystem/controllers/UploadController.java @@ -1,6 +1,6 @@ package com.ddf.vodsystem.controllers; -import com.ddf.vodsystem.entities.APIResponse; +import com.ddf.vodsystem.dto.APIResponse; import com.ddf.vodsystem.services.UploadService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/ddf/vodsystem/entities/APIResponse.java b/src/main/java/com/ddf/vodsystem/dto/APIResponse.java similarity index 89% rename from src/main/java/com/ddf/vodsystem/entities/APIResponse.java rename to src/main/java/com/ddf/vodsystem/dto/APIResponse.java index 2183ad0..436fb4a 100644 --- a/src/main/java/com/ddf/vodsystem/entities/APIResponse.java +++ b/src/main/java/com/ddf/vodsystem/dto/APIResponse.java @@ -1,4 +1,4 @@ -package com.ddf.vodsystem.entities; +package com.ddf.vodsystem.dto; import lombok.Data; diff --git a/src/main/java/com/ddf/vodsystem/dto/ClipDTO.java b/src/main/java/com/ddf/vodsystem/dto/ClipDTO.java new file mode 100644 index 0000000..bd299f1 --- /dev/null +++ b/src/main/java/com/ddf/vodsystem/dto/ClipDTO.java @@ -0,0 +1,15 @@ +package com.ddf.vodsystem.dto; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class ClipDTO { + private Long id; + private Long userId; + private String title; + private String description; + private Float duration; + private LocalDateTime createdAt; +} diff --git a/src/main/java/com/ddf/vodsystem/entities/VideoMetadata.java b/src/main/java/com/ddf/vodsystem/dto/VideoMetadata.java similarity index 88% rename from src/main/java/com/ddf/vodsystem/entities/VideoMetadata.java rename to src/main/java/com/ddf/vodsystem/dto/VideoMetadata.java index c3e5621..6eb6a9c 100644 --- a/src/main/java/com/ddf/vodsystem/entities/VideoMetadata.java +++ b/src/main/java/com/ddf/vodsystem/dto/VideoMetadata.java @@ -1,4 +1,4 @@ -package com.ddf.vodsystem.entities; +package com.ddf.vodsystem.dto; import lombok.Data; diff --git a/src/main/java/com/ddf/vodsystem/entities/Clip.java b/src/main/java/com/ddf/vodsystem/entities/Clip.java index 0ae1c77..924b0b5 100644 --- a/src/main/java/com/ddf/vodsystem/entities/Clip.java +++ b/src/main/java/com/ddf/vodsystem/entities/Clip.java @@ -47,4 +47,7 @@ public class Clip { @Column(name = "video_path", nullable = false, length = 255) private String videoPath; + + @Column(name = "thumbnail_path", nullable = false, length = 255) + private String thumbnailPath; } diff --git a/src/main/java/com/ddf/vodsystem/entities/Job.java b/src/main/java/com/ddf/vodsystem/entities/Job.java index 5e59c31..9c828b6 100644 --- a/src/main/java/com/ddf/vodsystem/entities/Job.java +++ b/src/main/java/com/ddf/vodsystem/entities/Job.java @@ -3,6 +3,7 @@ package com.ddf.vodsystem.entities; import java.io.File; import java.util.concurrent.atomic.AtomicReference; +import com.ddf.vodsystem.dto.VideoMetadata; import org.springframework.security.core.context.SecurityContext; import lombok.Data; diff --git a/src/main/java/com/ddf/vodsystem/services/ClipService.java b/src/main/java/com/ddf/vodsystem/services/ClipService.java index 8bae4dc..a32a6cb 100644 --- a/src/main/java/com/ddf/vodsystem/services/ClipService.java +++ b/src/main/java/com/ddf/vodsystem/services/ClipService.java @@ -1,5 +1,6 @@ package com.ddf.vodsystem.services; +import com.ddf.vodsystem.dto.VideoMetadata; import com.ddf.vodsystem.entities.*; import java.io.File; @@ -83,8 +84,20 @@ public class ClipService { private void persistClip(VideoMetadata videoMetadata, User user, Job job) { // Move clip from temp to output directory String fileExtension = directoryService.getFileExtension(job.getOutputFile().getAbsolutePath()); - File outputFile = directoryService.getOutputFile(job.getUuid(), fileExtension); - directoryService.copyFile(job.getOutputFile(), outputFile); + + File clipOutputDir = directoryService.getUserClipsDir(user.getId()); + File clipOutputFile = new File(clipOutputDir, job.getUuid() + "." + fileExtension); + directoryService.copyFile(job.getOutputFile(), clipOutputFile); + + File thumbnailOutputDir = directoryService.getUserThumbnailsDir(user.getId()); + File thumbnailOutputFile = new File(thumbnailOutputDir, job.getUuid() + ".png"); + + try { + ffmpegService.generateThumbnail(clipOutputFile, thumbnailOutputFile, 0.0f); + } catch (IOException | InterruptedException e) { + logger.error("Error generating thumbnail for clip: {}", e.getMessage()); + Thread.currentThread().interrupt(); + } // Save clip to database Clip clip = new Clip(); @@ -97,7 +110,8 @@ public class ClipService { clip.setFps(videoMetadata.getFps()); clip.setDuration(videoMetadata.getEndPoint() - videoMetadata.getStartPoint()); clip.setFileSize(videoMetadata.getFileSize()); - clip.setVideoPath(outputFile.getPath()); + clip.setVideoPath(clipOutputFile.getPath()); + clip.setThumbnailPath(thumbnailOutputFile.getPath()); clipRepository.save(clip); } diff --git a/src/main/java/com/ddf/vodsystem/services/DirectoryService.java b/src/main/java/com/ddf/vodsystem/services/DirectoryService.java index 3a9841f..eb74e90 100644 --- a/src/main/java/com/ddf/vodsystem/services/DirectoryService.java +++ b/src/main/java/com/ddf/vodsystem/services/DirectoryService.java @@ -61,6 +61,32 @@ public class DirectoryService { return new File(dir); } + public File getUserClipsDir(Long userId) { + if (userId == null) { + throw new IllegalArgumentException("User ID cannot be null"); + } + + String dir = outputDir + File.separator + userId + File.separator + "clips"; + return new File(dir); + } + + public File getUserThumbnailsDir(Long userId) { + if (userId == null) { + throw new IllegalArgumentException("User ID cannot be null"); + } + + String dir = outputDir + File.separator + userId + File.separator + "thumbnails"; + File thumbnailDir = new File(dir); + + try { + createDirectory(thumbnailDir.getAbsolutePath()); + } catch (IOException e) { + logger.error("Error creating thumbnails directory: {}", e.getMessage()); + } + + return thumbnailDir; + } + public void saveAtDir(File file, MultipartFile multipartFile) { try { createDirectory(file.getAbsolutePath()); @@ -118,7 +144,6 @@ public class DirectoryService { Files.delete(f.toPath()); } } - } @PostConstruct diff --git a/src/main/java/com/ddf/vodsystem/services/DownloadService.java b/src/main/java/com/ddf/vodsystem/services/DownloadService.java index 504cc44..24345b7 100644 --- a/src/main/java/com/ddf/vodsystem/services/DownloadService.java +++ b/src/main/java/com/ddf/vodsystem/services/DownloadService.java @@ -65,4 +65,19 @@ public class DownloadService { Clip clip = clipRepository.findById(id).orElseThrow(() -> new JobNotFound("Clip not found with id: " + id)); return downloadClip(clip); } + + public Resource downloadThumbnail(Clip clip) { + String path = clip.getThumbnailPath(); + File file = new File(path); + if (!file.exists()) { + throw new JobNotFound("Thumbnail file not found"); + } + + return new FileSystemResource(file); + } + + public Resource downloadThumbnail(Long id) { + Clip clip = clipRepository.findById(id).orElseThrow(() -> new JobNotFound("Clip not found with id: " + id)); + return downloadThumbnail(clip); + } } diff --git a/src/main/java/com/ddf/vodsystem/services/EditService.java b/src/main/java/com/ddf/vodsystem/services/EditService.java index e69e2f9..b102cc8 100644 --- a/src/main/java/com/ddf/vodsystem/services/EditService.java +++ b/src/main/java/com/ddf/vodsystem/services/EditService.java @@ -1,5 +1,6 @@ package com.ddf.vodsystem.services; +import com.ddf.vodsystem.dto.VideoMetadata; import com.ddf.vodsystem.entities.*; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/ddf/vodsystem/services/FfmpegService.java b/src/main/java/com/ddf/vodsystem/services/FfmpegService.java index 2e36ed8..24379ce 100644 --- a/src/main/java/com/ddf/vodsystem/services/FfmpegService.java +++ b/src/main/java/com/ddf/vodsystem/services/FfmpegService.java @@ -1,6 +1,6 @@ package com.ddf.vodsystem.services; -import com.ddf.vodsystem.entities.VideoMetadata; +import com.ddf.vodsystem.dto.VideoMetadata; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; @@ -48,6 +48,35 @@ public class FfmpegService { runWithProgress(inputFile, outputFile, videoMetadata, new AtomicReference<>(0f)); } + public void generateThumbnail(File inputFile, File outputFile, Float time) throws IOException, InterruptedException { + logger.info("Generating thumbnail at {} seconds", time); + + List command = new ArrayList<>(); + command.add("ffmpeg"); + command.add("-ss"); + command.add(time.toString()); + command.add("-i"); + command.add(inputFile.getAbsolutePath()); + command.add("-frames:v"); + command.add("1"); + command.add(outputFile.getAbsolutePath()); + + String strCommand = String.join(" ", command); + logger.info("FFMPEG thumbnail command: {}", strCommand); + + ProcessBuilder processBuilder = new ProcessBuilder(command); + processBuilder.redirectErrorStream(true); + + Process process = processBuilder.start(); + + if (process.waitFor() != 0) { + logger.error("FFMPEG process failed to generate thumbnail"); + throw new IOException("FFMPEG process failed to generate thumbnail"); + } + + logger.info("Thumbnail generated successfully at {}", outputFile.getAbsolutePath()); + } + private void updateJobProgress(Process process, AtomicReference progress, Float length) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); diff --git a/src/main/java/com/ddf/vodsystem/services/MetadataService.java b/src/main/java/com/ddf/vodsystem/services/MetadataService.java index 080dd16..a307e90 100644 --- a/src/main/java/com/ddf/vodsystem/services/MetadataService.java +++ b/src/main/java/com/ddf/vodsystem/services/MetadataService.java @@ -1,6 +1,6 @@ package com.ddf.vodsystem.services; -import com.ddf.vodsystem.entities.VideoMetadata; +import com.ddf.vodsystem.dto.VideoMetadata; import com.ddf.vodsystem.exceptions.FFMPEGException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; diff --git a/src/main/java/com/ddf/vodsystem/services/UploadService.java b/src/main/java/com/ddf/vodsystem/services/UploadService.java index 9afbc75..78fdf46 100644 --- a/src/main/java/com/ddf/vodsystem/services/UploadService.java +++ b/src/main/java/com/ddf/vodsystem/services/UploadService.java @@ -1,7 +1,7 @@ package com.ddf.vodsystem.services; import com.ddf.vodsystem.entities.Job; -import com.ddf.vodsystem.entities.VideoMetadata; +import com.ddf.vodsystem.dto.VideoMetadata; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 51bb1cf..e2605ea 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -6,7 +6,7 @@ spring.servlet.multipart.max-file-size=2GB spring.servlet.multipart.max-request-size=2GB storage.temp.inputs=videos/inputs/ storage.temp.outputs=videos/outputs/ -storage.outputs=videos/clips/ +storage.outputs=outputs/ ## Server Configuration server.servlet.session.timeout=30m diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql index 60dc57a..d61b245 100644 --- a/src/main/resources/db/schema.sql +++ b/src/main/resources/db/schema.sql @@ -23,5 +23,6 @@ CREATE TABLE IF NOT EXISTS clips ( duration FLOAT NOT NULL, file_size FLOAT NOT NULL, video_path VARCHAR(255) NOT NULL, + thumbnail_path VARCHAR(255) NOT NULL, FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); \ No newline at end of file