From 328e5c2fde86e65dbe2f9f199acabc30ba1d7e70 Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Thu, 14 May 2026 01:15:04 -0700 Subject: add filename override for time-range videos --- README.md | 7 ++-- pom.xml | 2 +- src/main/java/DownloadConfigPane.java | 71 ++++++++++++++++++++++++++--------- src/main/java/Downloader.java | 15 +++++--- src/main/java/Main.java | 33 ++++++++++------ 5 files changed, 90 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index cbac2b8..467b5ba 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,10 @@ If you don't want to use the built-in GUI builder to create a "task file", you c Each line will be treated as a download job (video), you may use either the full `youtube.com` or shortened `youtu.be` link ``` -URL,START_TIME-END_TIME (HH:MM:SS Timestamp Format) +URL,START_TIME-END_TIME,FILENAME_OVERRIDE (HH:MM:SS Timestamp Format) ``` +`FILENAME_OVERRIDE` is optional and only available if specifying a time range. +- Processed files will be automatically renamed to contain what is in this field. This is useful for videos that have multiple songs you want to download in them (so you can tell which file is which). ex: `https://www.youtube.com/watch?v=qvj_QSqOrBw,00:01:10-00:01:40` - Download video `https://www.youtube.com/watch?v=qvj_QSqOrBw` from `1 min 10s` to `1 min 40s` (30s total) @@ -33,8 +35,7 @@ You must also have one of the following browsers installed and have used it to l brave, chrome, chromium, edge, firefox, opera, safari, vivaldi, whale ``` -> Although this program comes with some circumvention techniques, it may still be possible for downloads to fail. When this is the case, try again later -> You may also try adding a [PO-Token](https://github.com/yt-dlp/yt-dlp/wiki/PO-Token-Guide) to make your traffic appear more legit +> Although this program comes with some rate-limit circumvention techniques, videos may still be possible for downloads to fail. When this is the case, try again later # Binaries Pre-built binaries are also available. You can download it from the [Releases](https://github.com/pinapelz/ytID3AutoTag/releases) section diff --git a/pom.xml b/pom.xml index 143c7a1..48c257a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ org.example ytID3AutoTag - 1.6 + 1.7 YouTubeMp3AutoTag diff --git a/src/main/java/DownloadConfigPane.java b/src/main/java/DownloadConfigPane.java index 0a9062c..fb71c55 100644 --- a/src/main/java/DownloadConfigPane.java +++ b/src/main/java/DownloadConfigPane.java @@ -11,12 +11,14 @@ public class DownloadConfigPane extends JFrame{ private JPanel mainPanel; private JTable outputTable; private JTextField urlField; + private JTextField filenameField; private JTextField fromField; private JTextField toField; private JButton loadFromFileButton; private JLabel fromLabel; private JLabel toLabel; private JLabel urlLabel; + private JLabel filenameLabel; private JButton addButton; private JButton saveButton; private JButton removeButton; @@ -30,12 +32,14 @@ public class DownloadConfigPane extends JFrame{ mainPanel = new JPanel(); mainPanel.setLayout(new GridBagLayout()); urlField = new JTextField(); + filenameField = new JTextField(); fromField = new JTextField("HH:MM:SS"); toField = new JTextField("HH:MM:SS"); loadFromFileButton = new JButton("Load From File"); fromLabel = new JLabel("From:"); toLabel = new JLabel("To:"); urlLabel = new JLabel("URL"); + filenameLabel = new JLabel("Filename:"); addButton = new JButton("Add"); saveButton = new JButton("Save"); removeButton = new JButton("Remove"); @@ -65,7 +69,7 @@ public class DownloadConfigPane extends JFrame{ assert playlistUrls != null; String[] urls = playlistUrls.split("\n"); for (String playlistUrl : urls) { - addURLToTable(playlistUrl, "00:00:00", "00:00:00"); + addURLToTable(playlistUrl, "00:00:00", "00:00:00", ""); } } catch (Exception ex) { JOptionPane.showMessageDialog(null, "Invalid playlist URLs. Make sure" + @@ -74,7 +78,8 @@ public class DownloadConfigPane extends JFrame{ } String from = fromField.getText(); String to = toField.getText(); - addURLToTable(url, from, to); + String filename = filenameField.getText(); + addURLToTable(url, from, to, filename); }); removeButton.addActionListener(e -> { @@ -99,10 +104,13 @@ public class DownloadConfigPane extends JFrame{ fromField.setText("BEGINNING_OF_VIDEO"); toField.setEnabled(false); toField.setText("END_OF_VIDEO"); + filenameField.setEnabled(false); + filenameField.setText(""); } else{ fromField.setEnabled(true); toField.setEnabled(true); + filenameField.setEnabled(true); } }); } @@ -111,17 +119,28 @@ public class DownloadConfigPane extends JFrame{ GridBagConstraints gbc = new GridBagConstraints(); gbc.insets = new Insets(5, 5, 5, 5); - // First row - URL + // First row - URL + filename gbc.gridx = 0; gbc.gridy = 0; gbc.anchor = GridBagConstraints.WEST; mainPanel.add(urlLabel, gbc); gbc.gridx = 1; - gbc.gridwidth = 4; + gbc.gridwidth = 2; gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.weightx = 1.0; + gbc.weightx = 0.7; mainPanel.add(urlField, gbc); + + gbc.gridx = 3; + gbc.gridwidth = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0; + mainPanel.add(filenameLabel, gbc); + + gbc.gridx = 4; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 0.3; + mainPanel.add(filenameField, gbc); // Second row - From/To fields gbc.gridx = 0; @@ -190,6 +209,7 @@ public class DownloadConfigPane extends JFrame{ model.addColumn("URL"); model.addColumn("From"); model.addColumn("To"); + model.addColumn("Filename (Override)"); outputTable.setModel(model); outputTable.getTableHeader().setReorderingAllowed(false); } @@ -232,25 +252,32 @@ public class DownloadConfigPane extends JFrame{ clearTable(); try{ for (String line : Files.readAllLines(file.toPath())) { - String[] split = line.split(","); + String from = "00:00:00"; + String to = "00:00:00"; + String filename = ""; + + String[] split = line.split(",", 3); String url = split[0]; - String[] timeRange = new String[2]; - if (split.length == 2){ - timeRange = split[1].split("-"); + if (split.length >= 2 && !split[1].isEmpty()) { + String[] timeRange = split[1].split("-", 2); + if (timeRange.length == 2) { + from = timeRange[0]; + to = timeRange[1]; + } } - else{ - timeRange[0] = "00:00:00"; - timeRange[1] = "00:00:00"; + if (split.length == 3) { + filename = split[2].trim(); } - String from = timeRange[0]; - String to = timeRange[1]; if (from.length() != 8){ from = "00:00:00"; } if (to.length() != 8){ to = "00:00:00"; } - Object[] song = new Object[]{url, from, to}; + if (from.equals("00:00:00") && to.equals("00:00:00")) { + filename = ""; + } + Object[] song = new Object[]{url, from, to, filename}; DefaultTableModel model = (DefaultTableModel) outputTable.getModel(); model.addRow(song); // add headers to the table @@ -287,11 +314,15 @@ public class DownloadConfigPane extends JFrame{ String url = (String) outputTable.getValueAt(i, 0); String from = (String) outputTable.getValueAt(i, 1); String to = (String) outputTable.getValueAt(i, 2); + String filename = (String) outputTable.getValueAt(i, 3); String line = ""; if (from.equals("00:00:00") && to.equals("00:00:00")) { line = url; } else { line = url + "," + from + "-" + to; + if (filename != null && !filename.trim().isEmpty()) { + line += "," + filename.trim(); + } } writer.write(line + System.lineSeparator()); System.out.println(line); @@ -300,7 +331,7 @@ public class DownloadConfigPane extends JFrame{ JOptionPane.showConfirmDialog(null, "Saved to " + loadedPath, "Saved", JOptionPane.DEFAULT_OPTION); } - private void addURLToTable(String url, String from, String to){ + private void addURLToTable(String url, String from, String to, String filename){ if (url.isEmpty()){ return; } @@ -310,7 +341,13 @@ public class DownloadConfigPane extends JFrame{ if (to.length() != 8){ to = "00:00:00"; } - Object[] song = new Object[]{url, from, to}; + if (filename == null){ + filename = ""; + } + if (from.equals("00:00:00") && to.equals("00:00:00")) { + filename = ""; + } + Object[] song = new Object[]{url, from, to, filename.trim()}; DefaultTableModel model = (DefaultTableModel) outputTable.getModel(); model.addRow(song); } diff --git a/src/main/java/Downloader.java b/src/main/java/Downloader.java index c480a85..1fa9470 100644 --- a/src/main/java/Downloader.java +++ b/src/main/java/Downloader.java @@ -83,7 +83,7 @@ public class Downloader { /* Download a part of a video */ - public boolean download(String url, String stamp, String browser){ + public boolean download(String url, String stamp, String filename, String browser){ ArrayList times = new ArrayList<>(Arrays.asList(stamp.split("-"))); String startTime = times.get(0); String endTime = times.get(1); @@ -143,9 +143,11 @@ public class Downloader { if(downloadedMp3 == null){ return false; } - String savedNonAlphaNumName; + String savedNonAlphaNumName = filename; try{ - savedNonAlphaNumName = downloadedMp3.getName(); + if(filename.isEmpty()) { + savedNonAlphaNumName = downloadedMp3.getName(); + } } catch(NullPointerException ex){ return false; @@ -167,7 +169,7 @@ public class Downloader { return true; } - public boolean download(String url, String browser) { + public boolean download(String url, String filename, String browser) { String ytDlpExecutable = "yt-dlp" + (System.getProperty("os.name").startsWith("Windows") ? ".exe" : ""); try { String[] command = { @@ -232,7 +234,10 @@ public class Downloader { UI.Modal.showError("No audio file was found after download."); return false; } - String savedNonAlphaNumName = downloadedFile.getName(); + String savedNonAlphaNumName = filename; + if(filename.isEmpty()){ + savedNonAlphaNumName = downloadedFile.getName(); + } String tempRemoveAlphaNumeric = savedNonAlphaNumName.replaceAll("[^a-zA-Z0-9]", "") + ".mp3"; File renamed = new File(tempRemoveAlphaNumeric); if (!downloadedFile.renameTo(renamed)) { diff --git a/src/main/java/Main.java b/src/main/java/Main.java index 0d1ef41..e7c187f 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -17,6 +17,12 @@ import javax.swing.text.DefaultCaret; import static UI.Modal.chooseBrowserType; import static UI.Modal.showTextFileChooser; +class DownloadTask { + String url = ""; + String range = ""; + String filename = ""; + +} public class Main extends JFrame { private static String completedDir; @@ -96,12 +102,19 @@ public class Main extends JFrame { String browser = configuration.get("browser"); int totalSongs = songs.size(); int songsProcessed = 0; - + Downloader downloader = new Downloader(completedDir, outputArea); for (String line : songs) { - System.out.println(line); - Downloader downloader = new Downloader(completedDir, outputArea); + DownloadTask task = new DownloadTask(); + String[] parts = line.split(","); + task.url = parts[0]; + if (parts.length > 1) { + task.range = parts[1].trim(); + } + if (parts.length > 2) { + task.filename = parts[2].trim(); + } String videoId = extractVideoId(line); - if(downloader.videoIdAlreadyDownloaded(videoId) && !line.contains(",")){ // if video has a time range we assume its on purpose and not a duplicate + if(downloader.videoIdAlreadyDownloaded(videoId) && !task.range.isEmpty()){ // if video has a time range we assume its on purpose and not a duplicate int continueConfirm = JOptionPane.showConfirmDialog( null, "A file with the same video ID (" + videoId + ") already exists in the output directoy. Download anyways?", @@ -113,23 +126,19 @@ public class Main extends JFrame { continue; } } - boolean success = false; + boolean success = false; for (int attempt = 1; attempt <= 3; attempt++) { try { if (line.contains(",")) { - String[] parts = line.split(","); - String url = parts[0]; - String stamp = parts[1]; - - if (downloader.download(url, stamp, browser)) { + if (downloader.download(task.url, task.range, task.filename, browser)) { success = true; break; } else { - System.out.println("Attempt " + attempt + " failed for " + url); + System.out.println("Attempt " + attempt + " failed for " + task.url); } } else { - if (downloader.download(line, browser)) { + if (downloader.download(task.url, task.filename, browser)) { success = true; break; } else { -- cgit v1.2.3