diff options
| author | Pinapelz <yukais@pinapelz.com> | 2026-05-14 01:15:04 -0700 |
|---|---|---|
| committer | Pinapelz <yukais@pinapelz.com> | 2026-05-14 01:20:32 -0700 |
| commit | f140a977dd16b8a5357fccb136b16a1f4195cfe6 (patch) | |
| tree | 5a5d0639a089b6deb160655aa1bee23a10fb68e4 | |
| parent | 34606cd95856449bdb8dc3a5d3e0ff823bb6af4e (diff) | |
add filename override for time-range videos
| -rw-r--r-- | README.md | 10 | ||||
| -rw-r--r-- | pom.xml | 2 | ||||
| -rw-r--r-- | src/main/java/DownloadConfigPane.java | 71 | ||||
| -rw-r--r-- | src/main/java/Downloader.java | 15 | ||||
| -rw-r--r-- | src/main/java/Main.java | 33 |
5 files changed, 92 insertions, 39 deletions
@@ -15,11 +15,14 @@ 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` +ex: `https://www.youtube.com/watch?v=qvj_QSqOrBw,00:01:10-00:01:40,MySong` - Download video `https://www.youtube.com/watch?v=qvj_QSqOrBw` from `1 min 10s` to `1 min 40s` (30s total) +- The output file will be renamed to contain `MySong` in the filename # Requirements @@ -33,8 +36,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 @@ -8,7 +8,7 @@ <groupId>org.example</groupId>
<artifactId>ytID3AutoTag</artifactId>
- <version>1.6</version>
+ <version>1.7</version>
<name>YouTubeMp3AutoTag</name>
<properties>
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<String> 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 {
|
