diff options
| author | Donald Shan <xxpinapelzxx@gmail.com> | 2022-10-23 14:13:00 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-23 14:13:00 -0700 |
| commit | 76d77da29c5386cb9ea3b64c07fe43571cfcd246 (patch) | |
| tree | f62943de706b1aa1f1100a02f9c368eeaf244356 | |
| parent | 888e64227a1e7e2ec74d2b9d96751309417bd677 (diff) | |
Fixed bug where files don't download due to missing thumbnail
code will now check multiple formats for thumbnails. Resolution may be lost but its better than nothing
| -rw-r--r-- | FileUtility.java | 189 | ||||
| -rw-r--r-- | Main.java | 258 |
2 files changed, 447 insertions, 0 deletions
diff --git a/FileUtility.java b/FileUtility.java new file mode 100644 index 0000000..3a1504a --- /dev/null +++ b/FileUtility.java @@ -0,0 +1,189 @@ +import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import java.io.*;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FileUtility {
+ public void deleteFile(String fileName) {
+ File file = new File(fileName);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+
+ public void downloadImage(String url, String fileName,String[] formats) {
+ boolean successfulDownload = false;
+ int formatIndex = 0;
+ while(!successfulDownload) {
+ try {
+ FileOutputStream fos = new FileOutputStream(fileName);
+ URL urlObj = new URL(url+formats[formatIndex]);
+ InputStream is = urlObj.openStream();
+ byte[] b = new byte[2048];
+ int length;
+ while ((length = is.read(b)) != -1) {
+ fos.write(b, 0, length);
+ }
+ fos.close();
+ is.close();
+ successfulDownload = true;
+ } catch (Exception e) {
+ formatIndex++;
+ }
+ }
+
+ }
+
+ public void moveFile(String source, String destination) {
+ File sourceFile = new File(source);
+ File destinationFile = new File(destination);
+ sourceFile.renameTo(destinationFile);
+ System.out.println("Moved file to Completed Folder");
+ }
+ public String removeNonAlphaNumeric(String str) {
+ return str.replaceAll("[^a-zA-Z0-9]", "");
+ }
+ public static String showTextFileChooser() {
+ javax.swing.JFileChooser chooser = new javax.swing.JFileChooser();
+ FileNameExtensionFilter filter = new FileNameExtensionFilter("Text File", "txt", "text");
+ chooser.setFileFilter(filter);
+ chooser.setDialogTitle("Select a text file");
+ chooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_ONLY);
+ chooser.setAcceptAllFileFilterUsed(false);
+ if (chooser.showOpenDialog(null) == javax.swing.JFileChooser.APPROVE_OPTION) {
+ return chooser.getSelectedFile().getAbsolutePath();
+ } else {
+ return null;
+ }
+ }
+ public static File findMP3File(String directory){
+ File dir = new File(directory);
+ File[] files = dir.listFiles();
+ for(File file : files){
+ if(file.getName().endsWith(".mp3")){
+ return file;
+ }
+ }
+ return null;
+ }
+
+ public static String findJsonFile(String folderName) {
+ File folder = new File(folderName);
+ File[] listOfFiles = folder.listFiles();
+ for (int i = 0; i < listOfFiles.length; i++) {
+ if (listOfFiles[i].isFile()) {
+ if (listOfFiles[i].getName().endsWith(".json")) {
+ return listOfFiles[i].getAbsolutePath();
+ }
+ }
+ }
+ return null;
+ }
+ public static String[] parseJson(String json) {
+ String title = "";
+ String uploader = "";
+ String id = "";
+ Pattern titlePattern = Pattern.compile("\"fulltitle\": \"(.*?)\",");
+ Matcher titleMatcher = titlePattern.matcher(json);
+ Pattern uploaderPattern = Pattern.compile("\"uploader\": \"(.*?)\",");
+ Matcher uploaderMatcher = uploaderPattern.matcher(json);
+ Pattern idPattern = Pattern.compile("\"id\": \"(.*?)\",");
+ Matcher idMatcher = idPattern.matcher(json);
+ titleMatcher.find();
+ idMatcher.find();
+ uploaderMatcher.find();
+ title = titleMatcher.group(1);
+ uploader = uploaderMatcher.group(1);
+ id = idMatcher.group(1);
+ String[] info = {title,uploader,id};
+ return info;
+
+ }
+ public static String jsonToString(String fileName) {
+ String json = "";
+ try {
+ BufferedReader br = new BufferedReader(new FileReader(fileName));
+ StringBuilder sb = new StringBuilder();
+ String line = br.readLine();
+ while (line != null) {
+ sb.append(line);
+ line = br.readLine();
+ }
+ json = sb.toString();
+ br.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return json;
+ }
+ public static void deleteAllFilesDir(String path) {
+ File folder = new File(path);
+ File[] files = folder.listFiles();
+ if (files != null) {
+ for (File f : files) {
+ f.delete();
+ }
+ }
+ }
+
+ public static String showImageFileChooser() {
+ javax.swing.JFileChooser chooser = new javax.swing.JFileChooser();
+ FileNameExtensionFilter filter = new FileNameExtensionFilter("JPEG Image File", "jpg", "jpeg");
+ chooser.setFileFilter(filter);
+ chooser.setDialogTitle("Select a image file");
+ chooser.setFileSelectionMode(javax.swing.JFileChooser.FILES_ONLY);
+ chooser.setAcceptAllFileFilterUsed(false);
+ if (chooser.showOpenDialog(null) == javax.swing.JFileChooser.APPROVE_OPTION) {
+ return chooser.getSelectedFile().getAbsolutePath();
+ } else {
+ return null;
+ }
+ }
+ public static ArrayList<String> txtToArrayList(String fileName) {
+ ArrayList<String> lines = new ArrayList<String>();
+ try {
+ FileReader fr = new FileReader(fileName);
+ BufferedReader br = new BufferedReader(fr);
+ String line;
+ while ((line = br.readLine()) != null) {
+ lines.add(line);
+ }
+ br.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return lines;
+ }
+ public String showDirectoryChooser(){
+ try {
+ JFileChooser fileChooser = new JFileChooser();
+ fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ int result = fileChooser.showOpenDialog(null);
+ if (result == JFileChooser.APPROVE_OPTION) {
+ return fileChooser.getSelectedFile().getAbsolutePath();
+ }
+ }
+ catch(Exception e){
+ JOptionPane.showMessageDialog(null,"An unexpected error has occured");
+ }
+ return "";
+ }
+ //get the path of all mp3 files in a directory and return them as a file arraylist
+ public ArrayList<File> getMp3Files(String path){
+ ArrayList<File> mp3Files = new ArrayList<File>();
+ File folder = new File(path);
+ File[] listOfFiles = folder.listFiles();
+
+ for(int i=0;i<listOfFiles.length;i++){
+ if(listOfFiles[i].isFile()){
+ if(listOfFiles[i].getName().endsWith(".mp3")){
+ mp3Files.add(listOfFiles[i]);
+ }
+ }
+ }
+ return mp3Files;
+ }
+}
diff --git a/Main.java b/Main.java new file mode 100644 index 0000000..8868afe --- /dev/null +++ b/Main.java @@ -0,0 +1,258 @@ +import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.*;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.jaudiotagger.audio.AudioFile;
+import org.jaudiotagger.audio.AudioFileIO;
+import org.jaudiotagger.tag.FieldKey;
+import org.jaudiotagger.tag.Tag;
+import org.jaudiotagger.tag.datatype.Artwork;
+import javax.swing.*;
+import javax.swing.text.DefaultCaret;
+
+
+public class Main extends JFrame {
+ String textPath = "";
+ JPanel panel = new JPanel();
+ Boolean readyState = false;
+ JScrollPane scrollPane;
+ JButton editButton = new JButton("Edit Tags");
+ int progress = 0;
+ String formats[] = {"maxresdefault.jpg","mqdefault.jpg","hqdefault.jpg"};
+ FileUtility fileUtil = new FileUtility();
+ JProgressBar progressBar = new JProgressBar();
+ JLabel title = new JLabel("YouTube to MP3 Auto Tagging");
+ JButton startButton = new JButton("Set .txt File");
+ static JTextArea outputArea = new JTextArea("");
+
+ public Main(){
+ initializeComponents();
+ initializeActionsListeners();
+ }
+
+ public static void main(String[] args) {
+ new Main().setVisible(true);
+ }
+
+ private void downloadAndTag(){ //Main loop ran for checking list of songs, downloading mp3 files, and applying tags
+ ArrayList<String> songs = fileUtil.txtToArrayList(textPath);
+ progress = 0;
+ String timeAppend = "";
+ boolean partFlag = false;
+ for(int i = 0;i<songs.size();i++) {
+ try {
+ fileUtil.deleteAllFilesDir("downloaded");
+ ArrayList<String> splitStamp = null;
+ try{
+ splitStamp = new ArrayList<>(Arrays.asList(songs.get(i).split(",")));
+ }
+ catch(Exception e) {
+
+ }
+ if(splitStamp.size()>=2){
+ timeAppend = youtubeToMP3Part(splitStamp.get(0),splitStamp.get(1));
+ partFlag = true;
+ }
+ else{
+ youtubeToMP3Full(songs.get(i));
+ }
+
+ String info[] = fileUtil.parseJson(fileUtil.jsonToString(fileUtil.findJsonFile("downloaded"))); //title,uploader
+ String uploader = info[1];
+ String title = info[0];
+ AudioFile f = AudioFileIO.read(fileUtil.findMP3File("downloaded"));
+ Tag tag = f.getTag();
+ tag.setField(FieldKey.ARTIST, uploader);
+ tag.setField(FieldKey.TITLE, title);
+ fileUtil.downloadImage("https://img.youtube.com/vi/"+info[2]+"/","img.jpg",formats);
+ Artwork cover = Artwork.createArtworkFromFile(new File("img.jpg"));
+ tag.addField(cover);
+ f.commit();
+ fileUtil.deleteFile("img.jpg");
+ if(partFlag){
+ fileUtil.moveFile(fileUtil.findMP3File("downloaded").getAbsolutePath(), "completed/"
+ + fileUtil.removeNonAlphaNumeric(info[0]) +
+ " ["+info[2]+ "]"+timeAppend+".mp3");
+ }
+ else{
+ fileUtil.moveFile(fileUtil.findMP3File("downloaded").getAbsolutePath(), "completed/" +
+ fileUtil.removeNonAlphaNumeric(info[0]) + " ["+info[2]+ "].mp3");
+ }
+ outputArea.setText(outputArea.getText()+"\n"+"Moved file to Completed Folder");
+ progress = i;
+ System.out.println("Current Progress " + calculatePercentage(i+1,songs.size()));
+ progressBar.setValue(calculatePercentage(i+1,songs.size()));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private int calculatePercentage(int current, int total){//Calculate the percentage when give numerator and denominator
+ double currentD = current;
+ double totalD = total;
+ return (int)((currentD/totalD)*100);
+ }
+
+ public static void showWarning(String message) {
+ JOptionPane.showMessageDialog(null, message, "JUST YOUR FRIENDLY NEIGHBORLY REMINDER", JOptionPane.WARNING_MESSAGE);
+ }
+
+ public static void youtubeToMP3Full(String url) {//Download mp3 of youtube video using yt-dlp.exe. Ran from cmd
+ try {
+ ProcessBuilder builder = new ProcessBuilder(
+ "yt-dlp.exe",
+ "--extract-audio",
+ "--audio-format", "mp3",
+ "--audio-quality", "0",
+ "--output", "downloaded/%(title)s_%(id)s.mp3",
+ "--ffmpeg-location","ffmpeg.exe",
+ "--write-info-json",
+ url
+ );
+ builder.redirectErrorStream(true);
+ Process p = builder.start();
+ BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ while (true) {
+ line = r.readLine();
+ if (line == null) {
+ break;
+ }
+ outputArea.setText(outputArea.getText()+"\n"+line);
+ System.out.println(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+ public static String youtubeToMP3Part(String url,String stamp) {//Download mp3 of youtube video using yt-dlp.exe. Ran from cmd
+ System.out.println(url + " " + stamp);
+ ArrayList<String> times = new ArrayList<>(Arrays.asList(stamp.split("-")));
+ ArrayList<String> startTimeComponents = new ArrayList<>(Arrays.asList(times.get(0).split(":")));
+ ArrayList<String> endTimeComponents = new ArrayList<>(Arrays.asList(times.get(1).split(":")));
+ int startSec = 0;
+ int endSec = 0;
+ if(startTimeComponents.size()==3){
+ startSec = Integer.parseInt(startTimeComponents.get(0))*60*60+Integer.parseInt(startTimeComponents.get(1))*60+Integer.parseInt(startTimeComponents.get(2));
+ }
+ else if(startTimeComponents.size()==2){
+ startSec = Integer.parseInt(startTimeComponents.get(0))*60+Integer.parseInt(startTimeComponents.get(1));
+ }
+ if(endTimeComponents.size()==3){
+ endSec = Integer.parseInt(endTimeComponents.get(0))*60*60+Integer.parseInt(endTimeComponents.get(1))*60+Integer.parseInt(endTimeComponents.get(2));
+ }
+ else if(endTimeComponents.size()==2){
+ endSec = Integer.parseInt(endTimeComponents.get(0))*60+Integer.parseInt(endTimeComponents.get(1));
+ }
+ try {
+ ProcessBuilder builder = new ProcessBuilder(
+ "yt-dlp.exe",
+ "--extract-audio",
+ "--audio-format", "mp3",
+ "--audio-quality", "0",
+ "--output", "downloaded/%(title)s_%(id)s.mp3",
+ "--ffmpeg-location","ffmpeg.exe",
+ "--write-info-json","--download-sections","\"*"+startSec+"-"+endSec+"\"",
+ "--force-keyframes-at-cuts",
+ url
+ );
+ builder.redirectErrorStream(true);
+ Process p = builder.start();
+ BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ while (true) {
+ line = r.readLine();
+ if (line == null) {
+ break;
+ }
+ outputArea.setText(outputArea.getText()+"\n"+line);
+ System.out.println(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return startSec+"to"+endSec;
+ }
+
+
+ private void initializeComponents(){//Initiate GUI components
+ this.setDefaultCloseOperation(EXIT_ON_CLOSE);
+ this.setLocationRelativeTo(null);
+ this.add(panel);
+ panel.setLayout(new BoxLayout(panel,BoxLayout.PAGE_AXIS));
+ scrollPane = new JScrollPane(outputArea);
+ scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ outputArea.setEditable(true);
+ outputArea.setLineWrap(true);
+ DefaultCaret caret = (DefaultCaret)outputArea.getCaret();
+ caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
+ panel.add(Box.createRigidArea(new Dimension(0,5)));
+ panel.setBorder(BorderFactory.createEmptyBorder(25,10,20,10));
+ startButton.setAlignmentX(CENTER_ALIGNMENT);
+ title.setAlignmentX(Component.CENTER_ALIGNMENT);
+ editButton.setAlignmentX(Component.CENTER_ALIGNMENT);
+ progressBar.setStringPainted(true);
+ title.setFont(new Font("Verdana", Font.PLAIN, 14));
+ panel.add(title);
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(progressBar);
+ panel.add(Box.createVerticalStrut(10));
+ panel.add(startButton);
+ panel.add(Box.createVerticalStrut(8));
+ panel.add(scrollPane);
+ panel.add(Box.createVerticalStrut(5));
+ panel.add(editButton);
+ this.setSize(550,450);
+ this.setTitle("YTMP3Tagger");
+ }
+
+ private void initializeActionsListeners(){//Add all actionlisteners for buttons
+ startButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if(readyState==false){
+ outputArea.setText(outputArea.getText()+"\n"+"txt path has not been set. Launching chooserPane");
+ System.out.println(".txt path has not been set. Launching chooserPane");
+ textPath = fileUtil.showTextFileChooser();
+ try {
+ if (!textPath.equals("")) {
+ showWarning("File has been set.\nMake sure you add a new line for each URL");
+ readyState = true;
+ startButton.setText("Start Download");
+ outputArea.setText(outputArea.getText() + "\n" + "Ready to begin downloading. Press the button");
+ System.out.println("Ready to begin downloading. Press the button");
+ }
+ }
+ catch(Exception ex){
+
+ }
+ }
+ else{
+ Runnable runnable = () -> {
+ outputArea.setText("");
+ startButton.setEnabled(false);
+ downloadAndTag();
+ startButton.setEnabled(true);
+
+ };
+ Thread thread = new Thread(runnable);
+ thread.start();
+ }
+ }
+ });
+ editButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e){
+ new TagEditorScreen().setVisible(true);
+ }
+ });
+ }
+
+
+}
\ No newline at end of file |
