Save metadata to library, Add thumbnail caching
This commit is contained in:
parent
f3e321d8c7
commit
04b17abdee
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@
|
||||
/target/
|
||||
/dependency-reduced-pom.xml
|
||||
/library
|
||||
/cache
|
||||
/config.json
|
||||
|
@ -1,5 +1,6 @@
|
||||
package me.mrletsplay.videobase;
|
||||
|
||||
import me.mrletsplay.mrcore.json.converter.JSONConstructor;
|
||||
import me.mrletsplay.mrcore.json.converter.JSONConvertible;
|
||||
import me.mrletsplay.mrcore.json.converter.JSONValue;
|
||||
|
||||
@ -8,11 +9,24 @@ public class Config implements JSONConvertible {
|
||||
@JSONValue
|
||||
private String libraryPath;
|
||||
|
||||
@JSONValue
|
||||
private String cachePath;
|
||||
|
||||
@JSONConstructor
|
||||
private Config() {}
|
||||
|
||||
public String getLibraryPath() {
|
||||
return libraryPath;
|
||||
}
|
||||
|
||||
public String getCachePath() {
|
||||
return cachePath;
|
||||
}
|
||||
|
||||
public static Config createDefault() {
|
||||
Config config = new Config();
|
||||
config.libraryPath = "library";
|
||||
config.cachePath = "cache";
|
||||
return config;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
package me.mrletsplay.videobase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
@ -7,25 +10,47 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.slf4j.helpers.NOPLogger;
|
||||
|
||||
import me.mrletsplay.mrcore.json.JSONObject;
|
||||
import me.mrletsplay.mrcore.json.converter.JSONConverter;
|
||||
import me.mrletsplay.mrcore.json.converter.SerializationOption;
|
||||
import me.mrletsplay.simplehttpserver.http.cors.CorsConfiguration;
|
||||
import me.mrletsplay.simplehttpserver.http.server.HttpServer;
|
||||
import me.mrletsplay.videobase.library.Library;
|
||||
import me.mrletsplay.videobase.rest.LibraryAPI;
|
||||
import me.mrletsplay.videobase.util.Hash;
|
||||
|
||||
public class VideoBase {
|
||||
|
||||
public static final Logger LOGGER = LoggerFactory.getLogger(VideoBase.class.getName());
|
||||
|
||||
private static ScheduledExecutorService executor;
|
||||
private static Config config;
|
||||
private static Library library;
|
||||
|
||||
public static void main(String[] args) {
|
||||
executor = Executors.newScheduledThreadPool(0);
|
||||
|
||||
// Verify hash is working
|
||||
Hash.hash("test");
|
||||
Path configPath = Path.of("config.json");
|
||||
if(args.length >= 1) {
|
||||
configPath = Path.of(args[0]);
|
||||
}
|
||||
|
||||
configPath = configPath.toAbsolutePath();
|
||||
|
||||
try {
|
||||
if(!Files.exists(configPath)) {
|
||||
Files.createDirectories(configPath.getParent());
|
||||
Files.writeString(configPath, Config.createDefault().toJSON(SerializationOption.DONT_INCLUDE_CLASS).toFancyString(), StandardCharsets.UTF_8);
|
||||
LOGGER.info("Default configuration created, please edit it and restart");
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
config = JSONConverter.decodeObject(new JSONObject(Files.readString(configPath, StandardCharsets.UTF_8)), Config.class);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to load config", e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
loadLibrary();
|
||||
executor.scheduleWithFixedDelay(VideoBase::loadLibrary, 10, 10, TimeUnit.MINUTES);
|
||||
@ -35,7 +60,7 @@ public class VideoBase {
|
||||
.port(6969)
|
||||
.poolSize(20)
|
||||
.ioWorkers(3)
|
||||
// .logger(NOPLogger.NOP_LOGGER)
|
||||
.logger(NOPLogger.NOP_LOGGER)
|
||||
.defaultCorsConfiguration(CorsConfiguration.createAllowAll())
|
||||
.create());
|
||||
|
||||
@ -44,12 +69,16 @@ public class VideoBase {
|
||||
server.start();
|
||||
}
|
||||
|
||||
public static Config getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public static Library getLibrary() {
|
||||
return library;
|
||||
}
|
||||
|
||||
private static void loadLibrary() {
|
||||
library = Library.load(Path.of("/mnt/wd4tb/Files/ytdl/Aliensrock/"));
|
||||
library = Library.load(Path.of(config.getLibraryPath()));
|
||||
|
||||
System.out.println(library.getVideos());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package me.mrletsplay.videobase.library;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -13,6 +14,7 @@ import java.util.stream.Collectors;
|
||||
import me.mrletsplay.mrcore.json.JSONObject;
|
||||
import me.mrletsplay.mrcore.json.JSONParseException;
|
||||
import me.mrletsplay.mrcore.json.converter.JSONConverter;
|
||||
import me.mrletsplay.mrcore.json.converter.SerializationOption;
|
||||
import me.mrletsplay.videobase.VideoBase;
|
||||
import me.mrletsplay.videobase.util.Hash;
|
||||
|
||||
@ -75,10 +77,18 @@ public class Library {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public void updateMetadata(Video video, VideoMetadata metadata) {
|
||||
public boolean updateMetadata(Video video, VideoMetadata metadata) {
|
||||
VideoMetadata oldMetadata = video.getMetadata();
|
||||
video.setMetadata(VideoMetadata.inherit(oldMetadata, metadata));
|
||||
// TODO: save metadata
|
||||
VideoMetadata newMetadata = VideoMetadata.inherit(oldMetadata, metadata);
|
||||
|
||||
Path videoPath = video.getPath().toAbsolutePath();
|
||||
try {
|
||||
Files.writeString(videoPath.getParent().resolve(videoPath.getFileName().toString() + VIDEO_METADATA_SUFFIX), newMetadata.toJSON(SerializationOption.DONT_INCLUDE_CLASS).toFancyString(), StandardCharsets.UTF_8);
|
||||
video.setMetadata(newMetadata);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean updateMetadata(String videoId, VideoMetadata metadata) {
|
||||
|
@ -138,7 +138,7 @@ public class LibraryAPI implements EndpointCollection {
|
||||
return;
|
||||
}
|
||||
|
||||
BufferedImage thumbnail = ThumbnailCreator.createThumbnail(video.getPath());
|
||||
BufferedImage thumbnail = ThumbnailCreator.createThumbnail(video);
|
||||
if(thumbnail == null) {
|
||||
ctx.respond(HttpStatusCodes.NOT_FOUND_404, new TextResponse("No thumbnail found"));
|
||||
return;
|
||||
|
@ -4,18 +4,36 @@ import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import me.mrletsplay.videobase.VideoBase;
|
||||
import me.mrletsplay.videobase.library.Video;
|
||||
|
||||
public class ThumbnailCreator {
|
||||
|
||||
public static BufferedImage createThumbnail(Path videoPath) {
|
||||
public static BufferedImage createThumbnail(Video video) {
|
||||
Path cacheDir = Path.of(VideoBase.getConfig().getCachePath()).resolve("thumbnails").toAbsolutePath();
|
||||
Path thumbnailFile = cacheDir.resolve(video.getId() + ".png");
|
||||
try {
|
||||
Files.createDirectories(cacheDir);
|
||||
if(Files.exists(thumbnailFile)) {
|
||||
try(InputStream in = Files.newInputStream(thumbnailFile)) {
|
||||
return ImageIO.read(in);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
VideoBase.LOGGER.warn("Failed to load thumbnail", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
ProcessBuilder ffmpegBuilder = new ProcessBuilder("ffmpeg",
|
||||
"-i", videoPath.toAbsolutePath().toString(),
|
||||
"-i", video.getPath().toAbsolutePath().toString(),
|
||||
"-vf", "thumbnail",
|
||||
"-vf", "scale=960:540:force_original_aspect_ratio=decrease,pad=960:540:-1:-1:color=black",
|
||||
"-frames:v", "1",
|
||||
@ -26,11 +44,9 @@ public class ThumbnailCreator {
|
||||
|
||||
try {
|
||||
Process ffmpeg = ffmpegBuilder.start();
|
||||
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int len;
|
||||
while(System.currentTimeMillis() - start < 1000
|
||||
@ -51,9 +67,14 @@ public class ThumbnailCreator {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ImageIO.read(new ByteArrayInputStream(bOut.toByteArray()));
|
||||
BufferedImage thumbnail = ImageIO.read(new ByteArrayInputStream(bOut.toByteArray()));
|
||||
try(OutputStream out = Files.newOutputStream(thumbnailFile)) {
|
||||
ImageIO.write(thumbnail, "PNG", out);
|
||||
}
|
||||
|
||||
return thumbnail;
|
||||
} catch (InterruptedException | IOException e) {
|
||||
e.printStackTrace();
|
||||
VideoBase.LOGGER.warn("Failed to create thumbnail", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user