SRT works ; adds support for export/import ass

This commit is contained in:
Guillaume Tâche
2024-08-24 20:52:01 +02:00
parent d14e32bfd0
commit 728b563d8b
37 changed files with 552 additions and 145 deletions

View File

@@ -0,0 +1,33 @@
package com.github.gtache.autosubtitle.archive.impl;
import com.github.gtache.autosubtitle.archive.Archiver;
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Implementation of {@link ArchiverProvider}
*/
public class ArchiverProviderImpl implements ArchiverProvider {
private final Map<String, Archiver> archiverMap;
@Inject
ArchiverProviderImpl(final Map<String, Archiver> archiverMap) {
this.archiverMap = archiverMap.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toUpperCase(), Map.Entry::getValue));
}
@Override
public Collection<Archiver> allArchivers() {
return archiverMap.values();
}
@Override
public Archiver getArchiver(final String extension) {
return archiverMap.get(extension.toUpperCase());
}
}

View File

@@ -0,0 +1,29 @@
package com.github.gtache.autosubtitle.modules.archive.impl;
import com.github.gtache.autosubtitle.archive.Archiver;
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
import com.github.gtache.autosubtitle.archive.impl.ArchiverProviderImpl;
import com.github.gtache.autosubtitle.archive.impl.ZipDecompresser;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
import dagger.multibindings.StringKey;
/**
* Dagger module for Archivers
*/
@Module
public abstract class ArchiveModule {
private ArchiveModule() {
}
@Binds
abstract ArchiverProvider bindsArchiverProvider(ArchiverProviderImpl provider);
@Binds
@StringKey("zip")
@IntoMap
abstract Archiver bindsZipDecompresser(final ZipDecompresser decompresser);
}

View File

