mirror of
https://github.com/mitb-archive/filebot
synced 2025-01-11 05:48:01 -05:00
Use AutoDetection for simple -rename calls
This commit is contained in:
parent
0445df2e0e
commit
b7f264928b
@ -57,6 +57,9 @@ import net.filebot.format.MediaBindingBean;
|
|||||||
import net.filebot.hash.HashType;
|
import net.filebot.hash.HashType;
|
||||||
import net.filebot.hash.VerificationFileReader;
|
import net.filebot.hash.VerificationFileReader;
|
||||||
import net.filebot.hash.VerificationFileWriter;
|
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.MediaDetection;
|
||||||
import net.filebot.media.XattrMetaInfoProvider;
|
import net.filebot.media.XattrMetaInfoProvider;
|
||||||
import net.filebot.similarity.CommonSequenceMatcher;
|
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);
|
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
|
// 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)) {
|
if (XattrMetaData.getName().equalsIgnoreCase(db)) {
|
||||||
return renameByMetaData(files, action, conflictAction, outputDir, format, filter, XattrMetaData);
|
return renameByMetaData(files, action, conflictAction, outputDir, format, filter, XattrMetaData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto-determine mode
|
// auto-detect mode for each fileset
|
||||||
List<File> mediaFiles = filter(files, VIDEO_FILES, SUBTITLE_FILES);
|
AutoDetection auto = new AutoDetection(files, false, locale);
|
||||||
double max = mediaFiles.size();
|
List<File> results = new ArrayList<File>();
|
||||||
int sxe = 0; // SxE
|
|
||||||
int cws = 0; // common word sequence
|
|
||||||
|
|
||||||
Collection<String> cwsList = emptySet();
|
for (Entry<Group, Set<File>> it : auto.group().entrySet()) {
|
||||||
if (max >= 5) {
|
if (it.getKey().values().stream().filter(Objects::nonNull).count() == 1) {
|
||||||
cwsList = getSeriesNameMatcher(true).matchAll(mediaFiles.toArray(new File[0]));
|
for (Type key : it.getKey().keySet()) {
|
||||||
}
|
switch (key) {
|
||||||
|
case Movie:
|
||||||
for (File f : mediaFiles) {
|
results.addAll(renameMovie(it.getValue(), action, conflictAction, outputDir, format, TheMovieDB, query, filter, locale, strict));
|
||||||
// count SxE matches
|
break;
|
||||||
if (MediaDetection.getEpisodeIdentifier(f.getName(), true) != null) {
|
case Series:
|
||||||
sxe++;
|
results.addAll(renameSeries(it.getValue(), action, conflictAction, outputDir, format, TheTVDB, query, SortOrder.forName(sortOrder), filter, locale, strict));
|
||||||
}
|
break;
|
||||||
|
case Anime:
|
||||||
// count CWS matches
|
results.addAll(renameSeries(it.getValue(), action, conflictAction, outputDir, format, AniDB, query, SortOrder.forName(sortOrder), filter, locale, strict));
|
||||||
for (String base : cwsList) {
|
break;
|
||||||
if (base.equalsIgnoreCase(getSeriesNameMatcher(true).matchByFirstCommonWordSequence(base, f.getName()))) {
|
case Music:
|
||||||
cws++;
|
results.addAll(renameMusic(it.getValue(), action, conflictAction, outputDir, format, MediaInfoID3, AcoustID));
|
||||||
break;
|
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));
|
return results;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -220,7 +219,7 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (matches.isEmpty()) {
|
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
|
// handle derived files
|
||||||
@ -392,7 +391,7 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
List<Movie> results = service.searchMovie(query, locale);
|
List<Movie> results = service.searchMovie(query, locale);
|
||||||
List<Movie> validResults = applyExpressionFilter(results, filter);
|
List<Movie> validResults = applyExpressionFilter(results, filter);
|
||||||
if (validResults.isEmpty()) {
|
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
|
// force all mappings
|
||||||
@ -502,16 +501,22 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
return renameAll(renameMap, renameAction, conflictAction, matches);
|
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 {
|
public List<File> renameMusic(Collection<File> files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, MusicIdentificationService... services) throws Exception {
|
||||||
log.config(format("Rename music using [%s]", service.getName()));
|
|
||||||
List<File> audioFiles = sortByUniquePath(filter(files, AUDIO_FILES, VIDEO_FILES));
|
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, ?>>();
|
List<Match<File, ?>> matches = new ArrayList<Match<File, ?>>();
|
||||||
for (Entry<File, AudioTrack> it : service.lookup(audioFiles).entrySet()) {
|
LinkedHashSet<File> remaining = new LinkedHashSet<File>(audioFiles);
|
||||||
if (it.getKey() != null && it.getValue() != null) {
|
|
||||||
matches.add(new Match<File, AudioTrack>(it.getKey(), it.getValue().clone()));
|
// 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
|
// 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) {
|
for (Match<File, ?> it : matches) {
|
||||||
File file = it.getValue();
|
File file = it.getValue();
|
||||||
AudioTrack music = (AudioTrack) it.getCandidate();
|
Object music = it.getCandidate();
|
||||||
String newName = (format != null) ? format.format(new MediaBindingBean(music, file, getContext(matches))) : validateFileName(music.toString());
|
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
|
// error logging
|
||||||
if (renameMap.size() != audioFiles.size()) {
|
remaining.forEach(f -> log.warning(format("Failed to process music file: %s", f)));
|
||||||
for (File f : audioFiles) {
|
|
||||||
if (!renameMap.containsKey(f)) {
|
|
||||||
log.warning(format("Unable to lookup %s: %s", service.getName(), f.getName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rename movies
|
// rename movies
|
||||||
return renameAll(renameMap, renameAction, conflictAction, null);
|
return renameAll(renameMap, renameAction, conflictAction, null);
|
||||||
@ -558,18 +557,12 @@ public class CmdlineOperations implements CmdlineInterface {
|
|||||||
return renameAll(renameMap, renameAction, conflictAction, null);
|
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>() {
|
return new AbstractMap<File, Object>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Entry<File, Object>> entrySet() {
|
public Set<Entry<File, Object>> entrySet() {
|
||||||
Set<Entry<File, Object>> context = new LinkedHashSet<Entry<File, Object>>();
|
return matches.stream().collect(toMap(it -> it.getValue(), it -> (Object) it.getCandidate())).entrySet();
|
||||||
for (Match<File, ?> it : matches) {
|
|
||||||
if (it.getValue() != null && it.getCandidate() != null) {
|
|
||||||
context.add(new SimpleImmutableEntry<File, Object>(it.getValue(), it.getCandidate()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -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 {
|
public List<File> renameAll(Map<File, File> renameMap, RenameAction renameAction, ConflictAction conflictAction, List<Match<File, ?>> matches) throws Exception {
|
||||||
if (renameMap.isEmpty()) {
|
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
|
// rename files
|
||||||
|
Loading…
Reference in New Issue
Block a user