Adds WhisperX, reworks UI (still needs some work), theoretically usable

This commit is contained in:
Guillaume Tâche
2024-08-17 22:05:04 +02:00
parent 7bddf53bab
commit 3fa51eb95b
204 changed files with 4787 additions and 1321 deletions

View File

@@ -6,7 +6,7 @@ import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
/**
* Translates texts and subtitles
*/
public interface Translator {
public interface Translator<T extends Subtitle> {
/**
* Guesses the language of the given text
@@ -42,7 +42,7 @@ public interface Translator {
* @param to The target language
* @return The translated subtitle
*/
Subtitle translate(Subtitle subtitle, Language to);
T translate(Subtitle subtitle, Language to);
/**
* Translates the given subtitles collection to the given language
@@ -51,5 +51,5 @@ public interface Translator {
* @param to The target language
* @return The translated subtitles collection
*/
SubtitleCollection translate(SubtitleCollection collection, Language to);
SubtitleCollection<T> translate(SubtitleCollection<?> collection, Language to);
}

View File

@@ -19,7 +19,7 @@ public interface VideoConverter {
* @return The modified video
* @throws IOException If an I/O error occurs
*/
Video addSoftSubtitles(final Video video, final Collection<SubtitleCollection> subtitles) throws IOException;
Video addSoftSubtitles(final Video video, final Collection<? extends SubtitleCollection<?>> subtitles) throws IOException;
/**
* Adds soft subtitles to the given video
@@ -29,7 +29,7 @@ public interface VideoConverter {
* @param path The output path
* @throws IOException If an I/O error occurs
*/
void addSoftSubtitles(final Video video, final Collection<SubtitleCollection> subtitles, final Path path) throws IOException;
void addSoftSubtitles(final Video video, final Collection<? extends SubtitleCollection<?>> subtitles, final Path path) throws IOException;
/**
* Adds hard subtitles to the given video
@@ -39,7 +39,7 @@ public interface VideoConverter {
* @return The modified video
* @throws IOException If an I/O error occurs
*/
Video addHardSubtitles(final Video video, final SubtitleCollection subtitles) throws IOException;
Video addHardSubtitles(final Video video, final SubtitleCollection<?> subtitles) throws IOException;
/**
* Adds hard subtitles to the given video
@@ -49,7 +49,7 @@ public interface VideoConverter {
* @param path The output path
* @throws IOException If an I/O error occurs
*/
void addHardSubtitles(final Video video, final SubtitleCollection subtitles, final Path path) throws IOException;
void addHardSubtitles(final Video video, final SubtitleCollection<?> subtitles, final Path path) throws IOException;
/**
* Extracts the audio from the given video

View File

@@ -0,0 +1,44 @@
package com.github.gtache.autosubtitle.archive;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
/**
* Compresses and uncompresses files
*/
public interface Archiver {
/**
* Zips multiple files to the given destination
*
* @param files The files to zip
* @param destination The zipped file
* @throws IOException if an error occurs
*/
void compress(final List<Path> files, final Path destination) throws IOException;
/**
* Unzips an archive to the given destination
*
* @param archive The archive
* @param destination The destination folder
* @throws IOException if an error occurs
*/
void decompress(final Path archive, final Path destination) throws IOException;
/**
* Checks whether the given archive file is supported by the compresser
*
* @param path The file path
* @return True if the file is supported
*/
default boolean isPathSupported(final Path path) {
return path.toString().endsWith("." + archiveExtension());
}
/**
* @return The zipped archive extension
*/
String archiveExtension();
}

View File

@@ -22,10 +22,11 @@ public interface ProcessListener {
String readLine() throws IOException;
/**
* Waits for the process to finish
* Waits for the process to finish. Automatically reads the process output to ensure it doesn't get stuck.
*
* @param duration The maximum time to wait
* @return The process result
* @throws IOException if an error occurs
*/
ProcessResult join(final Duration duration) throws IOException;
}

View File

@@ -1,6 +1,7 @@
package com.github.gtache.autosubtitle.process;
import java.io.IOException;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
@@ -10,24 +11,25 @@ import java.util.List;
public interface ProcessRunner {
/**
* Runs a command
* Runs a command and waits max 1 hour for the process to run
*
* @param args the command
* @return the result
* @throws IOException if something goes wrong
*/
default ProcessResult run(final String... args) throws IOException {
return run(Arrays.asList(args));
return run(Arrays.asList(args), Duration.ofHours(1));
}
/**
* Runs a command
*
* @param args the command
* @param args the command
* @param duration The maximum duration to wait for
* @return the result
* @throws IOException if something goes wrong
*/
ProcessResult run(final List<String> args) throws IOException;
ProcessResult run(final List<String> args, final Duration duration) throws IOException;
/**
* Starts a process

View File

@@ -7,7 +7,7 @@ import java.util.Collection;
/**
* Represents a collection of {@link Subtitle}
*/
public interface SubtitleCollection {
public interface SubtitleCollection<T extends Subtitle> {
/**
* @return The whole text of the subtitles
@@ -17,7 +17,7 @@ public interface SubtitleCollection {
/**
* @return The subtitles
*/
Collection<? extends Subtitle> subtitles();
Collection<T> subtitles();
/**
* @return The language of the subtitles

View File

@@ -0,0 +1,56 @@
package com.github.gtache.autosubtitle.subtitle;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.subtitle.converter.ParseException;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Map;
/**
* Imports and exports subtitles
*/
public interface SubtitleImporterExporter<T extends Subtitle> {
/**
* Imports subtitles from a file
*
* @param file The path to the file
* @return A mapping of langauge to collection
* @throws IOException If an error occurred
* @throws ParseException If an error occurred while parsing a subtitle
*/
Map<Language, SubtitleCollection<T>> importSubtitles(final Path file) throws IOException, ParseException;
/**
* Exports multiple collections to a file
*
* @param collections The subtitle collections
* @param file The path to the file
* @throws IOException If an error occurred
*/
void exportSubtitles(final Collection<? extends SubtitleCollection<?>> collections, final Path file) throws IOException;
/**
* Exports a single collection to a file
*
* @param collection The subtitle collection
* @param file The path to the file
* @throws IOException If an error occurred
*/
default void exportSubtitles(final SubtitleCollection<?> collection, final Path file) throws IOException {
exportSubtitles(List.of(collection), file);
}
/**
* @return The supported file extensions for multiple collection exports
*/
Collection<String> supportedArchiveExtensions();
/**
* @return The supported file extensions for single collection exports
*/
Collection<String> supportedSingleFileExtensions();
}

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.subtitle.converter;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
import java.io.IOException;
@@ -9,7 +10,7 @@ import java.nio.file.Path;
/**
* Converts subtitles to a specific format (e.g. srt, ssa, ass, ...) and vice-versa
*/
public interface SubtitleConverter {
public interface SubtitleConverter<T extends Subtitle> {
/**
* Converts the subtitle collection
@@ -17,7 +18,7 @@ public interface SubtitleConverter {
* @param collection The collection
* @return The converted subtitles as the content of a file
*/
String format(final SubtitleCollection collection);
String format(final SubtitleCollection<?> collection);
/**
* Parses a subtitle collection
@@ -26,7 +27,7 @@ public interface SubtitleConverter {
* @return The subtitle collection
* @throws ParseException If an error occurred
*/
default SubtitleCollection parse(final Path file) throws ParseException {
default SubtitleCollection<T> parse(final Path file) throws ParseException {
try {
final var content = Files.readString(file);
return parse(content);
@@ -42,7 +43,7 @@ public interface SubtitleConverter {
* @return The subtitle collection
* @throws ParseException If an error occurred
*/
SubtitleCollection parse(String content) throws ParseException;
SubtitleCollection<T> parse(String content) throws ParseException;
/**
* Check if the parser can parse the given file

View File

@@ -3,12 +3,13 @@ package com.github.gtache.autosubtitle.subtitle.extractor;
import com.github.gtache.autosubtitle.Audio;
import com.github.gtache.autosubtitle.Language;
import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.subtitle.Subtitle;
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
/**
* Extracts subtitles from a video or audio
*/
public interface SubtitleExtractor {
public interface SubtitleExtractor<T extends Subtitle> {
/**
* Adds a listener
@@ -37,7 +38,7 @@ public interface SubtitleExtractor {
* @return The extracted subtitle collection
* @throws ExtractException If an error occurs
*/
default SubtitleCollection extract(final Video video, final ExtractionModel model) throws ExtractException {
default SubtitleCollection<T> extract(final Video video, final ExtractionModel model) throws ExtractException {
return extract(video, Language.AUTO, model);
}
@@ -50,7 +51,7 @@ public interface SubtitleExtractor {
* @return The extracted subtitle collection
* @throws ExtractException If an error occurs
*/
SubtitleCollection extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException;
SubtitleCollection<T> extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException;
/**
* Extracts the subtitles from an audio
@@ -60,7 +61,7 @@ public interface SubtitleExtractor {
* @return The extracted subtitle collection
* @throws ExtractException If an error occurs
*/
default SubtitleCollection extract(final Audio audio, final ExtractionModel model) throws ExtractException {
default SubtitleCollection<T> extract(final Audio audio, final ExtractionModel model) throws ExtractException {
return extract(audio, Language.AUTO, model);
}
@@ -73,5 +74,5 @@ public interface SubtitleExtractor {
* @return The extracted subtitle collection
* @throws ExtractException If an error occurs
*/
SubtitleCollection extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException;
SubtitleCollection<T> extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException;
}

View File

@@ -3,6 +3,7 @@
*/
module com.github.gtache.autosubtitle.api {
exports com.github.gtache.autosubtitle;
exports com.github.gtache.autosubtitle.archive;
exports com.github.gtache.autosubtitle.process;
exports com.github.gtache.autosubtitle.setup;
exports com.github.gtache.autosubtitle.subtitle;

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.com.github.gtache.autosubtitle.subtitle.converter;
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;
@@ -23,10 +24,10 @@ import static org.mockito.Mockito.when;
class TestSubtitleConverter {
private final SubtitleConverter subtitleConverter;
private final SubtitleCollection subtitleCollection;
private final SubtitleCollection<Subtitle> subtitleCollection;
TestSubtitleConverter(@Mock final SubtitleConverter subtitleConverter,
@Mock final SubtitleCollection subtitleCollection) {
@Mock final SubtitleCollection<Subtitle> subtitleCollection) {
this.subtitleConverter = Objects.requireNonNull(subtitleConverter);
this.subtitleCollection = Objects.requireNonNull(subtitleCollection);
}

View File

@@ -7,6 +7,7 @@ import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Objects;
@@ -32,7 +33,7 @@ class TestProcessRunner {
@Test
void testRunVarargs() throws IOException {
when(processRunner.run(List.of("arg1", "arg2"))).thenReturn(result);
when(processRunner.run(List.of("arg1", "arg2"), Duration.ofHours(1))).thenReturn(result);
when(processRunner.run(any(String[].class))).thenCallRealMethod();
assertEquals(result, processRunner.run("arg1", "arg2"));