Youtube Downloader In Java

Introduction 

 
YouTube is the biggest video sharing platform in the world. It is headquartered in San Bruno, California. The service was created by three former PayPal employees-Chad Hurley, Steve Chen, and Jawed Karim – in February 2005. Google bought the site in November 2006. YouTube now operates as one of Google’s subsidiaries.
 
The site allows a user to upload, view, rate, share, add to favorites, report, comment on videos and subscribe to other channels. In order to upload a video or create a channel, you have to register yourself. Your Gmail account is enough to add videos and to open a channel. The only disadvantage of this site is that it does not have a download option. You cannot download videos directly from the website. Direct download is not available in order to protect the users' content. Some of the content available on YouTube is copyrighted.
 
Here comes the app I have developed. This app is capable of downloading videos from YouTube. What this app does is, it sends an HTTP request to the YouTube Server using the video ID. In response, the server returns video info. The video info contains the URL to download the video. But there is one problem - the URL is encoded. So first, the URL is decoded by the app and then used to download the video. But that does not mean you can download copyright content.
 
If you send HTTP requests to download the copyright video to the Server, you will not get video URL in response. Also, just a slight nit pick - the app is not perfect. Sometimes, it refuses to download the video however the video is available in the public domain. But guys, don’t worry; just download it again. If you download the installer, the app will download the video in the apps folder. Since the app is installed in the C drive, you should run it using administrative privileges. You can see the code below. These are well documented. I have used Net-beans as an IDE.
  1. /*  
  2.  * To change this license header, choose License Headers in Project Properties.  
  3.  * To change this template file, choose Tools | Templates  
  4.  * and open the template in the editor.  
  5.  */  
  6. package youtubedownloader;  
  7. import java.io.BufferedInputStream;  
  8. import java.io.BufferedReader;  
  9. import java.io.FileOutputStream;  
  10. import java.io.IOException;  
  11. import java.io.InputStreamReader;  
  12. import java.net.HttpURLConnection;  
  13. import java.net.MalformedURLException;  
  14. import java.net.URL;  
  15. import java.net.URLDecoder;  
  16. import javafx.application.Application;  
  17. import javafx.concurrent.Service;  
  18. import javafx.concurrent.Task;  
  19. import javafx.concurrent.WorkerStateEvent;  
  20. import javafx.event.ActionEvent;  
  21. import javafx.scene.Group;  
  22. import javafx.scene.Scene;  
  23. import javafx.scene.control.Alert;  
  24. import javafx.scene.control.Alert.AlertType;  
  25. import javafx.scene.control.Button;  
  26. import javafx.scene.control.Label;  
  27. import javafx.scene.control.ProgressBar;  
  28. import javafx.scene.control.TextField;  
  29. import javafx.scene.text.Font;  
  30. import javafx.stage.Stage;  
  31. /**  
  32.  *  
  33.  * @author Passionate Coder  
  34.  */  
  35. public class YoutubeDownloader extends Application {  
  36.  /*java fx UI element used in the javafx application*/  
  37.  private Button downloadBtn = new Button();  
  38.  private TextField youtubeUrlField = new TextField();  
  39.  private TextField fileName = new TextField();  
  40.  private Label label1 = new Label();  
  41.  private Label label2 = new Label();  
  42.  private Label about = new Label("Created and Developed by Deepank Pant");  
  43.  private ProgressBar pbar = new ProgressBar(0);  
  44.  private URL downloadURL;  
  45.  @Override  
  46.  public void start(Stage primaryStage) {  
  47.   /*Font used in the project*/  
  48.   Font poorRichard = new Font("Poor Richard"16);  
  49.   Font poorRichard2 = new Font("Poor Richard"13);  
  50.   /*setting for the UI element*/  
  51.   downloadBtn.setText("Download");  
  52.   downloadBtn.setFont(poorRichard);  
  53.   downloadBtn.setLayoutX(10);  
  54.   downloadBtn.setLayoutY(200);  
  55.   youtubeUrlField.setFont(poorRichard);  
  56.   youtubeUrlField.setLayoutX(10);  
  57.   youtubeUrlField.setLayoutY(80);  
  58.   youtubeUrlField.setPrefColumnCount(23);  
  59.   fileName.setFont(poorRichard);  
  60.   fileName.setLayoutX(10);  
  61.   fileName.setLayoutY(150);  
  62.   fileName.setPrefColumnCount(23);  
  63.   label1.setFont(poorRichard);  
  64.   label1.setText("Youtube URL");  
  65.   label1.setLayoutX(10);  
  66.   label1.setLayoutY(50);  
  67.   label2.setFont(poorRichard);  
  68.   label2.setText("File Name (Optional)");  
  69.   label2.setLayoutX(10);  
  70.   label2.setLayoutY(120);  
  71.   pbar.setVisible(false);  
  72.   pbar.setPrefWidth(350);  
  73.   pbar.setLayoutX(100);  
  74.   pbar.setLayoutY(200);  
  75.   about.setFont(poorRichard2);  
  76.   about.setLayoutX(20);  
  77.   about.setLayoutY(260);  
  78.   /*Event is triggered when we press the download button*/  
  79.   downloadBtn.setOnAction((ActionEvent event) -> {  
  80.    sendHTTPRequest.restart();  
  81.   });  
  82.   /*Event is triggered when the sendHTTP request service completed successfully*/  
  83.   sendHTTPRequest.setOnSucceeded((WorkerStateEvent we) -> {  
  84.    try {  
  85.     downloadURL = new URL(getURLS(sendHTTPRequest.getValue()));  
  86.     pbar.progressProperty().unbind();  
  87.     pbar.setProgress(0);  
  88.     pbar.progressProperty().bind(VideoDownload.progressProperty());  
  89.     pbar.setVisible(true);  
  90.     /*if everything goes right then it will start a new service to download the video*/  
  91.     VideoDownload.restart();  
  92.    } catch (MalformedURLException ex) {  
  93.     Alert msg = new Alert(AlertType.INFORMATION);  
  94.     msg.setTitle("Message from Youtube Downloader");  
  95.     msg.setContentText("Invalid Url");  
  96.     msg.showAndWait();  
  97.    }  
  98.   });  
  99.   /*Event is fired when videDownload service is completed successfully*/  
  100.   VideoDownload.setOnSucceeded((WorkerStateEvent we) -> {  
  101.    boolean val = VideoDownload.getValue();  
  102.    System.out.println(val);  
  103.    if (val) {  
  104.     Alert msg = new Alert(AlertType.INFORMATION);  
  105.     msg.setTitle("Message from Youtube Downloader");  
  106.     msg.setContentText("Download complete");  
  107.     msg.showAndWait();  
  108.    } else {  
  109.     Alert msg = new Alert(AlertType.INFORMATION);  
  110.     msg.setTitle("Message from Youtube Downloader");  
  111.     msg.setContentText("Download Failed");  
  112.     msg.showAndWait();  
  113.    }  
  114.    pbar.setVisible(false);  
  115.   });  
  116.   Group root = new Group();  
  117.   root.getChildren().add(downloadBtn);  
  118.   root.getChildren().add(youtubeUrlField);  
  119.   root.getChildren().add(fileName);  
  120.   root.getChildren().add(label1);  
  121.   root.getChildren().add(label2);  
  122.   root.getChildren().add(pbar);  
  123.   root.getChildren().add(about);  
  124.   Scene scene = new Scene(root, 500280);  
  125.   primaryStage.setTitle("Youtube Downloader");  
  126.   primaryStage.setScene(scene);  
  127.   primaryStage.setResizable(false);  
  128.   primaryStage.show();  
  129.  }  
  130.  /*Method to extract the video id from the url.  
  131.  if the url does not contain 'v=' parameter  
  132.  then it will not work. It will accept only  
  133.  standard url*/  
  134.  private String getVideoID(String url) {  
  135.   int index = url.indexOf("v=");  
  136.   String;  
  137.   index += 2;  
  138.   for (int i = index; i < url.length(); i++) id += url.charAt(i);  
  139.   return id;  
  140.  }  
  141.  /*This service send the HTTP Request to the youtube server. In response the youtube server  
  142.  sends the video information. This information contains the url in the encoded format. This  
  143.  method decode the url return it as a StringBuilder Object*/  
  144.  final private Service < StringBuilder > sendHTTPRequest = new Service < StringBuilder > () {  
  145.   @Override  
  146.   protected Task < StringBuilder > createTask() {  
  147.    return new Task < StringBuilder > () {  
  148.     @Override  
  149.     protected StringBuilder call() {  
  150.      String response;  
  151.      StringBuilder res = new StringBuilder();  
  152.      StringBuilder refinedres = new StringBuilder();  
  153.      try {  
  154.       URL url = new URL("https://www.youtube.com/get_video_info?&video_id=" + getVideoID(youtubeUrlField.getText()));  
  155.       System.out.println(url.toString());  
  156.       HttpURLConnection conn = (HttpURLConnection) url.openConnection();  
  157.       conn.setRequestMethod("GET");  
  158.       System.out.println(conn.getResponseMessage());  
  159.       BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));  
  160.       while ((response = in .readLine()) != null) res.append(response);  
  161.       refinedres.append(URLDecoder.decode(URLDecoder.decode(res.toString(), "UTF-8"), "UTF-8")); in .close();  
  162.       return refinedres;  
  163.      } catch (MalformedURLException ex) {} catch (IOException ex) {}  
  164.      return null;  
  165.     }  
  166.    };  
  167.   }  
  168.  };  
  169.  /*This service will download the videos using the URL*/  
  170.  Service < Boolean > VideoDownload = new Service < Boolean > () {  
  171.   @Override  
  172.   protected Task < Boolean > createTask() {  
  173.    return new Task < Boolean > () {  
  174.     @Override  
  175.     protected Boolean call() throws Exception {  
  176.      long length;  
  177.      boolean completed = false;  
  178.      int count = 0;  
  179.      try (BufferedInputStream bis = new BufferedInputStream(downloadURL.openStream()); FileOutputStream fos = new FileOutputStream(fileName.getText().length() == 0 ? "video.mp4" : fileName.getText().concat(".mp4"))) {  
  180.       length = downloadURL.openConnection().getContentLength();  
  181.       int i = 0;  
  182.       final byte[] data = new byte[1024];  
  183.       while ((count = bis.read(data)) != -1) {  
  184.        i += count;  
  185.        fos.write(data, 0, count);  
  186.        updateProgress(i, length);  
  187.       }  
  188.       completed = true;  
  189.      } catch (IOException ex) {}  
  190.      return completed;  
  191.     }  
  192.    };  
  193.   }  
  194.  };  
  195.  /*This methid receives refined response as a paramter and extract the url from the  
  196.  response which will be used to download the video from the youtube*/  
  197.  private String getURLS(StringBuilder response) {  
  198.   StringBuilder temp1 = new StringBuilder();  
  199.   String[] temp2, temp3, temp4;  
  200.   try {  
  201.    int index = response.indexOf("url_encoded_fmt_stream_map");  
  202.    for (int i = index; i < response.length(); i++) {  
  203.     temp1.append(response.charAt(i));  
  204.    }  
  205.    temp2 = temp1.toString().split("&url=");  
  206.    if (temp2.length > 0) {  
  207.     temp3 = temp2[1].split(";");  
  208.     if (temp3.length > 0) {  
  209.      temp4 = temp3[0].split(",");  
  210.      if (temp4.length > 0return temp4[0];  
  211.      else return temp3[0];  
  212.     } else return temp2[1];  
  213.    }  
  214.   } catch (Exception e) {  
  215.    Alert msg = new Alert(AlertType.INFORMATION);  
  216.    msg.setTitle("Message form youtube Downloader");  
  217.    msg.setContentText("Error in downloading");  
  218.    msg.showAndWait();  
  219.   }  
  220.   return null;  
  221.  }  
  222.  /**  
  223.   * @param args the command line arguments  
  224.   */  
  225.  public static void main(String[] args) {  
  226.   launch(args);  
  227.  }  
  228. }   
Remember, I have used Java 8 to develop this app. Readers are advised to install Java 8 in order to run the code. I have also created a stand-alone installer for which you do not need the trace of Java to be installed on your system. The installer contains all the Java runtime files required to run the application.
 
Since I have used 64-bit Java to create the app, it might not work in 32-bit operating systems. If you can download the source code as a Netbeans project in a zip file and the standalone installer you can follow the link below.
Next Recommended Reading Steps For Handling Events In JAVA