mirror of
https://github.com/mitb-archive/filebot
synced 2024-08-13 17:03:45 -04:00
Refactor common media characteristics (e.g. to use ffprobe instead of libmediainfo internally for various use cases)
This commit is contained in:
parent
82557248d4
commit
e8ca45789c
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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()));
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user