|
|
|
|
@@ -1,16 +1,17 @@
|
|
|
|
|
package com.github.gtache.autosubtitle.subtitle.parser.json.whisperx;
|
|
|
|
|
|
|
|
|
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
|
|
import com.github.gtache.autosubtitle.Language;
|
|
|
|
|
import com.github.gtache.autosubtitle.VideoInfo;
|
|
|
|
|
import com.github.gtache.autosubtitle.modules.impl.MaxLineLength;
|
|
|
|
|
import com.github.gtache.autosubtitle.modules.impl.MaxLines;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.converter.FormatException;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.converter.FormatOptions;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.converter.ParseOptions;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.converter.SubtitleConverter;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
|
|
|
|
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
|
|
|
|
import com.google.gson.Gson;
|
|
|
|
|
|
|
|
|
|
import javax.inject.Inject;
|
|
|
|
|
import javax.inject.Singleton;
|
|
|
|
|
@@ -19,7 +20,6 @@ import java.util.ArrayList;
|
|
|
|
|
import java.util.Comparator;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.Objects;
|
|
|
|
|
import java.util.prefs.Preferences;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
import java.util.stream.Stream;
|
|
|
|
|
@@ -30,42 +30,38 @@ import java.util.stream.Stream;
|
|
|
|
|
@Singleton
|
|
|
|
|
public class JSONSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
|
|
|
|
|
|
|
|
|
private static final String MAX_LINE_LENGTH = "maxLineLength";
|
|
|
|
|
private static final String MAX_LINES = "maxLines";
|
|
|
|
|
private static final Pattern SPLIT_PATTERN = Pattern.compile("[ \n]+");
|
|
|
|
|
|
|
|
|
|
private final Gson gson;
|
|
|
|
|
private final Preferences preferences;
|
|
|
|
|
private final int defaultMaxLineLength;
|
|
|
|
|
private final int defaultMaxLines;
|
|
|
|
|
private final ObjectMapper mapper;
|
|
|
|
|
|
|
|
|
|
@Inject
|
|
|
|
|
JSONSubtitleConverter(final Gson gson, final Preferences preferences, @MaxLineLength final int defaultMaxLineLength, @MaxLines final int defaultMaxLines) {
|
|
|
|
|
this.gson = Objects.requireNonNull(gson);
|
|
|
|
|
this.preferences = Objects.requireNonNull(preferences);
|
|
|
|
|
this.defaultMaxLineLength = defaultMaxLineLength;
|
|
|
|
|
this.defaultMaxLines = defaultMaxLines;
|
|
|
|
|
JSONSubtitleConverter(final ObjectMapper mapper) {
|
|
|
|
|
this.mapper = Objects.requireNonNull(mapper);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String format(final SubtitleCollection<?> collection, final VideoInfo videoInfo) {
|
|
|
|
|
public String format(final SubtitleCollection<?> collection, final FormatOptions options) throws FormatException {
|
|
|
|
|
final var segments = collection.subtitles().stream().map(s -> new JSONSubtitleSegment(s.start() / (double) 1000,
|
|
|
|
|
s.end() / (double) 1000, s.content(), List.of())).toList();
|
|
|
|
|
final var subtitles = new JSONSubtitles(segments, collection.language().iso2());
|
|
|
|
|
return gson.toJson(subtitles);
|
|
|
|
|
try {
|
|
|
|
|
return mapper.writeValueAsString(subtitles);
|
|
|
|
|
} catch (final JsonProcessingException e) {
|
|
|
|
|
throw new FormatException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content) throws ParseException {
|
|
|
|
|
public SubtitleCollectionImpl<SubtitleImpl> parse(final String content, final ParseOptions options) throws ParseException {
|
|
|
|
|
try {
|
|
|
|
|
final var json = gson.fromJson(content, JSONSubtitles.class);
|
|
|
|
|
final var json = mapper.readValue(content, JSONSubtitles.class);
|
|
|
|
|
final var subtitles = json.segments().stream().flatMap(s -> {
|
|
|
|
|
final var start = (long) (s.start() * 1000L);
|
|
|
|
|
final var end = (long) (s.end() * 1000L);
|
|
|
|
|
if (s.words().isEmpty()) {
|
|
|
|
|
return Stream.of(new SubtitleImpl(s.text(), start, end, null, null));
|
|
|
|
|
} else {
|
|
|
|
|
return splitSubtitle(s);
|
|
|
|
|
return splitSubtitle(s, options);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}).sorted(Comparator.comparing(Subtitle::start).thenComparing(Subtitle::end)).toList();
|
|
|
|
|
@@ -77,23 +73,23 @@ public class JSONSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Stream<SubtitleImpl> splitSubtitle(final JSONSubtitleSegment segment) {
|
|
|
|
|
final var maxLineLength = preferences.getInt(MAX_LINE_LENGTH, defaultMaxLineLength);
|
|
|
|
|
final var maxLines = preferences.getInt(MAX_LINES, defaultMaxLines);
|
|
|
|
|
private static Stream<SubtitleImpl> splitSubtitle(final JSONSubtitleSegment segment, final ParseOptions options) {
|
|
|
|
|
final var maxLineLength = options.maxLineLength();
|
|
|
|
|
final var maxLines = options.maxLines();
|
|
|
|
|
final var text = segment.text();
|
|
|
|
|
if (text.length() <= maxLineLength) {
|
|
|
|
|
final var start = (long) (segment.start() * 1000L);
|
|
|
|
|
final var end = (long) (segment.end() * 1000L);
|
|
|
|
|
return Stream.of(new SubtitleImpl(text.replace("\n", " "), start, end, null, null));
|
|
|
|
|
} else if (text.length() <= maxLines * maxLineLength) {
|
|
|
|
|
return splitSubtitleLines(segment);
|
|
|
|
|
return splitSubtitleLines(segment, options);
|
|
|
|
|
} else {
|
|
|
|
|
return splitSubtitleWords(segment);
|
|
|
|
|
return splitSubtitleWords(segment, options);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Stream<SubtitleImpl> splitSubtitleLines(final JSONSubtitleSegment segment) {
|
|
|
|
|
final var maxLineLength = preferences.getInt(MAX_LINE_LENGTH, defaultMaxLineLength);
|
|
|
|
|
private static Stream<SubtitleImpl> splitSubtitleLines(final JSONSubtitleSegment segment, final ParseOptions options) {
|
|
|
|
|
final var maxLineLength = options.maxLineLength();
|
|
|
|
|
final var text = segment.text();
|
|
|
|
|
final var split = SPLIT_PATTERN.split(text);
|
|
|
|
|
final var builder = new StringBuilder(text.length());
|
|
|
|
|
@@ -116,9 +112,9 @@ public class JSONSubtitleConverter implements SubtitleConverter<SubtitleImpl> {
|
|
|
|
|
return currentLength / (maxLength + 1) < newLength / (maxLength + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Stream<SubtitleImpl> splitSubtitleWords(final JSONSubtitleSegment segment) {
|
|
|
|
|
final var maxLineLength = preferences.getInt(MAX_LINE_LENGTH, defaultMaxLineLength);
|
|
|
|
|
final var maxLines = preferences.getInt(MAX_LINES, defaultMaxLines);
|
|
|
|
|
private static Stream<SubtitleImpl> splitSubtitleWords(final JSONSubtitleSegment segment, final ParseOptions options) {
|
|
|
|
|
final var maxLineLength = options.maxLineLength();
|
|
|
|
|
final var maxLines = options.maxLines();
|
|
|
|
|
final var ret = new ArrayList<SubtitleImpl>(segment.text().length() / (maxLines * maxLineLength));
|
|
|
|
|
final var builder = new StringBuilder(maxLines * maxLineLength);
|
|
|
|
|
final var words = segment.words();
|
|
|
|
|
|