Use AutoDetection for simple -rename calls

This commit is contained in:
Reinhard Pointner 2016-04-07 14:30:05 +00:00
parent 0445df2e0e
commit b7f264928b
1 changed files with 50 additions and 57 deletions

View File

@ -57,6 +57,9 @@ import net.filebot.format.MediaBindingBean;
import net.filebot.hash.HashType;
import net.filebot.hash.VerificationFileReader;
import net.filebot.hash.VerificationFileWriter;
import net.filebot.media.AutoDetection;
import net.filebot.media.AutoDetection.Group;
import net.filebot.media.AutoDetection.Type;
import net.filebot.media.MediaDetection;
import net.filebot.media.XattrMetaInfoProvider;
import net.filebot.similarity.CommonSequenceMatcher;
@ -106,47 +109,43 @@ public class CmdlineOperations implements CmdlineInterface {
return renameSeries(files, action, conflictAction, outputDir, format, getEpisodeListProvider(db), query, SortOrder.forName(sortOrder), filter, locale, strict);
}
if (getMusicIdentificationService(db) != null || containsOnly(files, AUDIO_FILES)) {
if (getMusicIdentificationService(db) != null) {
// music mode
return renameMusic(files, action, conflictAction, outputDir, format, getMusicIdentificationService(db) == null ? AcoustID : getMusicIdentificationService(db));
return renameMusic(files, action, conflictAction, outputDir, format, getMusicIdentificationService(db));
}
if (XattrMetaData.getName().equalsIgnoreCase(db)) {
return renameByMetaData(files, action, conflictAction, outputDir, format, filter, XattrMetaData);
}
// auto-determine mode
List<File> mediaFiles = filter(files, VIDEO_FILES, SUBTITLE_FILES);
double max = mediaFiles.size();
int sxe = 0; // SxE
int cws = 0; // common word sequence
// auto-detect mode for each fileset
AutoDetection auto = new AutoDetection(files, false, locale);
List<File> results = new ArrayList<File>();
Collection<String> cwsList = emptySet();
if (max >= 5) {
cwsList = getSeriesNameMatcher(true).matchAll(mediaFiles.toArray(new File[0]));
}
for (File f : mediaFiles) {
// count SxE matches
if (MediaDetection.getEpisodeIdentifier(f.getName(), true) != null) {
sxe++;
}
// count CWS matches
for (String base : cwsList) {
if (base.equalsIgnoreCase(getSeriesNameMatcher(true).matchByFirstCommonWordSequence(base, f.getName()))) {
cws++;
break;
for (Entry<Group, Set<File>> it : auto.group().entrySet()) {
if (it.getKey().values().stream().filter(Objects::nonNull).count() == 1) {
for (Type key : it.getKey().keySet()) {
switch (key) {
case Movie:
results.addAll(renameMovie(it.getValue(), action, conflictAction, outputDir, format, TheMovieDB, query, filter, locale, strict));
break;
case Series:
results.addAll(renameSeries(it.getValue(), action, conflictAction, outputDir, format, TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict));
break;
case Anime:
results.addAll(renameSeries(it.getValue(), action, conflictAction, outputDir, format, AniDB, query, SortOrder.forName(sortOrder), filter, locale, strict));
break;
case Music:
results.addAll(renameMusic(it.getValue(), action, conflictAction, outputDir, format, MediaInfoID3, AcoustID));
break;
}
}
} else {
debug.warning(format("Failed to process group: %s => %s", it.getKey(), it.getValue()));
}
}
log.finest(format("Filename pattern: [%.02f] SxE, [%.02f] CWS", sxe / max, cws / max));
if (sxe > (max * 0.65) || cws > (max * 0.65)) {
return renameSeries(files, action, conflictAction, outputDir, format, TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict); // use default episode db
} else {
return renameMovie(files, action, conflictAction, outputDir, format, TheMovieDB, query, filter, locale, strict); // use default movie db
}
return results;
}
@Override
@ -220,7 +219,7 @@ public class CmdlineOperations implements CmdlineInterface {
}
if (matches.isEmpty()) {
throw new CmdlineException("Unable to match files to episode data");
throw new CmdlineException("Failed to match files to episode data");
}
// handle derived files
@ -392,7 +391,7 @@ public class CmdlineOperations implements CmdlineInterface {
List<Movie> results = service.searchMovie(query, locale);
List<Movie> validResults = applyExpressionFilter(results, filter);
if (validResults.isEmpty()) {
throw new CmdlineException("Unable to find a valid match: " + results);
throw new CmdlineException("Failed to find a valid match: " + results);
}
// force all mappings
@ -502,16 +501,22 @@ public class CmdlineOperations implements CmdlineInterface {
return renameAll(renameMap, renameAction, conflictAction, matches);
}
public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MusicIdentificationService service) throws Exception {
log.config(format("Rename music using [%s]", service.getName()));
public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MusicIdentificationService... services) throws Exception {
List<File> audioFiles = sortByUniquePath(filter(files, AUDIO_FILES, VIDEO_FILES));
// check audio files against acoustid
// check audio files against all services if necessary
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
for (Entry<File, AudioTrack> it : service.lookup(audioFiles).entrySet()) {
if (it.getKey() != null && it.getValue() != null) {
matches.add(new Match<File, AudioTrack>(it.getKey(), it.getValue().clone()));
}
LinkedHashSet<File> remaining = new LinkedHashSet<File>(audioFiles);
// check audio files against all services
for (int i = 0; i < services.length && remaining.size() > 0; i++) {
log.config(format("Rename music using %s", services[i]));
services[i].lookup(remaining).forEach((file, music) -> {
if (music != null) {
matches.add(new Match<File, AudioTrack>(file, music.clone()));
remaining.remove(file);
}
});
}
// map old files to new paths by applying formatting and validating filenames
@ -519,20 +524,14 @@ public class CmdlineOperations implements CmdlineInterface {
for (Match<File, ?> it : matches) {
File file = it.getValue();
AudioTrack music = (AudioTrack) it.getCandidate();
String newName = (format != null) ? format.format(new MediaBindingBean(music, file, getContext(matches))) : validateFileName(music.toString());
Object music = it.getCandidate();
String path = format != null ? format.format(new MediaBindingBean(music, file, getContext(matches))) : validateFileName(music.toString());
renameMap.put(file, getDestinationFile(file, newName, outputDir));
renameMap.put(file, getDestinationFile(file, path, outputDir));
}
// error logging
if (renameMap.size() != audioFiles.size()) {
for (File f : audioFiles) {
if (!renameMap.containsKey(f)) {
log.warning(format("Unable to lookup %s: %s", service.getName(), f.getName()));
}
}
}
remaining.forEach(f -> log.warning(format("Failed to process music file: %s", f)));
// rename movies
return renameAll(renameMap, renameAction, conflictAction, null);
@ -558,18 +557,12 @@ public class CmdlineOperations implements CmdlineInterface {
return renameAll(renameMap, renameAction, conflictAction, null);
}
private Map<File, Object> getContext(final Collection<Match<File, ?>> matches) {
private Map<File, Object> getContext(List<Match<File, ?>> matches) {
return new AbstractMap<File, Object>() {
@Override
public Set<Entry<File, Object>> entrySet() {
Set<Entry<File, Object>> context = new LinkedHashSet<Entry<File, Object>>();
for (Match<File, ?> it : matches) {
if (it.getValue() != null && it.getCandidate() != null) {
context.add(new SimpleImmutableEntry<File, Object>(it.getValue(), it.getCandidate()));
}
}
return context;
return matches.stream().collect(toMap(it -> it.getValue(), it -> (Object) it.getCandidate())).entrySet();
}
};
}
@ -593,7 +586,7 @@ public class CmdlineOperations implements CmdlineInterface {
public List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction, ConflictAction conflictAction, List<Match<File, ?>> matches) throws Exception {
if (renameMap.isEmpty()) {
throw new CmdlineException("Unable to identify or process any files");
throw new CmdlineException("Failed to identify or process any files");
}
// rename files