mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-24 00:38:52 -05:00
Unify CLI/GUI lookupSubtitleByHash
This commit is contained in:
parent
66fa39af25
commit
87238fe330
@ -718,8 +718,8 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
CLILogger.fine("Looking up subtitles by hash via " + service.getName());
|
CLILogger.fine("Looking up subtitles by hash via " + service.getName());
|
||||||
Map<File, SubtitleDescriptor> subtitles = lookupSubtitleByHash(service, language, remainingVideos, strict);
|
Map<File, List<SubtitleDescriptor>> options = lookupSubtitleByHash(service, language.getName(), remainingVideos, false, strict);
|
||||||
Map<File, File> downloads = downloadSubtitleBatch(service.getName(), subtitles, outputFormat, outputEncoding, naming);
|
Map<File, File> downloads = downloadSubtitleBatch(service.getName(), options, outputFormat, outputEncoding, naming);
|
||||||
remainingVideos.removeAll(downloads.keySet());
|
remainingVideos.removeAll(downloads.keySet());
|
||||||
subtitleFiles.addAll(downloads.values());
|
subtitleFiles.addAll(downloads.values());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -734,13 +734,8 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
CLILogger.fine(format("Looking up subtitles by name via %s", service.getName()));
|
CLILogger.fine(format("Looking up subtitles by name via %s", service.getName()));
|
||||||
Map<File, SubtitleDescriptor> subtitles = new TreeMap<File, SubtitleDescriptor>();
|
Map<File, List<SubtitleDescriptor>> options = findSubtitleByName(service, remainingVideos, language.getName(), query, false, strict);
|
||||||
for (Entry<File, List<SubtitleDescriptor>> it : findSubtitleMatches(service, remainingVideos, language.getName(), query, false, strict).entrySet()) {
|
Map<File, File> downloads = downloadSubtitleBatch(service.getName(), options, outputFormat, outputEncoding, naming);
|
||||||
if (it.getValue().size() > 0) {
|
|
||||||
subtitles.put(it.getKey(), it.getValue().get(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Map<File, File> downloads = downloadSubtitleBatch(service.getName(), subtitles, outputFormat, outputEncoding, naming);
|
|
||||||
remainingVideos.removeAll(downloads.keySet());
|
remainingVideos.removeAll(downloads.keySet());
|
||||||
subtitleFiles.addAll(downloads.values());
|
subtitleFiles.addAll(downloads.values());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -752,6 +747,7 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
for (File it : remainingVideos) {
|
for (File it : remainingVideos) {
|
||||||
CLILogger.warning("No matching subtitles found: " + it);
|
CLILogger.warning("No matching subtitles found: " + it);
|
||||||
}
|
}
|
||||||
|
|
||||||
return subtitleFiles;
|
return subtitleFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -828,17 +824,20 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<File, File> downloadSubtitleBatch(String service, Map<File, SubtitleDescriptor> subtitles, SubtitleFormat outputFormat, Charset outputEncoding, SubtitleNaming naming) {
|
private Map<File, File> downloadSubtitleBatch(String service, Map<File, List<SubtitleDescriptor>> subtitles, SubtitleFormat outputFormat, Charset outputEncoding, SubtitleNaming naming) {
|
||||||
Map<File, File> downloads = new HashMap<File, File>();
|
Map<File, File> downloads = new LinkedHashMap<File, File>();
|
||||||
|
|
||||||
// fetch subtitle
|
// fetch subtitle
|
||||||
for (Entry<File, SubtitleDescriptor> it : subtitles.entrySet()) {
|
subtitles.forEach((movie, options) -> {
|
||||||
try {
|
if (options.size() > 0) {
|
||||||
downloads.put(it.getKey(), downloadSubtitle(it.getValue(), it.getKey(), outputFormat, outputEncoding, naming));
|
SubtitleDescriptor subtitle = options.get(0);
|
||||||
} catch (Exception e) {
|
try {
|
||||||
CLILogger.warning(format("Failed to download %s: %s", it.getValue().getPath(), e.getMessage()));
|
downloads.put(movie, downloadSubtitle(subtitle, movie, outputFormat, outputEncoding, naming));
|
||||||
|
} catch (Exception e) {
|
||||||
|
CLILogger.warning(format("Failed to download %s: %s", subtitle.getPath(), e.getMessage()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
return downloads;
|
return downloads;
|
||||||
}
|
}
|
||||||
@ -868,22 +867,6 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<File, SubtitleDescriptor> lookupSubtitleByHash(VideoHashSubtitleService service, Language language, Collection<File> videoFiles, boolean strict) throws Exception {
|
|
||||||
Map<File, SubtitleDescriptor> subtitleByVideo = new TreeMap<File, SubtitleDescriptor>();
|
|
||||||
|
|
||||||
for (Entry<File, List<SubtitleDescriptor>> it : service.getSubtitleList(videoFiles.toArray(new File[0]), language.getName()).entrySet()) {
|
|
||||||
// guess best hash match (default order is open bad due to invalid hash links)
|
|
||||||
SubtitleDescriptor bestMatch = getBestMatch(it.getKey(), it.getValue(), strict);
|
|
||||||
|
|
||||||
if (bestMatch != null) {
|
|
||||||
CLILogger.finest(format("Matched [%s] to [%s] via hash", it.getKey().getName(), bestMatch.getName()));
|
|
||||||
subtitleByVideo.put(it.getKey(), bestMatch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtitleByVideo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> List<T> applyExpressionFilter(Collection<T> input, ExpressionFilter filter) throws Exception {
|
private <T> List<T> applyExpressionFilter(Collection<T> input, ExpressionFilter filter) throws Exception {
|
||||||
if (filter == null) {
|
if (filter == null) {
|
||||||
return new ArrayList<T>(input);
|
return new ArrayList<T>(input);
|
||||||
|
@ -940,7 +940,7 @@ public class MediaBindingBean {
|
|||||||
|
|
||||||
// still no good match found -> just take the most probable video from the same folder
|
// still no good match found -> just take the most probable video from the same folder
|
||||||
if (videos.size() > 0) {
|
if (videos.size() > 0) {
|
||||||
sort(videos, SimilarityComparator.compareTo(getMediaFile(), FileUtilities::getName));
|
sort(videos, SimilarityComparator.compareTo(FileUtilities.getName(getMediaFile()), FileUtilities::getName));
|
||||||
return videos.get(0);
|
return videos.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,8 @@ import java.util.function.Function;
|
|||||||
|
|
||||||
public class SimilarityComparator<T, P> implements Comparator<T> {
|
public class SimilarityComparator<T, P> implements Comparator<T> {
|
||||||
|
|
||||||
public static <T, S extends CharSequence> SimilarityComparator<T, S> compareTo(T value, Function<T, S> mapper) {
|
public static <T, S extends CharSequence> SimilarityComparator<T, S> compareTo(S value, Function<T, S> mapper) {
|
||||||
return new SimilarityComparator<T, S>(new NameSimilarityMetric(), singleton(mapper.apply(value)), mapper.andThen(Collections::singleton));
|
return new SimilarityComparator<T, S>(new NameSimilarityMetric(), singleton(value), mapper.andThen(Collections::singleton));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SimilarityMetric metric;
|
protected SimilarityMetric metric;
|
||||||
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -41,6 +42,7 @@ import net.filebot.similarity.MetricAvg;
|
|||||||
import net.filebot.similarity.NameSimilarityMetric;
|
import net.filebot.similarity.NameSimilarityMetric;
|
||||||
import net.filebot.similarity.SeasonEpisodeMatcher.SxE;
|
import net.filebot.similarity.SeasonEpisodeMatcher.SxE;
|
||||||
import net.filebot.similarity.SequenceMatchSimilarity;
|
import net.filebot.similarity.SequenceMatchSimilarity;
|
||||||
|
import net.filebot.similarity.SimilarityComparator;
|
||||||
import net.filebot.similarity.SimilarityMetric;
|
import net.filebot.similarity.SimilarityMetric;
|
||||||
import net.filebot.util.ByteBufferInputStream;
|
import net.filebot.util.ByteBufferInputStream;
|
||||||
import net.filebot.util.UnicodeReader;
|
import net.filebot.util.UnicodeReader;
|
||||||
@ -50,6 +52,7 @@ import net.filebot.web.Movie;
|
|||||||
import net.filebot.web.SubtitleDescriptor;
|
import net.filebot.web.SubtitleDescriptor;
|
||||||
import net.filebot.web.SubtitleProvider;
|
import net.filebot.web.SubtitleProvider;
|
||||||
import net.filebot.web.SubtitleSearchResult;
|
import net.filebot.web.SubtitleSearchResult;
|
||||||
|
import net.filebot.web.VideoHashSubtitleService;
|
||||||
|
|
||||||
import com.optimaize.langdetect.DetectedLanguage;
|
import com.optimaize.langdetect.DetectedLanguage;
|
||||||
import com.optimaize.langdetect.LanguageDetector;
|
import com.optimaize.langdetect.LanguageDetector;
|
||||||
@ -62,7 +65,30 @@ import com.optimaize.langdetect.profiles.LanguageProfileReader;
|
|||||||
|
|
||||||
public final class SubtitleUtilities {
|
public final class SubtitleUtilities {
|
||||||
|
|
||||||
public static Map<File, List<SubtitleDescriptor>> findSubtitleMatches(SubtitleProvider service, Collection<File> fileSet, String languageName, String forceQuery, boolean addOptions, boolean strict) throws Exception {
|
public static Map<File, List<SubtitleDescriptor>> lookupSubtitleByHash(VideoHashSubtitleService service, String languageName, Collection<File> files, boolean addOptions, boolean strict) throws Exception {
|
||||||
|
Map<File, List<SubtitleDescriptor>> options = service.getSubtitleList(files.toArray(new File[files.size()]), languageName);
|
||||||
|
Map<File, List<SubtitleDescriptor>> results = new LinkedHashMap<File, List<SubtitleDescriptor>>(options.size());
|
||||||
|
|
||||||
|
options.forEach((k, v) -> {
|
||||||
|
// guess best hash match (default order is open bad due to invalid hash links)
|
||||||
|
SubtitleDescriptor bestMatch = getBestMatch(k, v, strict);
|
||||||
|
|
||||||
|
// ignore results if there is no best match
|
||||||
|
if (bestMatch != null) {
|
||||||
|
if (addOptions) {
|
||||||
|
Stream<SubtitleDescriptor> top1 = Stream.of(bestMatch);
|
||||||
|
Stream<SubtitleDescriptor> topN = v.stream().filter(Predicate.isEqual(bestMatch).negate()).sorted(SimilarityComparator.compareTo(getName(k), SubtitleDescriptor::getName));
|
||||||
|
results.put(k, Stream.concat(top1, topN).collect(toList()));
|
||||||
|
} else {
|
||||||
|
results.put(k, singletonList(bestMatch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<File, List<SubtitleDescriptor>> findSubtitleByName(SubtitleProvider service, Collection<File> fileSet, String languageName, String forceQuery, boolean addOptions, boolean strict) throws Exception {
|
||||||
// ignore anything that is not a video
|
// ignore anything that is not a video
|
||||||
fileSet = filter(fileSet, VIDEO_FILES);
|
fileSet = filter(fileSet, VIDEO_FILES);
|
||||||
|
|
||||||
@ -331,13 +357,13 @@ public final class SubtitleUtilities {
|
|||||||
if (outputFormat == SubtitleFormat.SubRip) {
|
if (outputFormat == SubtitleFormat.SubRip) {
|
||||||
// output buffer
|
// output buffer
|
||||||
StringBuilder buffer = new StringBuilder(4 * 1024);
|
StringBuilder buffer = new StringBuilder(4 * 1024);
|
||||||
SubRipWriter out = new SubRipWriter(buffer);
|
try (SubRipWriter out = new SubRipWriter(buffer)) {
|
||||||
|
for (SubtitleElement it : decodeSubtitles(data)) {
|
||||||
for (SubtitleElement it : decodeSubtitles(data)) {
|
if (outputTimingOffset != 0) {
|
||||||
if (outputTimingOffset != 0) {
|
it = new SubtitleElement(max(0, it.getStart() + outputTimingOffset), max(0, it.getEnd() + outputTimingOffset), it.getText());
|
||||||
it = new SubtitleElement(max(0, it.getStart() + outputTimingOffset), max(0, it.getEnd() + outputTimingOffset), it.getText());
|
}
|
||||||
|
out.write(it);
|
||||||
}
|
}
|
||||||
out.write(it);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return outputEncoding.encode(CharBuffer.wrap(buffer));
|
return outputEncoding.encode(CharBuffer.wrap(buffer));
|
||||||
|
@ -915,7 +915,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception {
|
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception {
|
||||||
return service.getSubtitleList(files.toArray(new File[0]), languageName);
|
return lookupSubtitleByHash(service, languageName, files, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -940,7 +940,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> fileSet, String languageName, Component parent) throws Exception {
|
protected Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> fileSet, String languageName, Component parent) throws Exception {
|
||||||
return findSubtitleMatches(service, fileSet, languageName, null, true, false);
|
return findSubtitleByName(service, fileSet, languageName, null, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
Reference in New Issue
Block a user