Refactor common media characteristics (e.g. to use ffprobe instead of libmediainfo internally for various use cases)

This commit is contained in:
Reinhard Pointner 2018-06-03 19:45:17 +07:00
parent 82557248d4
commit e8ca45789c
7 changed files with 68 additions and 32 deletions

View File

@ -17,7 +17,6 @@ import static net.filebot.util.StringUtilities.*;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
@ -36,7 +35,6 @@ import java.util.regex.Pattern;
import java.util.stream.Stream; import java.util.stream.Stream;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.similarity.NameSimilarityMetric; import net.filebot.similarity.NameSimilarityMetric;
import net.filebot.util.FastFile; import net.filebot.util.FastFile;
import net.filebot.web.Episode; import net.filebot.web.Episode;
@ -118,9 +116,8 @@ public class AutoDetection {
if (VIDEO_FILES.accept(f) && f.length() > ONE_MEGABYTE) { if (VIDEO_FILES.accept(f) && f.length() > ONE_MEGABYTE) {
// check for Japanese audio or characteristic subtitles // check for Japanese audio or characteristic subtitles
try (MediaInfo mi = new MediaInfo().open(f)) { try (MediaCharacteristics mi = new MediaInfo().open(f)) {
long minutes = Duration.ofMillis(Long.parseLong(mi.get(StreamKind.General, 0, "Duration"))).toMinutes(); return mi.getDuration().toMinutes() < 60 || mi.getAudioLanguage().contains("Japanese") && mi.getSubtitleCodec().contains("ASS");
return minutes < 60 || mi.get(StreamKind.General, 0, "AudioLanguageList").contains("Japanese") && mi.get(StreamKind.General, 0, "TextCodecList").contains("ASS");
} catch (Exception e) { } catch (Exception e) {
debug.warning("Failed to read audio language: " + e.getMessage()); debug.warning("Failed to read audio language: " + e.getMessage());
} }

View File

@ -2,16 +2,22 @@ package net.filebot.media;
import java.time.Duration; import java.time.Duration;
public interface MediaCharacteristics { public interface MediaCharacteristics extends AutoCloseable {
String getVideoCodec(); String getVideoCodec();
String getAudioCodec();
String getAudioLanguage(); String getAudioLanguage();
String getSubtitleCodec(); String getSubtitleCodec();
Duration getDuration(); Duration getDuration();
float getFrameRate(); Integer getWidth();
Integer getHeight();
Float getFrameRate();
} }

View File

@ -17,7 +17,6 @@ import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.io.IOException; import java.io.IOException;
import java.text.CollationKey; import java.text.CollationKey;
import java.time.Duration;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -50,7 +49,6 @@ import net.filebot.Resource;
import net.filebot.WebServices; import net.filebot.WebServices;
import net.filebot.archive.Archive; import net.filebot.archive.Archive;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.similarity.DateMatcher; import net.filebot.similarity.DateMatcher;
import net.filebot.similarity.EpisodeMetrics; import net.filebot.similarity.EpisodeMetrics;
import net.filebot.similarity.MetricAvg; import net.filebot.similarity.MetricAvg;
@ -1117,12 +1115,12 @@ public class MediaDetection {
filesByExtension.stream().collect(groupingBy(f -> { filesByExtension.stream().collect(groupingBy(f -> {
if (VIDEO_FILES.accept(f) && f.length() > ONE_MEGABYTE) { if (VIDEO_FILES.accept(f) && f.length() > ONE_MEGABYTE) {
try (MediaInfo mi = new MediaInfo().open(f)) { try (MediaCharacteristics mi = new MediaInfo().open(f)) {
Object d = Duration.ofMillis(Long.parseLong(mi.get(StreamKind.General, 0, "Duration"))).toMinutes() < 10 ? ChronoUnit.MINUTES : ChronoUnit.HOURS; ChronoUnit d = mi.getDuration().toMinutes() < 10 ? ChronoUnit.MINUTES : ChronoUnit.HOURS;
String v = mi.get(StreamKind.Video, 0, "CodecID"); String v = mi.getVideoCodec();
String a = mi.get(StreamKind.Audio, 0, "CodecID"); String a = mi.getAudioCodec();
String w = mi.get(StreamKind.Video, 0, "Width"); Integer w = mi.getWidth();
String h = mi.get(StreamKind.Video, 0, "Height"); Integer h = mi.getHeight();
return asList(d, v, a, w, h); return asList(d, v, a, w, h);
} catch (Exception e) { } catch (Exception e) {
debug.warning(format("Failed to read media characteristics: %s", e.getMessage())); debug.warning(format("Failed to read media characteristics: %s", e.getMessage()));

View File

@ -6,7 +6,6 @@ import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind;
public class MediaDurationFilter implements FileFilter { public class MediaDurationFilter implements FileFilter {
@ -25,11 +24,8 @@ public class MediaDurationFilter implements FileFilter {
} }
public long getDuration(File f) { public long getDuration(File f) {
try (MediaInfo mi = new MediaInfo().open(f)) { try (MediaCharacteristics mi = new MediaInfo().open(f)) {
String duration = mi.get(StreamKind.General, 0, "Duration"); return mi.getDuration().toMillis();
if (duration.length() > 0) {
return Long.parseLong(duration);
}
} catch (Exception e) { } catch (Exception e) {
debug.warning(format("Failed to read video duration: %s", e.getMessage())); debug.warning(format("Failed to read video duration: %s", e.getMessage()));
} }

View File

@ -5,11 +5,11 @@ import static java.util.stream.Collectors.*;
import static net.filebot.Logging.*; import static net.filebot.Logging.*;
import static net.filebot.util.RegularExpressions.*; import static net.filebot.util.RegularExpressions.*;
import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import java.lang.ref.Cleaner; import java.lang.ref.Cleaner;
import java.time.Duration;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -22,8 +22,9 @@ import com.sun.jna.Pointer;
import com.sun.jna.WString; import com.sun.jna.WString;
import net.filebot.media.ImageMetadata; import net.filebot.media.ImageMetadata;
import net.filebot.media.MediaCharacteristics;
public class MediaInfo implements Closeable { public class MediaInfo implements MediaCharacteristics {
private Pointer handle; private Pointer handle;
private Cleaner.Cleanable cleanable; private Cleaner.Cleanable cleanable;
@ -138,6 +139,46 @@ public class MediaInfo implements Closeable {
return MediaInfoLibrary.INSTANCE.Count_Get(handle, streamKind.ordinal(), streamNumber); return MediaInfoLibrary.INSTANCE.Count_Get(handle, streamKind.ordinal(), streamNumber);
} }
@Override
public String getVideoCodec() {
return get(StreamKind.Video, 0, "CodecID");
}
@Override
public String getAudioCodec() {
return get(StreamKind.Audio, 0, "CodecID");
}
@Override
public String getAudioLanguage() {
return get(StreamKind.General, 0, "AudioLanguageList");
}
@Override
public String getSubtitleCodec() {
return get(StreamKind.General, 0, "TextCodecList");
}
@Override
public Duration getDuration() {
return Duration.ofMillis(Long.parseLong(get(StreamKind.General, 0, "Duration")));
}
@Override
public Integer getWidth() {
return Integer.parseInt(get(StreamKind.Video, 0, "Width"));
}
@Override
public Integer getHeight() {
return Integer.parseInt(get(StreamKind.Video, 0, "Height"));
}
@Override
public Float getFrameRate() {
return Float.parseFloat(get(StreamKind.Video, 0, "FrameRate"));
}
public Map<StreamKind, List<Map<String, String>>> snapshot() { public Map<StreamKind, List<Map<String, String>>> snapshot() {
Map<StreamKind, List<Map<String, String>>> mediaInfo = new EnumMap<StreamKind, List<Map<String, String>>>(StreamKind.class); Map<StreamKind, List<Map<String, String>>> mediaInfo = new EnumMap<StreamKind, List<Map<String, String>>>(StreamKind.class);

View File

@ -15,8 +15,8 @@ import java.util.WeakHashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import net.filebot.media.MediaCharacteristics;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.similarity.CrossPropertyMetric; import net.filebot.similarity.CrossPropertyMetric;
import net.filebot.similarity.EpisodeMetrics; import net.filebot.similarity.EpisodeMetrics;
import net.filebot.similarity.MetricAvg; import net.filebot.similarity.MetricAvg;
@ -185,10 +185,8 @@ public enum SubtitleMetrics implements SimilarityMetric {
private Map<String, Object> getVideoProperties(File file) { private Map<String, Object> getVideoProperties(File file) {
return mediaInfoCache.computeIfAbsent(file, key -> { return mediaInfoCache.computeIfAbsent(file, key -> {
try (MediaInfo mi = new MediaInfo().open(file)) { try (MediaCharacteristics mi = new MediaInfo().open(file)) {
float fps = Float.parseFloat(mi.get(StreamKind.Video, 0, "FrameRate")); return getProperties(mi.getFrameRate(), mi.getDuration().toMillis());
long millis = Long.parseLong(mi.get(StreamKind.Video, 0, "Duration"));
return getProperties(fps, millis);
} catch (Exception e) { } catch (Exception e) {
debug.warning("Failed to read video properties: " + e.getMessage()); debug.warning("Failed to read video properties: " + e.getMessage());
} }

View File

@ -28,9 +28,9 @@ import net.filebot.Cache;
import net.filebot.Cache.TypedCache; import net.filebot.Cache.TypedCache;
import net.filebot.CacheType; import net.filebot.CacheType;
import net.filebot.ResourceManager; import net.filebot.ResourceManager;
import net.filebot.media.MediaCharacteristics;
import net.filebot.media.MediaDetection; import net.filebot.media.MediaDetection;
import net.filebot.mediainfo.MediaInfo; import net.filebot.mediainfo.MediaInfo;
import net.filebot.mediainfo.MediaInfo.StreamKind;
import net.filebot.util.ExceptionUtilities; import net.filebot.util.ExceptionUtilities;
import net.filebot.util.Timer; import net.filebot.util.Timer;
import net.filebot.web.OpenSubtitlesXmlRpc.BaseInfo; import net.filebot.web.OpenSubtitlesXmlRpc.BaseInfo;
@ -312,9 +312,9 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS
sub.setSubContent(readFile(subtitleFile)); sub.setSubContent(readFile(subtitleFile));
} }
try (MediaInfo mi = new MediaInfo().open(videoFile)) { try (MediaCharacteristics mi = new MediaInfo().open(videoFile)) {
sub.setMovieFPS(mi.get(StreamKind.Video, 0, "FrameRate")); sub.setMovieFPS(String.valueOf(mi.getFrameRate()));
sub.setMovieTimeMS(mi.get(StreamKind.General, 0, "Duration")); sub.setMovieTimeMS(String.valueOf(mi.getDuration().toMillis()));
} catch (Throwable e) { } catch (Throwable e) {
debug.log(Level.SEVERE, "Failed to read media info", e); debug.log(Level.SEVERE, "Failed to read media info", e);
} }