@@ -1,17 +1,13 @@
package com.github.gtache.autosubtitle.modules.impl;
import com.github.gtache.autosubtitle.archive.Archiver;
import com.github.gtache.autosubtitle.archive.impl.ZipDecompresser;
import com.github.gtache.autosubtitle.impl.Architecture;
import com.github.gtache.autosubtitle.impl.DaggerException;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.modules.archive.impl.ArchiveModule;
import com.github.gtache.autosubtitle.modules.setup.impl.SetupModule;
import com.github.gtache.autosubtitle.modules.subtitle.impl.SubtitleModule;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoMap;
import dagger.multibindings.StringKey;
import javax.inject.Singleton;
import java.util.prefs.Preferences;
@@ -19,18 +15,13 @@ import java.util.prefs.Preferences;
/**
* Dagger module for Core
*/
@Module(includes = {SetupModule.class, SubtitleModule.class})
@Module(includes = {ArchiveModule.class, SetupModule.class, SubtitleModule.class})
public abstract class CoreModule {
private CoreModule() {
}
@Binds
@StringKey("zip")
@IntoMap
abstract Archiver bindsZipDecompresser(final ZipDecompresser decompresser);
@Provides
static OS providesOS() {
final var os = OS.getOS();
@@ -74,4 +65,16 @@ public abstract class CoreModule {
static int providesMaxLines() {
return 1;
}
@Provides
@FontName
static String providesFontName() {
return "Arial";
}
@Provides
@FontSize
static int providesFontSize() {
return 12;
}
}

View File

@@ -0,0 +1,16 @@
package com.github.gtache.autosubtitle.modules.impl;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
public @interface FontName {
}

View File

@@ -0,0 +1,16 @@
package com.github.gtache.autosubtitle.modules.impl;
import javax.inject.Qualifier;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Qualifier
@Documented
@Retention(RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD, ElementType.FIELD})
public @interface FontSize {
}

View File

@@ -0,0 +1,34 @@
package com.github.gtache.autosubtitle.modules.subtitle.converter.impl;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
import com.github.gtache.autosubtitle.subtitle.converter.impl.ASSSubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.impl.SRTSubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.impl.SubtitleConverterProviderImpl;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
import dagger.multibindings.StringKey;
/**
* Dagger module for the subtitle converters
*/
@Module
public abstract class SubtitleConverterModule {
private SubtitleConverterModule() {
}
@Binds
abstract SubtitleConverterProvider bindsSubtitleConverterProvider(final SubtitleConverterProviderImpl subtitleConverterProvider);
@Binds
@IntoMap
@StringKey("srt")
abstract SubtitleConverter bindsSrtSubtitleConverter(final SRTSubtitleConverter converter);
@Binds
@IntoMap
@StringKey("ass")
abstract SubtitleConverter bindsAssSubtitleConverter(final ASSSubtitleConverter converter);
}

View File

@@ -1,28 +1,20 @@
package com.github.gtache.autosubtitle.modules.subtitle.impl;
import com.github.gtache.autosubtitle.modules.subtitle.converter.impl.SubtitleConverterModule;
import com.github.gtache.autosubtitle.subtitle.SubtitleImporterExporter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.impl.SRTSubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImporterExporterImpl;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
import dagger.multibindings.StringKey;
/**
* Dagger module for subtitles
*/
@Module
@Module(includes = {SubtitleConverterModule.class})
public abstract class SubtitleModule {
private SubtitleModule() {
}
@Binds
@IntoMap
@StringKey("srt")
abstract SubtitleConverter bindsSubtitleConverter(final SRTSubtitleConverter converter);
@Binds
abstract SubtitleImporterExporter bindsSubtitleImporterExporter(final SubtitleImporterExporterImpl impl);
}

View File

@@ -0,0 +1,200 @@
package com.github.gtache.autosubtitle.subtitle.converter.impl;
import com.github.gtache.autosubtitle.VideoInfo;
import com.github.gtache.autosubtitle.modules.impl.FontName;
import com.github.gtache.autosubtitle.modules.impl.FontSize;
import com.github.gtache.autosubtitle.subtitle.Font;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.impl.FontImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
import com.github.gtache.autosubtitle.translation.Translator;
import javax.inject.Inject;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* Converts subtitles to SRT format
*/
public class ASSSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
private static final String STYLE = "Style:";
private static final String FORMAT = "Format:";
private static final String DIALOGUE = "Dialogue:";
private static final String EVENTS_SECTION = "[Events]";
private static final String STYLES_SECTION = "[V4+ Styles]";
private final Translator<?> translator;
private final Preferences preferences;
private final String defaultFontName;
private final int defaultFontSize;
@Inject
ASSSubtitleConverter(final Translator translator, final Preferences preferences,
@FontName final String defaultFontName, @FontSize final int defaultFontSize) {
this.translator = requireNonNull(translator);
this.preferences = requireNonNull(preferences);
this.defaultFontName = Objects.requireNonNull(defaultFontName);
this.defaultFontSize = defaultFontSize;
}
@Override
public String format(final SubtitleCollection<?> collection, final VideoInfo videoInfo) {
final var subtitles = collection.subtitles().stream().sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
final var scriptInfo = getScriptInfo(videoInfo);
final var styles = getStyles(subtitles);
final var events = getEvents(subtitles);
return scriptInfo + "\n\n" + styles + "\n\n" + events;
}
private String getEvents(final Collection<? extends Subtitle> subtitles) {
return EVENTS_SECTION + "\n" + "Format: Start, End, Style, Text\n" +
subtitles.stream().map(this::getEvent).collect(Collectors.joining("\n"));
}
private String getEvent(final Subtitle subtitle) {
return DIALOGUE + " " + formatTime(subtitle.start()) + "," + formatTime(subtitle.end()) + "," + getName(subtitle.font()) + "," + subtitle.content();
}
private String getName(final Font font) {
final String fontName;
final int fontSize;
if (font == null) {
fontName = preferences.get("fontName", defaultFontName);
fontSize = preferences.getInt("fontSize", defaultFontSize);
} else {
fontName = font.name();
fontSize = font.size();
}
return fontName + fontSize;
}
private String getStyles(final Collection<? extends Subtitle> subtitles) {
return STYLES_SECTION + "\n" + "Format: Name, Fontname, Fontsize\n" + listStyles(subtitles);
}
private String listStyles(final Collection<? extends Subtitle> subtitles) {
final var uniqueStyles = subtitles.stream().map(Subtitle::font).filter(Objects::nonNull).collect(Collectors.toSet());
if (subtitles.stream().anyMatch(s -> s.font() == null)) {
uniqueStyles.add(new FontImpl(preferences.get("fontName", defaultFontName), preferences.getInt("fontSize", defaultFontSize)));
}
return uniqueStyles.stream().map(f -> STYLE + " " + getName(f) + ", " + f.name() + ", " + f.size()).collect(Collectors.joining("\n"));
}
private static String getScriptInfo(final VideoInfo videoInfo) {
return """
[Script Info]
PlayResX: %d
PlayResY: %d
WrapStyle: 1""".formatted(videoInfo.width(), videoInfo.height());
}
private static String formatTime(final long time) {
final var millisPerHour = 3600000;
final var millisPerMinute = 60000;
final var hours = time / millisPerHour;
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
final var millis = time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000;
final var hundredths = millis / 10;
return String.format("%d:%02d:%02d.%02d", hours, minutes, seconds, hundredths);
}
@Override
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content) throws ParseException {
final var fonts = parseFonts(content);
final var subtitles = parseSubtitles(content, fonts);
final var text = subtitles.stream().map(Subtitle::content).collect(Collectors.joining());
final var language = translator.getLanguage(text);
return new SubtitleCollectionImpl<>(text, subtitles, language);
}
private static List<SubtitleImpl> parseSubtitles(final String content, final Map<String, Font> fonts) throws ParseException {
final var fontIndex = content.indexOf(EVENTS_SECTION);
if (fontIndex == -1) {
throw new ParseException("Events section not found in " + content);
} else {
final var split = content.substring(fontIndex).split("\\n");
final List<String> fields;
if (split[0].startsWith(EVENTS_SECTION)) {
fields = getFields(split[1]);
} else {
throw new ParseException("Couldn't parse events : " + content);
}
final var startIndex = fields.indexOf("Start");
final var endIndex = fields.indexOf("End");
final var styleIndex = fields.indexOf("Style");
final var textIndex = fields.indexOf("Text");
if (startIndex == -1 || endIndex == -1 || styleIndex == -1 || textIndex == -1) {
throw new ParseException("Couldn't parse events : " + content);
}
return Arrays.stream(split).filter(s -> s.startsWith(DIALOGUE))
.map(s -> {
final var values = Arrays.stream(s.replace(DIALOGUE, "").split(",")).map(String::trim).filter(w -> !w.isBlank()).toList();
final var start = parseTime(values.get(startIndex));
final var end = parseTime(values.get(endIndex));
final var style = values.get(styleIndex);
final var font = fonts.get(style);
final var text = values.stream().skip(textIndex).collect(Collectors.joining(", "));
return new SubtitleImpl(text, start, end, font, null); //TODO pos style overrides
}).toList();
}
}
private Map<String, Font> parseFonts(final String content) throws ParseException {
final var fontIndex = content.indexOf(STYLES_SECTION);
if (fontIndex == -1) {
throw new ParseException("Styles section not found in " + content);
} else {
final var split = content.substring(fontIndex).split("\\n");
final List<String> fields;
if (split[0].startsWith(STYLES_SECTION)) {
fields = getFields(split[1]);
} else {
throw new ParseException("Couldn't parse styles : " + content);
}
final var fontNameIndex = fields.indexOf("Fontname");
final var fontSizeIndex = fields.indexOf("Fontsize");
if (fontNameIndex == -1 || fontSizeIndex == -1) {
throw new ParseException("Couldn't parse styles : " + content);
}
return Arrays.stream(split).filter(s -> s.startsWith(STYLE))
.map(s -> {
final var values = Arrays.stream(s.replace(STYLE, "").split(",")).map(String::trim).filter(w -> !w.isBlank()).toList();
final var name = values.get(fontNameIndex);
final var size = Integer.parseInt(values.get(fontSizeIndex));
return new FontImpl(name, size);
}).collect(Collectors.toMap(this::getName, f -> f));
}
}
private static List<String> getFields(final String string) {
return Arrays.stream(string.replace(FORMAT, "").split(",")).map(String::trim).filter(s -> !s.isBlank()).toList();
}
private static long parseTime(final String timeStr) {
final var split = timeStr.split(":");
final var hours = Integer.parseInt(split[0]);
final var minutes = Integer.parseInt(split[1]);
final var secondsSplit = split[2].split("\\.");
final var seconds = Integer.parseInt(secondsSplit[0]);
final var hundredths = Integer.parseInt(secondsSplit[1]);
return (hours * 3600L + minutes * 60L + seconds) * 1000L + hundredths * 10L;
}
@Override
public String formatName() {
return "ass";
}
}

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.subtitle.converter.impl;
import com.github.gtache.autosubtitle.VideoInfo;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
@@ -29,7 +30,7 @@ public class SRTSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
}
@Override
public String format(final SubtitleCollection<?> collection) {
public String format(final SubtitleCollection<?> collection, final VideoInfo videoInfo) {
final var subtitles = collection.subtitles().stream().sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
return IntStream.range(0, subtitles.size()).mapToObj(i -> {
final var subtitle = subtitles.get(i);

View File

@@ -0,0 +1,32 @@
package com.github.gtache.autosubtitle.subtitle.converter.impl;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Implementation of {@link SubtitleConverterProvider}
*/
public class SubtitleConverterProviderImpl implements SubtitleConverterProvider {
private final Map<String, SubtitleConverter<?>> converters;
@Inject
SubtitleConverterProviderImpl(final Map<String, SubtitleConverter> converters) {
this.converters = converters.entrySet().stream().collect(Collectors.toMap(e -> e.getKey().toUpperCase(), Map.Entry::getValue));
}
@Override
public Collection<SubtitleConverter<?>> allConverters() {
return converters.values();
}
@Override
public SubtitleConverter<?> getConverter(final String format) {
return converters.get(format.toUpperCase());
}
}

View File

@@ -1,11 +1,14 @@
package com.github.gtache.autosubtitle.subtitle.impl;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.VideoInfo;
import com.github.gtache.autosubtitle.archive.Archiver;
import com.github.gtache.autosubtitle.archive.ArchiverProvider;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import com.github.gtache.autosubtitle.subtitle.SubtitleImporterExporter;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverterProvider;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -17,7 +20,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;
import java.util.stream.Collectors;
import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link SubtitleImporterExporter}
@@ -25,32 +29,32 @@ import java.util.stream.Collectors;
public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<SubtitleImpl> {
private static final Logger logger = LogManager.getLogger(SubtitleImporterExporterImpl.class);
private final Map<String, Archiver> archiverMap;
private final Map<String, SubtitleConverter<?>> converterMap;
private final ArchiverProvider archiverProvider;
private final SubtitleConverterProvider converterProvider;
@Inject
SubtitleImporterExporterImpl(final Map<String, Archiver> archiverMap, final Map<String, SubtitleConverter> converterMap) {
this.archiverMap = Map.copyOf(archiverMap);
this.converterMap = converterMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
SubtitleImporterExporterImpl(final ArchiverProvider archiverProvider, final SubtitleConverterProvider converterProvider) {
this.archiverProvider = requireNonNull(archiverProvider);
this.converterProvider = requireNonNull(converterProvider);
}
@Override
public Map<Language, SubtitleCollection<SubtitleImpl>> importSubtitles(final Path file) throws IOException, ParseException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
if (archiverMap.containsKey(extension)) {
return loadArchive(file);
} else {
if (archiverProvider.getArchiver(extension) == null) {
final var loaded = loadSingleFile(file);
logger.info("Loaded {}", file);
return Map.of(loaded.language(), loaded);
} else {
return loadArchive(file);
}
}
private SubtitleCollection<SubtitleImpl> loadSingleFile(final Path file) throws ParseException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
final var parser = converterMap.get(extension);
final var parser = converterProvider.getConverter(extension);
if (parser == null) {
throw new ParseException("No converter found for " + file);
} else {
@@ -62,7 +66,7 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
private Map<Language, SubtitleCollection<SubtitleImpl>> loadArchive(final Path file) throws IOException, ParseException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
final var archiver = archiverMap.get(extension);
final var archiver = archiverProvider.getArchiver(extension);
final var tempDirectory = Files.createTempDirectory("autosubtitle");
archiver.decompress(file, tempDirectory);
final var files = new ArrayList<Path>();
@@ -81,27 +85,27 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
}
@Override
public void exportSubtitles(final Collection<? extends SubtitleCollection<?>> collections, final Path file) throws IOException {
public void exportSubtitles(final Collection<? extends SubtitleCollection<?>> collections, final VideoInfo videoInfo, final Path file) throws IOException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
if (archiverMap.containsKey(extension)) {
saveArchive(file, collections);
if (archiverProvider.getArchiver(extension) != null) {
saveArchive(file, collections, videoInfo);
} else if (collections.size() == 1) {
saveSingleFile(file, collections.iterator().next());
saveSingleFile(file, collections.iterator().next(), videoInfo);
} else {
throw new IllegalArgumentException("Cannot export multiple collections to a non-archive file : " + file);
}
}
private void saveArchive(final Path file, final Iterable<? extends SubtitleCollection<?>> collections) throws IOException {
private void saveArchive(final Path file, final Iterable<? extends SubtitleCollection<?>> collections, final VideoInfo videoInfo) throws IOException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
final var archiver = archiverMap.get(extension);
final var singleExporter = converterMap.getOrDefault("json", converterMap.values().iterator().next());
final var archiver = archiverProvider.getArchiver(extension);
final var singleExporter = converterProvider.getConverter("json");
final var tempDir = Files.createTempDirectory("autosubtitle");
for (final var collection : collections) {
final var subtitleFile = tempDir.resolve(collection.language() + "." + singleExporter.formatName());
saveSingleFile(subtitleFile, collection);
saveSingleFile(subtitleFile, collection, videoInfo);
}
final var files = new ArrayList<Path>();
try (final var stream = Files.list(tempDir)) {
@@ -115,14 +119,14 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
logger.info("Saved {}", file);
}
private void saveSingleFile(final Path file, final SubtitleCollection<?> collection) throws IOException {
private void saveSingleFile(final Path file, final SubtitleCollection<?> collection, final VideoInfo videoInfo) throws IOException {
final var fileName = file.getFileName().toString();
final var extension = fileName.substring(fileName.lastIndexOf('.') + 1);
final var converter = converterMap.get(extension);
final var converter = converterProvider.getConverter(extension);
if (converter == null) {
throw new IOException("No converter found for " + file);
} else {
final var string = converter.format(collection);
final var string = converter.format(collection, videoInfo);
Files.writeString(file, string);
logger.info("Saved {}", file);
}
@@ -131,11 +135,11 @@ public class SubtitleImporterExporterImpl implements SubtitleImporterExporter<Su
@Override
public Collection<String> supportedArchiveExtensions() {
return archiverMap.keySet();
return archiverProvider.allArchivers().stream().map(Archiver::archiveExtension).toList();
}
@Override
public Collection<String> supportedSingleFileExtensions() {
return converterMap.keySet();
return converterProvider.allConverters().stream().map(SubtitleConverter::formatName).toList();
}
}

View File

@@ -1,6 +1,7 @@
package com.github.gtache.autosubtitle.subtitle.converter.impl;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.VideoInfo;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
@@ -23,10 +24,12 @@ class TestSRTSubtitleConverter {
private final Translator translator;
private final Language language;
private final VideoInfo videoInfo;
TestSRTSubtitleConverter(@Mock final Translator translator, @Mock final Language language) {
TestSRTSubtitleConverter(@Mock final Translator translator, @Mock final Language language, @Mock final VideoInfo videoInfo) {
this.translator = Objects.requireNonNull(translator);
this.language = Objects.requireNonNull(language);
this.videoInfo = Objects.requireNonNull(videoInfo);
when(translator.getLanguage(anyString())).thenReturn(language);
}
@@ -53,7 +56,7 @@ class TestSRTSubtitleConverter {
final var subtitles = new SubtitleCollectionImpl<>(subtitle1.content() + " " + subtitle2.content(), Arrays.asList(subtitle1, subtitle2), language);
final var converter = new SRTSubtitleConverter(translator);
assertEquals(subtitles, converter.parse(in));
assertEquals(in, converter.format(subtitles));
assertEquals(in, converter.format(subtitles, videoInfo));
}
@Test