|
|
@ -13,6 +13,7 @@ import java.nio.file.Files; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.LinkedList; |
|
|
|
import java.util.LinkedList; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
|
|
|
|
import java.util.Scanner; |
|
|
|
import java.util.concurrent.LinkedBlockingDeque; |
|
|
|
import java.util.concurrent.LinkedBlockingDeque; |
|
|
|
import java.util.concurrent.ThreadPoolExecutor; |
|
|
|
import java.util.concurrent.ThreadPoolExecutor; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
@ -38,12 +39,14 @@ public class Downloader implements Consumer<DownloadTask> |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
private static final int DOWNLOAD_TIMEOUT = 300; |
|
|
|
private static final int DOWNLOAD_TIMEOUT = 300; |
|
|
|
private static final int INFO_TIMEOUT = 10; |
|
|
|
private static final int INFO_TIMEOUT = 30; |
|
|
|
private static final int FORMAT_TIMEOUT = 5; |
|
|
|
private static final int FORMAT_TIMEOUT = 5; |
|
|
|
|
|
|
|
|
|
|
|
private static final int BITRATE_TARGET = (int) AudioSendHandler.INPUT_FORMAT.getSampleRate(); |
|
|
|
private static final int BITRATE_TARGET = (int) AudioSendHandler.INPUT_FORMAT.getSampleRate(); |
|
|
|
private static final Pattern FORMAT_PATTERN = Pattern.compile("^([\\w]+)\\s+([\\w]+)\\s+(\\w+ ?\\w*)\\s+(.*)$"); |
|
|
|
private static final Pattern FORMAT_PATTERN = Pattern.compile("^([\\w]+)\\s+([\\w]+)\\s+(\\w+ ?\\w*)\\s+(.*)$"); |
|
|
|
public static final Pattern DESTINATION_PATTERN = Pattern.compile("Destination: (.*\\.wav)"); |
|
|
|
public static final Pattern DESTINATION_PATTERN = Pattern.compile("Destination: (.*\\.wav)"); |
|
|
|
|
|
|
|
public static final Pattern PROGRESS_PATTERN = Pattern.compile("\\[download\\].*?([\\d\\.]+)%"); |
|
|
|
|
|
|
|
private static final Pattern ETA_PATTERN = Pattern.compile("\\[download\\].*?ETA\\s+(\\d{1,2}:\\d{2})"); |
|
|
|
|
|
|
|
|
|
|
|
private final List<DownloadTask> downloadQueue = new LinkedList<>(); |
|
|
|
private final List<DownloadTask> downloadQueue = new LinkedList<>(); |
|
|
|
private final LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(); |
|
|
|
private final LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(); |
|
|
@ -258,19 +261,39 @@ public class Downloader implements Consumer<DownloadTask> |
|
|
|
+ " -f " + formatCodes + "worstaudio/bestaudio/worst/best" |
|
|
|
+ " -f " + formatCodes + "worstaudio/bestaudio/worst/best" |
|
|
|
+ " --audio-format=wav" |
|
|
|
+ " --audio-format=wav" |
|
|
|
+ " --no-playlist" |
|
|
|
+ " --no-playlist" |
|
|
|
|
|
|
|
+ " --extractor-args youtube:player_client=android" |
|
|
|
+ " -o " + getDownloadDir().getAbsolutePath() + "/%(title)s.%(ext)s " |
|
|
|
+ " -o " + getDownloadDir().getAbsolutePath() + "/%(title)s.%(ext)s " |
|
|
|
+ song.getUrl().toString(); |
|
|
|
+ song.getUrl().toString(); |
|
|
|
|
|
|
|
|
|
|
|
Process exec = runCommand(cmd, DOWNLOAD_TIMEOUT); |
|
|
|
Process exec = runCommand(cmd, DOWNLOAD_TIMEOUT); |
|
|
|
InputStream in = exec.getInputStream(); |
|
|
|
InputStream in = exec.getInputStream(); |
|
|
|
String output = new String(in.readAllBytes(), Charset.defaultCharset()); |
|
|
|
|
|
|
|
|
|
|
|
Scanner sc = new Scanner(in); |
|
|
|
|
|
|
|
while (sc.hasNextLine()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
String line = sc.nextLine(); |
|
|
|
|
|
|
|
System.out.println(line); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matcher progMatcher = PROGRESS_PATTERN.matcher(line); |
|
|
|
|
|
|
|
if (progMatcher.find()) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
task.request.setProgress(Double.parseDouble(progMatcher.group(1))); |
|
|
|
|
|
|
|
messageHandler.accept(task.request, null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Matcher destMatcher = DESTINATION_PATTERN.matcher(line); |
|
|
|
|
|
|
|
if (destMatcher.find()) |
|
|
|
|
|
|
|
song.setLocation(new File(destMatcher.group(1))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// String output = new String(in.readAllBytes(), Charset.defaultCharset());
|
|
|
|
String error = new String(exec.getErrorStream().readAllBytes(), Charset.defaultCharset()); |
|
|
|
String error = new String(exec.getErrorStream().readAllBytes(), Charset.defaultCharset()); |
|
|
|
System.out.println(output); |
|
|
|
// System.out.println(output);
|
|
|
|
Matcher matcher = DESTINATION_PATTERN.matcher(output); |
|
|
|
|
|
|
|
if (matcher.find()) |
|
|
|
if (exec.exitValue() != 0) |
|
|
|
song.setLocation(new File(matcher.group(1))); |
|
|
|
|
|
|
|
else if (exec.exitValue() != 0) |
|
|
|
|
|
|
|
throw new RuntimeException("youtube-dl failed with error " + exec.exitValue() + ", output:\n" + error); |
|
|
|
throw new RuntimeException("youtube-dl failed with error " + exec.exitValue() + ", output:\n" + error); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
task.request.setProgress(100); |
|
|
|
// return true;
|
|
|
|
// return true;
|
|
|
|
|
|
|
|
|
|
|
|
if (task.getDestination() != null) |
|
|
|
if (task.getDestination() != null) |
|
|
|