* optimize subtitle lookup
This commit is contained in:
parent
a8b28ac8cd
commit
0ebf4b0a45
|
@ -7,6 +7,7 @@ import static net.filebot.media.MediaDetection.*;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -211,12 +212,17 @@ public final class WebServices {
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<SearchResult> search(final String query) throws Exception {
|
||||
Callable<List<? extends SearchResult>> seriesSearch = () -> seriesIndex.search(query, Locale.ENGLISH);
|
||||
Callable<List<? extends SearchResult>> movieSearch = () -> movieIndex.searchMovie(query, Locale.ENGLISH);
|
||||
public synchronized List<SearchResult> search(final String query, final boolean byMovie, final boolean bySeries) throws Exception {
|
||||
List<Callable<List<? extends SearchResult>>> queries = new ArrayList<>(2);
|
||||
if (byMovie) {
|
||||
queries.add(() -> movieIndex.searchMovie(query, Locale.ENGLISH));
|
||||
}
|
||||
if (bySeries) {
|
||||
queries.add(() -> seriesIndex.search(query, Locale.ENGLISH));
|
||||
}
|
||||
|
||||
Set<SearchResult> results = new LinkedHashSet<SearchResult>();
|
||||
for (Future<List<? extends SearchResult>> resultSet : requestThreadPool.invokeAll(asList(seriesSearch, movieSearch))) {
|
||||
for (Future<List<? extends SearchResult>> resultSet : requestThreadPool.invokeAll(queries)) {
|
||||
try {
|
||||
results.addAll(resultSet.get());
|
||||
} catch (ExecutionException e) {
|
||||
|
|
|
@ -65,14 +65,18 @@ public final class SubtitleUtilities {
|
|||
throw new InterruptedException();
|
||||
|
||||
// auto-detect query and search for subtitles
|
||||
boolean searchByMovie = false, searchBySeries = false;
|
||||
Collection<String> querySet = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
|
||||
List<File> files = bySeries.getValue();
|
||||
|
||||
if (forceQuery != null && forceQuery.length() > 0) {
|
||||
querySet.add(forceQuery);
|
||||
searchByMovie = true;
|
||||
searchBySeries = true;
|
||||
} else if (bySeries.getKey().length() > 0) {
|
||||
// use auto-detected series name as query
|
||||
querySet.add(bySeries.getKey());
|
||||
searchBySeries = true;
|
||||
} else {
|
||||
for (File f : files) {
|
||||
List<String> queries = new ArrayList<String>();
|
||||
|
@ -88,11 +92,18 @@ public final class SubtitleUtilities {
|
|||
queries.add(stripReleaseInfo(getName(f)));
|
||||
}
|
||||
|
||||
querySet.addAll(queries);
|
||||
if (queries.size() > 0) {
|
||||
querySet.addAll(queries);
|
||||
searchByMovie = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<SubtitleDescriptor> subtitles = findSubtitles(service, querySet, languageName);
|
||||
if (!searchByMovie && !searchBySeries)
|
||||
continue;
|
||||
|
||||
// search for subtitles online using the auto-detected or forced query information
|
||||
Set<SubtitleDescriptor> subtitles = findSubtitles(service, querySet, searchByMovie, searchBySeries, languageName);
|
||||
|
||||
// allow early abort
|
||||
if (Thread.interrupted())
|
||||
|
@ -175,13 +186,13 @@ public final class SubtitleUtilities {
|
|||
return subtitleByVideo;
|
||||
}
|
||||
|
||||
public static Set<SubtitleDescriptor> findSubtitles(SubtitleProvider service, Collection<String> querySet, String languageName) throws Exception {
|
||||
public static Set<SubtitleDescriptor> findSubtitles(SubtitleProvider service, Collection<String> querySet, boolean searchByMovie, boolean searchBySeries, String languageName) throws Exception {
|
||||
Set<SubtitleDescriptor> subtitles = new LinkedHashSet<SubtitleDescriptor>();
|
||||
|
||||
// search for and automatically select movie / show entry
|
||||
Set<SearchResult> resultSet = new HashSet<SearchResult>();
|
||||
for (String query : querySet) {
|
||||
resultSet.addAll(findProbableSearchResults(query, service.search(query), querySet.size() == 1 ? 4 : 2));
|
||||
resultSet.addAll(findProbableSearchResults(query, service.search(query, searchByMovie, searchBySeries), querySet.size() == 1 ? 4 : 2));
|
||||
}
|
||||
|
||||
// fetch subtitles for all search results
|
||||
|
|
|
@ -51,6 +51,7 @@ import javax.swing.JOptionPane;
|
|||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.SwingWorker.StateValue;
|
||||
import javax.swing.border.Border;
|
||||
|
@ -169,7 +170,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
}
|
||||
|
||||
protected void addSubtitleService(final SubtitleServiceBean service, final JPanel servicePanel) {
|
||||
final LinkButton component = new LinkButton(service.getName(), null, ResourceManager.getIcon("database"), service.getLink());
|
||||
final LinkButton component = new LinkButton(service.getDescription(), null, ResourceManager.getIcon("database"), service.getLink());
|
||||
component.setBorder(BorderFactory.createEmptyBorder());
|
||||
component.setVisible(false);
|
||||
|
||||
|
@ -184,7 +185,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
}
|
||||
|
||||
component.setVisible(true);
|
||||
component.setToolTipText(service.getError() == null ? null : service.getError().getMessage());
|
||||
component.setToolTipText(String.format("%s: %s", service.getName(), service.getError() == null ? service.getState().toString().toLowerCase() : service.getError().getMessage()));
|
||||
servicePanel.setVisible(true);
|
||||
servicePanel.getParent().revalidate();
|
||||
}
|
||||
|
@ -216,6 +217,11 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
SwingUtilities.invokeLater(() -> mappingModel.fireTableStructureChanged()); // make sure UI is refershed after completion
|
||||
}
|
||||
};
|
||||
|
||||
queryService = Executors.newFixedThreadPool(1);
|
||||
|
@ -842,7 +848,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
private final URI link;
|
||||
|
||||
private StateValue state = StateValue.PENDING;
|
||||
private Throwable error = null;
|
||||
private Exception error = null;
|
||||
|
||||
public SubtitleServiceBean(String name, Icon icon, URI link) {
|
||||
this.name = name;
|
||||
|
@ -862,6 +868,8 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
return link;
|
||||
}
|
||||
|
||||
public abstract String getDescription();
|
||||
|
||||
public abstract float getMatchProbabilty(File videoFile, SubtitleDescriptor descriptor);
|
||||
|
||||
protected abstract Map<File, List<SubtitleDescriptor>> getSubtitleList(Collection<File> files, String languageName, Component parent) throws Exception;
|
||||
|
@ -872,11 +880,7 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
try {
|
||||
return getSubtitleList(files, languageName, parent);
|
||||
} catch (Exception e) {
|
||||
// remember error
|
||||
error = e;
|
||||
|
||||
// rethrow error
|
||||
throw e;
|
||||
throw (error = e);
|
||||
} finally {
|
||||
setState(StateValue.DONE);
|
||||
}
|
||||
|
@ -906,8 +910,8 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("%s [via hash]", service.getName());
|
||||
public String getDescription() {
|
||||
return "Exact Search";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -923,18 +927,16 @@ class SubtitleAutoMatchDialog extends JDialog {
|
|||
|
||||
protected static class SubtitleProviderBean extends SubtitleServiceBean {
|
||||
|
||||
private SubtitleAutoMatchDialog inputProvider;
|
||||
private SubtitleProvider service;
|
||||
|
||||
public SubtitleProviderBean(SubtitleProvider service, SubtitleAutoMatchDialog inputProvider) {
|
||||
super(service.getName(), service.getIcon(), service.getLink());
|
||||
this.service = service;
|
||||
this.inputProvider = inputProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return String.format("%s [via name]", service.getName());
|
||||
public String getDescription() {
|
||||
return "Fuzzy Search";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -214,7 +214,7 @@ public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, Subtitl
|
|||
|
||||
@Override
|
||||
public Collection<SearchResult> search() throws Exception {
|
||||
return request.getProvider().search(request.getSearchText());
|
||||
return request.getProvider().search(request.getSearchText(), true, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -90,8 +90,8 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS
|
|||
}
|
||||
|
||||
@Override
|
||||
public synchronized List<SearchResult> search(String query) throws Exception {
|
||||
throw new UnsupportedOperationException("SearchMoviesOnIMDB is not allowed due to abuse");
|
||||
public synchronized List<SearchResult> search(String query, boolean byMovie, boolean bySeries) throws Exception {
|
||||
throw new UnsupportedOperationException(); // XMLRPC::SearchMoviesOnIMDB is not allowed due to abuse
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -486,7 +486,7 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS
|
|||
if (data.length < 256) {
|
||||
throw new IllegalArgumentException("data is not enough");
|
||||
}
|
||||
|
||||
|
||||
String language = getCache().getData("detectLanguage", md5(data), Locale.ROOT, String.class);
|
||||
if (language != null) {
|
||||
return language.isEmpty() ? null : new Locale(language);
|
||||
|
@ -497,9 +497,9 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS
|
|||
|
||||
// detect language
|
||||
List<String> languages = xmlrpc.detectLanguage(data);
|
||||
|
||||
|
||||
// return first language
|
||||
language = languages.size() > 0 ? languages.get(0) : "";
|
||||
language = languages.size() > 0 ? languages.get(0) : "";
|
||||
getCache().putData("detectLanguage", md5(data), Locale.ROOT, language);
|
||||
return new Locale(language);
|
||||
}
|
||||
|
|
|
@ -1,30 +1,22 @@
|
|||
|
||||
package net.filebot.web;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
|
||||
public interface SubtitleProvider {
|
||||
|
||||
public List<SearchResult> search(String query) throws Exception;
|
||||
|
||||
|
||||
public List<SearchResult> search(String query, boolean byMovie, boolean bySeries) throws Exception;
|
||||
|
||||
public List<SubtitleDescriptor> getSubtitleList(SearchResult searchResult, String languageName) throws Exception;
|
||||
|
||||
|
||||
public URI getSubtitleListLink(SearchResult searchResult, String languageName);
|
||||
|
||||
|
||||
public String getName();
|
||||
|
||||
|
||||
public URI getLink();
|
||||
|
||||
|
||||
public Icon getIcon();
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue