1
0
mirror of https://github.com/mitb-archive/filebot synced 2024-12-22 07:48:52 -05:00

Fix mediaInfo / inferredMediaFile bottleneck

This commit is contained in:
Reinhard Pointner 2019-05-24 01:13:08 +07:00
parent 93095dd9f4
commit 996701aec3

View File

@ -1144,50 +1144,6 @@ public class MediaBindingBean {
return new FFProbe().open(getInferredMediaFile());
}
public File getInferredMediaFile() {
File file = getMediaFile();
if (file.isDirectory()) {
// just select the first video file in the folder as media sample
List<File> videos = getChildren(file, VIDEO_FILES, HUMAN_NAME_ORDER);
if (videos.isEmpty()) {
// check for indirect descendant video files as well
videos = listFiles(file, VIDEO_FILES, HUMAN_NAME_ORDER);
}
if (videos.size() > 0) {
return videos.get(0);
}
} else if ((SUBTITLE_FILES.accept(file) || IMAGE_FILES.accept(file)) || ((infoObject instanceof Episode || infoObject instanceof Movie) && !VIDEO_FILES.accept(file))) {
// prefer equal match from current context if possible
if (context != null) {
for (Entry<File, ?> it : context.entrySet()) {
if (infoObject.equals(it.getValue()) && VIDEO_FILES.accept(it.getKey())) {
return it.getKey();
}
}
}
// file is a subtitle, or nfo, etc
String baseName = stripReleaseInfo(FileUtilities.getName(file)).toLowerCase();
List<File> videos = getChildren(file.getParentFile(), VIDEO_FILES);
// find corresponding movie file
for (File movieFile : videos) {
if (!baseName.isEmpty() && stripReleaseInfo(FileUtilities.getName(movieFile)).toLowerCase().startsWith(baseName)) {
return movieFile;
}
}
// still no good match found -> just take the most probable video from the same folder
if (videos.size() > 0) {
sort(videos, SimilarityComparator.compareTo(FileUtilities.getName(file), FileUtilities::getName));
return videos.get(0);
}
}
return file;
}
public Episode getSeasonEpisode() {
// magically convert AniDB absolute numbers to TheTVDB SxE numbers if AniDB is selected with airdate SxE episode sort order
if (getEpisodes().stream().allMatch(it -> isAnime(it) && isRegular(it) && !isAbsolute(it))) {
@ -1242,13 +1198,13 @@ public class MediaBindingBean {
return null;
}
private static final Cache<File, MediaInfo> mediaInfoCache = Caffeine.newBuilder().expireAfterAccess(20, TimeUnit.MINUTES).build();
// lazy initialize and then keep in memory
private MediaInfo mediaInfo;
private synchronized MediaInfo getMediaInfo() {
// use inferred media file (e.g. actual movie file instead of subtitle file)
File inferredMediaFile = getInferredMediaFile();
return mediaInfoCache.get(inferredMediaFile, f -> {
if (mediaInfo == null) {
mediaInfo = mediaInfoCache.get(getInferredMediaFile(), f -> {
try {
return new MediaInfo().open(f);
} catch (Exception e) {
@ -1256,6 +1212,60 @@ public class MediaBindingBean {
}
});
}
return mediaInfo;
}
// lazy initialize and then keep in memory
private File inferredMediaFile;
private synchronized File getInferredMediaFile() {
if (inferredMediaFile == null) {
inferredMediaFile = getInferredMediaFile(getMediaFile());
}
return inferredMediaFile;
}
private File getInferredMediaFile(File file) {
if (file.isDirectory()) {
// just select the first video file in the folder as media sample
List<File> videos = getChildren(file, VIDEO_FILES, HUMAN_NAME_ORDER);
if (videos.isEmpty()) {
// check for indirect descendant video files as well
videos = listFiles(file, VIDEO_FILES, HUMAN_NAME_ORDER);
}
if (videos.size() > 0) {
return videos.get(0);
}
} else if ((SUBTITLE_FILES.accept(file) || IMAGE_FILES.accept(file)) || ((infoObject instanceof Episode || infoObject instanceof Movie) && !VIDEO_FILES.accept(file))) {
// prefer equal match from current context if possible
if (context != null) {
for (Entry<File, ?> it : context.entrySet()) {
if (infoObject.equals(it.getValue()) && VIDEO_FILES.accept(it.getKey())) {
return it.getKey();
}
}
}
// file is a subtitle, or nfo, etc
String baseName = stripReleaseInfo(FileUtilities.getName(file)).toLowerCase();
List<File> videos = getChildren(file.getParentFile(), VIDEO_FILES);
// find corresponding movie file
for (File movieFile : videos) {
if (!baseName.isEmpty() && stripReleaseInfo(FileUtilities.getName(movieFile)).toLowerCase().startsWith(baseName)) {
return movieFile;
}
}
// still no good match found -> just take the most probable video from the same folder
if (videos.size() > 0) {
sort(videos, SimilarityComparator.compareTo(FileUtilities.getName(file), FileUtilities::getName));
return videos.get(0);
}
}
return file;
}
private Integer identityIndexOf(Iterable<?> c, Object o) {
Iterator<?> itr = c.iterator();
@ -1380,4 +1390,9 @@ public class MediaBindingBean {
public static final String EXCEPTION_UNDEFINED = "undefined";
public static final String EXCEPTION_SAMPLE_FILE_NOT_SET = "Sample file has not been set. Click \"Change Sample\" to select a sample file.";
/**
* Reading MediaInfo can be a very expensive operation, especially if network drives are involved, so we do our best to cache it for a while, because memory is cheap, and time is not.
*/
private static final Cache<File, MediaInfo> mediaInfoCache = Caffeine.newBuilder().expireAfterAccess(20, TimeUnit.MINUTES).build();
}