1
0
mirror of https://github.com/openeggbert/youtubedl-frontend.git synced 2025-03-14 21:23:27 +01:00

Added 2 new command line options

This commit is contained in:
Robert Vokac 2024-07-17 17:38:23 +02:00
parent 66ed2445b2
commit 679af67719
No known key found for this signature in database
GPG Key ID: C459E1E4B4A986BB
5 changed files with 215 additions and 137 deletions

View File

@ -1,2 +1,4 @@
# youtubedl-frontend
ffmpeg -i "$video"mkv -preset slow -crf 18 "$video"webm

View File

@ -119,7 +119,12 @@
</dependency>
<dependency>
<groupId>org.nanoboot.powerframework</groupId>
<artifactId>power-random</artifactId>
<artifactId>power-utils</artifactId>
<version>${power.version}</version>
</dependency>
<dependency>
<groupId>org.nanoboot.powerframework</groupId>
<artifactId>power-io</artifactId>
<version>${power.version}</version>
</dependency>

View File

@ -26,4 +26,6 @@ module youtubedlfrontend {
requires humble.video.all;
requires com.fasterxml.jackson.databind;
requires java.desktop;
requires powerframework.io;
requires powerframework.utils;
}

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
@ -42,6 +43,8 @@ public class Main {
private static int internalStaticVariableVideoNumberPerRow = 0;
public static boolean argAlwaysGenerateMetadata = true;
public static boolean argAlwaysGenerateHtmlFiles = true;
public static boolean thumbnailAsBase64 = false;
public static boolean thumbnailLinksToYoutube = false;
public static int argVideosPerRow = 4;
public static int THUMBNAIL_WIDTH = 250;
public static String argVideo;
@ -50,12 +53,13 @@ public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
System.out.println("youtubedlfrontend - HTML generator\n");
//args = "/rv/databig/youtube --_video UDpsz1yIwiw --always-generate-metadata 1 --always-generate-html-files 1 --videos-per-row 4".split(" ");
if (args.length < 1) {
//System.err.println("At least one argument is expected, but the count of arguments is: " + args.length + ".");
args = "/rv/blupi/archivebox --_video UDpsz1yIwiw --always-generate-metadata 0 --always-generate-html-files 1 --videos-per-row 4".split(" ");
String argsS = "/rv/blupi/archivebox --_video UDpsz1yIwiw --always-generate-metadata 0 "
+ " --always-generate-html-files 1 --videos-per-row 4 --thumbnail-links-to-youtube 1"
+ " --thumbnail-as-base64 1";
args = argsS.split(" ");
//System.exit(1);
}
argVideo = "";
@ -98,22 +102,12 @@ public class Main {
throw new YoutubedlFrontendException("Fatal error: missing value for --always-generate-metadata");
}
String s = args[i];
switch (s) {
case "1":
argAlwaysGenerateMetadata = true;
break;
case "true":
argAlwaysGenerateMetadata = true;
break;
case "0":
argAlwaysGenerateMetadata = false;
break;
case "false":
argAlwaysGenerateMetadata = false;
break;
default:
throw new YoutubedlFrontendException("Invalid value for --always-generate-metadata");
};
try {
argAlwaysGenerateMetadata = Utils.convertStringToBoolean(s);
} catch (Exception e) {
throw new YoutubedlFrontendException("Invalid value for --always-generate-metadata");
}
}
if (arg.equals("--always-generate-html-files")) {
@ -122,24 +116,41 @@ public class Main {
throw new YoutubedlFrontendException("Fatal error: missing value for --always-generate-html-files");
}
String s = args[i];
switch (s) {
case "1":
argAlwaysGenerateHtmlFiles = true;
break;
case "true":
argAlwaysGenerateHtmlFiles = true;
break;
case "0":
argAlwaysGenerateHtmlFiles = false;
break;
case "false":
argAlwaysGenerateHtmlFiles = false;
break;
default:
try {argAlwaysGenerateHtmlFiles = Utils.convertStringToBoolean(s);} catch(Exception e) {
throw new YoutubedlFrontendException("Invalid value for --always-generate-html-files");
};
}
}
if (arg.equals("--thumbnail-as-base64")) {
i++;
if (i >= args.length) {
throw new YoutubedlFrontendException("Fatal error: missing value for --thumbnail-as-base64");
}
String s = args[i];
try {thumbnailAsBase64 = Utils.convertStringToBoolean(s);} catch(Exception e) {
throw new YoutubedlFrontendException("Invalid value for --thumbnail-as-base64");
}
}
if (arg.equals("--thumbnail-links-to-youtube")) {
i++;
if (i >= args.length) {
throw new YoutubedlFrontendException("Fatal error: missing value for --thumbnail-links-to-youtube");
}
String s = args[i];
try {
thumbnailLinksToYoutube = Utils.convertStringToBoolean(s);
} catch (Exception e) {
throw new YoutubedlFrontendException("Invalid value for --thumbnail-links-to-youtube");
}
}
}
}
String workingDirectory = args.length > 0 && !args[0].startsWith(TWO_DASHES) ? args[0] : new File(".").getAbsolutePath();
@ -168,13 +179,13 @@ public class Main {
i++;
System.out.println("\n\nFound video #" + i);
for(File f:new File(archiveBoxArchiveDirectory + "/" +youtubeVideo.getSnapshot() + "/media/" + youtubeVideo.getVideoFileName()).getParentFile().listFiles()) {
if(f.getName().endsWith(".webm")) {
for (File f : new File(archiveBoxArchiveDirectory + "/" + youtubeVideo.getSnapshot() + "/media/" + youtubeVideo.getVideoFileName()).getParentFile().listFiles()) {
if (f.getName().endsWith(".webm")) {
//mkv file was manually converted to webm
youtubeVideo.setVideoFileName(f.getName());
break;
}
}
System.out.println("id = " + youtubeVideo.getId());
System.out.println("snapshot = " + youtubeVideo.getSnapshot());
@ -256,7 +267,7 @@ public class Main {
iii = 0;
internalStaticVariableVideoNumberPerRow = 0;
sb.append("<table>\n");
youtubeVideos.stream().filter(v -> c.equals(v.getChannelName())).forEach(z -> {
youtubeVideos.stream().filter(v -> c.equals(v.getChannelName())).forEach(youtubeVideo -> {
iii++;
if (internalStaticVariableVideoNumberPerRow == 0) {
sb.append("<tr>");
@ -264,41 +275,58 @@ public class Main {
internalStaticVariableVideoNumberPerRow++;
sb.append("<td><div class=\"box\"><table style=\"margin:5px;max-width:")
.append(THUMBNAIL_WIDTH)
.append("px;\">\n<tr><td><a href=\"videos/" + z.getId() + ".html\" target=\"_blank\"><img src=\"archive/");
sb.append(z.getSnapshot());
sb
.append("/media/mini-thumbnail.")
.append(z.getMiniThumbnailFormat())
.append("\" width=\"")
.append("px;\">\n<tr><td><a href=\"");
if (thumbnailLinksToYoutube) {
sb.append("https://www.youtube.com/watch?v=").append(youtubeVideo.getId());
} else {
sb.append("videos/" + youtubeVideo.getId() + ".html");
}
sb.append("\" target=\"_blank\"><img src=\"");
String thumbnailPath = new StringBuilder()
.append("archive/")
.append(youtubeVideo.getSnapshot())
.append("/media/mini-thumbnail.")
.append(youtubeVideo.getMiniThumbnailFormat()).toString();
if (thumbnailAsBase64) {
try {
byte[] bytes= Files.readAllBytes(new File(archiveBoxRootDirectory + "/" + thumbnailPath).toPath());
String bytesS = "data:image/jpg;base64, " + org.nanoboot.powerframework.io.bit.base64.Base64Coder.encode(bytes);
sb.append(bytesS);
} catch (IOException ex) {
throw new YoutubedlFrontendException(ex.getMessage());
}
} else {
sb.append(thumbnailPath);
}
sb.append("\" width=\"")
.append(THUMBNAIL_WIDTH)
.append("\"></a></td></tr>\n");
sb.append("<tr><td><b style=\"font-size:90%;\">").append(z.getTitle()).append("</b></td></tr>\n");
String uploadDate = z.getUploadDate();
sb.append("<tr><td><b style=\"font-size:90%;\">").append(youtubeVideo.getTitle()).append("</b></td></tr>\n");
String uploadDate = youtubeVideo.getUploadDate();
uploadDate = uploadDate.substring(0, 4) + "-" + uploadDate.substring(4, 6) + "-" + uploadDate.substring(6, 8);
sb.append("<tr><td style=\"font-size:80%;color:grey;\">").append(uploadDate).append(" •︎ ").append(z.getVideoDuration())
sb.append("<tr><td style=\"font-size:80%;color:grey;\">").append(uploadDate).append(" •︎ ").append(youtubeVideo.getVideoDuration())
.append(" •︎ ")
.append("#").append(iii)
.append("</td></tr>\n");
z.setNumber(iii);
youtubeVideo.setNumber(iii);
sb.append("</table></div></td>\n");
if (internalStaticVariableVideoNumberPerRow == argVideosPerRow) {
sb.append("<tr>");
internalStaticVariableVideoNumberPerRow = 0;
}
File videoHtmlFile = new File(videosDirectory, z.getId() + ".html");
if(!videoHtmlFile.exists() || argAlwaysGenerateHtmlFiles) {
File videoHtmlFile = new File(videosDirectory, youtubeVideo.getId() + ".html");
if (!videoHtmlFile.exists() || argAlwaysGenerateHtmlFiles) {
{
StringBuilder sb2 = new StringBuilder("""
{
StringBuilder videoHtml = new StringBuilder("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/x-icon" href="../favicon.ico" sizes="16x16">
<title>"""
+ z.getTitle()
+ """
+ youtubeVideo.getTitle()
+ """
</title>
<style>
body {padding:20px;}
@ -310,95 +338,121 @@ public class Main {
</head>
<body>
"""
);
String finalUrl = "https://www.youtube.com/watch?v=" + z.getId();
);
String finalUrl = "https://www.youtube.com/watch?v=" + youtubeVideo.getId();
sb2.append("<input type=\"text\" id=\"youtube_url\" name=\"youtube_url\" size=\"60\" width=\"60\" style=\"margint-bottom:20px;margin-right:10px;font-size:110%;padding:5px;\" value=\"" + finalUrl + "\"><br>\n<br>\n");
sb2.append("<a target=\"_blank\" href=\"").append(finalUrl).append("\">");
sb2.append(finalUrl).append("</a>").append("<br>\n");
String videoLocalUrl = "";
try {
videoLocalUrl = "file:///" + archiveBoxRootDirectory.getAbsolutePath() + "/archive/" + z.getSnapshot() + "/media/" + URLEncoder.encode(z.getVideoFileName(), StandardCharsets.UTF_8.toString()).replace("+", "%20");
} catch (UnsupportedEncodingException ex) {
throw new YoutubedlFrontendException(ex.getMessage());
}
if(!z.getVideoFileName().endsWith(".mkv")) {
//try {
sb2.append("<video src=\"");
sb2.append("../archive/" + z.getSnapshot() + "/media/"
+
// URLEncoder.encode(
z.getVideoFileName()
// , StandardCharsets.UTF_8.toString()
// )
// .replace("+", "%20")
);
sb2.append("""
" controls height=\"500px\">
videoHtml.append("<input type=\"text\" id=\"youtube_url\" name=\"youtube_url\" size=\"60\" width=\"60\" style=\"margint-bottom:20px;margin-right:10px;font-size:110%;padding:5px;\" value=\"" + finalUrl + "\"><br>\n<br>\n");
videoHtml.append("<a target=\"_blank\" href=\"").append(finalUrl).append("\">");
videoHtml.append(finalUrl).append("</a>").append("<br>\n");
String videoLocalUrl = "";
try {
videoLocalUrl = "file:///" + archiveBoxRootDirectory.getAbsolutePath() + "/archive/" + youtubeVideo.getSnapshot() + "/media/" + URLEncoder.encode(youtubeVideo.getVideoFileName(), StandardCharsets.UTF_8.toString()).replace("+", "%20");
} catch (UnsupportedEncodingException ex) {
throw new YoutubedlFrontendException(ex.getMessage());
}
if (!youtubeVideo.getVideoFileName().endsWith(".mkv")) {
//try {
videoHtml.append("<video src=\"");
videoHtml.append("../archive/").append(youtubeVideo.getSnapshot()).append("/media/").append(// URLEncoder.encode(
youtubeVideo.getVideoFileName());
videoHtml.append("""
" controls height=\"500px\">
Your browser does not support the video tag.
</video><br>
""");
// } catch (UnsupportedEncodingException ex) {
// throw new YoutubedlFrontendException(ex.getMessage());
// }
} else {
sb2.append("<a target=\"_blank\" href=\"").append(videoLocalUrl).append("\">");
}
else
{
videoHtml.append("<a target=\"_blank\" href=\"").append(videoLocalUrl).append("\">");
sb2.append("<img style=\"margin:10px;height:500px;\" src=\"../archive/")
.append(z.getSnapshot())
.append("/media/thumbnail.")
.append(z.getThumbnailFormat())
.append("\"></a><br>\n");
}
sb2.append("<span style=\"font-size:160%;font-weight:bold;\">").append(z.getTitle()).append("</span>");
sb2.append("<br>\n<br>\n");
sb2.append("#").append(z.getNumber()).append("&nbsp;&nbsp;&nbsp;");
if (z.getPreviousVideoId() != null) {
sb2.append("<a href=\"./").append(z.getPreviousVideoId()).append(".html\">");
}
sb2.append("Back");
if (z.getPreviousVideoId() != null) {
sb2.append("</a>");
}
sb2.append("&nbsp;&nbsp;&nbsp;");
if (z.getNextVideoId() != null) {
sb2.append("<a href=\"./").append(z.getNextVideoId()).append(".html\">");
}
sb2.append("Next");
if (z.getNextVideoId() != null) {
sb2.append("</a>");
}
sb2.append(" ");
sb2
.append("<br><br><a href=\"../archive/")
.append(z.getSnapshot())
.append("/media/")
.append(z.getVideoFileName())
.append("\">Download</a> ");
videoHtml.append("<img style=\"margin:10px;height:500px;\" src=\"../archive/")
.append(youtubeVideo.getSnapshot())
.append("/media/thumbnail.")
.append(youtubeVideo.getThumbnailFormat())
.append("\"></a><br>\n");
}
videoHtml.append("<span style=\"font-size:160%;font-weight:bold;\">").append(youtubeVideo.getTitle()).append("</span>");
videoHtml.append("<br>\n<br>\n");
videoHtml.append("#").append(youtubeVideo.getNumber()).append("&nbsp;&nbsp;&nbsp;");
if (youtubeVideo.getPreviousVideoId() != null) {
// videoHtml.append("<a href=\"./").append(youtubeVideo.getPreviousVideoId()).append(".html\">");
videoHtml.append("<button style=\"font-size:150%;\" onclick=\"window.location ='").append("./").append(youtubeVideo.getPreviousVideoId()).append(".html'\">");
//<button class="link" onclick="alert(1)">Click</button>
}
videoHtml.append("Back");
if (youtubeVideo.getPreviousVideoId() != null) {
//videoHtml.append("</a>");
videoHtml.append("</button>");
}
videoHtml.append("&nbsp;&nbsp;&nbsp;");
if (youtubeVideo.getNextVideoId() != null) {
//videoHtml.append("<a href=\"./").append(youtubeVideo.getNextVideoId()).append(".html\">");
videoHtml.append("<button style=\"font-size:150%;\" onclick=\"window.location ='").append("./").append(youtubeVideo.getNextVideoId()).append(".html'\">");
}
videoHtml.append("Next");
if (youtubeVideo.getNextVideoId() != null) {
//videoHtml.append("</a>");
videoHtml.append("</button>");
sb2.append(formatter.format(((double)z.getVideoFileSizeInBytes()) / 1024d / 1024d)).append(" MB");
sb2.append("<br>\n");
sb2.append("<pre style=\"white-space: pre-wrap; border:1px solid black;max-width:600px;padding:10px;min-height:50px;\">");
sb2.append(z.getDescription().isBlank() ? "No description" : z.getDescription());
sb2.append("</pre>");
sb2.append("<h2>Comments</h2>");
z.getComments().forEach(co -> {
}
videoHtml.append(" ");
videoHtml
.append("<br><br><a href=\"../archive/")
.append(youtubeVideo.getSnapshot())
.append("/media/")
.append(youtubeVideo.getVideoFileName())
.append("\">Download</a> ");
videoHtml.append(formatter.format(((double) youtubeVideo.getVideoFileSizeInBytes()) / 1024d / 1024d)).append(" MB ");
if (youtubeVideo.getVideoFileName().endsWith(".mkv")) {
String v = youtubeVideo.getVideoFileName().replaceAll(" ", "\\\\ ");
v = v.replace("(", "\\(");
v = v.replace(")", "\\)");
var vWebm = v.substring(0, v.length() - 3) + "webm";
videoHtml.append("<input type=\"text\" id=\"archiveBoxArchiveDirectory\" name=\"archiveBoxArchiveDirectory\" size=\"100\" width=\"100\" style=\"margin-bottom:20px;margin-right:10px;font-size:110%;padding:5px;\" value=\"");
videoHtml.append("cd ").append(archiveBoxArchiveDirectory).append("/").append(youtubeVideo.getSnapshot()).append("/media/");
videoHtml.append(" && ffmpeg -i ").append(v).append(" -preset slow -crf 18 ").append(vWebm) ;
videoHtml.append("\"><br>");
} else {
videoHtml.append("<input type=\"text\" id=\"archiveBoxArchiveDirectory\" name=\"archiveBoxArchiveDirectory\" size=\"100\" width=\"100\" style=\"margin-bottom:20px;margin-right:10px;font-size:110%;padding:5px;\" value=\"");
videoHtml.append(archiveBoxArchiveDirectory).append("/").append(youtubeVideo.getSnapshot()).append("/media/");
videoHtml.append("\"><br>");
}
videoHtml.append("<a target=\"_blank\" href=\"file://").append(archiveBoxArchiveDirectory).append("/").append(youtubeVideo.getSnapshot()).append("/media\">Directory</a>").append("<br>");
videoHtml.append("<br>\n<br>\n");
videoHtml.append("<br>\n");
videoHtml.append("<pre style=\"white-space: pre-wrap; border:1px solid black;max-width:600px;padding:10px;min-height:50px;\">");
videoHtml.append(youtubeVideo.getDescription().isBlank() ? "No description" : youtubeVideo.getDescription());
videoHtml.append("</pre>");
videoHtml.append("<h2>Comments</h2>");
youtubeVideo.getComments().forEach(co -> {
// private String id, parentId, text, author;
// private int timestamp;
sb2.append("<div style=\"margin-left:")
.append(co.dotCount() * 50)
.append("px;\">");
sb2.append("<h3>").append(co.getAuthor()).append("</h3>");
videoHtml.append("<div style=\"margin-left:")
.append(co.dotCount() * 50)
.append("px;\">");
videoHtml.append("<h3>").append(co.getAuthor()).append("</h3>");
sb2.append("<span style=\"color:grey;font-size:80%;\">")
.append(Utils.DATE_FORMAT.format(new Date(co.getTimestamp() * 1000))).append("</span><br>\n");
sb2.append("<span style=\"color:grey;font-size:80%;\">")
.append(co.getId() + " " + co.getParentId()).append("</span><br>\n");
sb2.append("<pre style=\"white-space: pre-wrap;border:1px solid black;max-width:600px;padding:10px;min-height:50px;\">").append(co.getText()).append("</pre>");
sb2.append("</div>");
});
videoHtml.append("<span style=\"color:grey;font-size:80%;\">")
.append(Utils.DATE_FORMAT.format(new Date(co.getTimestamp() * 1000))).append("</span><br>\n");
videoHtml.append("<span style=\"color:grey;font-size:80%;\">").append(co.getId()).append(" ")
.append(co.getParentId()).append("</span><br>\n");
videoHtml.append("<pre style=\"white-space: pre-wrap;border:1px solid black;max-width:600px;padding:10px;min-height:50px;\">").append(co.getText()).append("</pre>");
videoHtml.append("</div>");
});
// private String id;
//
@ -414,11 +468,11 @@ public class Main {
// private String description;
// private String thumbnail;
// private List<YoutubeComment> comments = new ArrayList<>();
sb2.append("</body></html>");
String singleVideo = sb2.toString();
//singleVideo.replace("<br>\n", "<br>\n\n");
Utils.writeTextToFile(singleVideo, videoHtmlFile);
}
videoHtml.append("</body></html>");
String singleVideo = videoHtml.toString();
//singleVideo.replace("<br>\n", "<br>\n\n");
Utils.writeTextToFile(singleVideo, videoHtmlFile);
}
}
});
if (internalStaticVariableVideoNumberPerRow < argVideosPerRow) {

View File

@ -168,4 +168,19 @@ public class Utils {
}
}
public static boolean convertStringToBoolean(String s) {
switch (s) {
case "1":
return true;
case "true":
return true;
case "0":
return false;
case "false":
return false;
default:
throw new YoutubedlFrontendException("Could not create boolean from String: " + s);
}
}
}