Adds tests for common whisper
This commit is contained in:
@@ -9,7 +9,7 @@ import java.io.InputStream;
|
|||||||
public interface Audio {
|
public interface Audio {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The audio input stream
|
* @return The input stream
|
||||||
* @throws IOException If an I/O error occurs
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
InputStream getInputStream() throws IOException;
|
InputStream getInputStream() throws IOException;
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ package com.github.gtache.autosubtitle;
|
|||||||
* Represents info about an audio
|
* Represents info about an audio
|
||||||
*/
|
*/
|
||||||
public interface AudioInfo {
|
public interface AudioInfo {
|
||||||
/**
|
|
||||||
* @return The audio extension (mp3, etc.)
|
|
||||||
*/
|
|
||||||
String audioFormat();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The audio duration in milliseconds
|
* @return The extension (mp3, etc.)
|
||||||
|
*/
|
||||||
|
String format();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The duration in milliseconds
|
||||||
*/
|
*/
|
||||||
long duration();
|
long duration();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,8 @@ import java.io.InputStream;
|
|||||||
* Represents a video
|
* Represents a video
|
||||||
*/
|
*/
|
||||||
public interface Video {
|
public interface Video {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The video input stream
|
* @return The input stream
|
||||||
* @throws IOException If an I/O error occurs
|
* @throws IOException If an I/O error occurs
|
||||||
*/
|
*/
|
||||||
InputStream getInputStream() throws IOException;
|
InputStream getInputStream() throws IOException;
|
||||||
@@ -18,5 +17,4 @@ public interface Video {
|
|||||||
* @return The video info
|
* @return The video info
|
||||||
*/
|
*/
|
||||||
VideoInfo info();
|
VideoInfo info();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,7 @@ package com.github.gtache.autosubtitle;
|
|||||||
/**
|
/**
|
||||||
* Info about a video
|
* Info about a video
|
||||||
*/
|
*/
|
||||||
public interface VideoInfo {
|
public interface VideoInfo extends AudioInfo {
|
||||||
/**
|
|
||||||
* @return The video extension (mp4, etc.)
|
|
||||||
*/
|
|
||||||
String videoFormat();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The video width in pixels
|
* @return The video width in pixels
|
||||||
@@ -19,11 +15,6 @@ public interface VideoInfo {
|
|||||||
*/
|
*/
|
||||||
int height();
|
int height();
|
||||||
|
|
||||||
/**
|
|
||||||
* @return The video duration in milliseconds
|
|
||||||
*/
|
|
||||||
long duration();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The aspect ratio of the video
|
* @return The aspect ratio of the video
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ public interface SubtitleExtractor<T extends Subtitle> {
|
|||||||
* Extracts the subtitles from a video
|
* Extracts the subtitles from a video
|
||||||
*
|
*
|
||||||
* @param video The video
|
* @param video The video
|
||||||
* @param language The language of the video
|
* @param language The language of the audio
|
||||||
* @param model The model to use
|
* @param model The model to use
|
||||||
* @return The extracted subtitle collection
|
* @return The extracted subtitle collection
|
||||||
* @throws ExtractException If an error occurs
|
* @throws ExtractException If an error occurs
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ import static org.mockito.Mockito.when;
|
|||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class TestSubtitleConverter {
|
class TestSubtitleConverter {
|
||||||
|
|
||||||
private final SubtitleConverter subtitleConverter;
|
private final SubtitleConverter<Subtitle> subtitleConverter;
|
||||||
private final SubtitleCollection<Subtitle> subtitleCollection;
|
private final SubtitleCollection<Subtitle> subtitleCollection;
|
||||||
|
|
||||||
TestSubtitleConverter(@Mock final SubtitleConverter subtitleConverter,
|
TestSubtitleConverter(@Mock final SubtitleConverter<Subtitle> subtitleConverter,
|
||||||
@Mock final SubtitleCollection<Subtitle> subtitleCollection) {
|
@Mock final SubtitleCollection<Subtitle> subtitleCollection) {
|
||||||
this.subtitleConverter = Objects.requireNonNull(subtitleConverter);
|
this.subtitleConverter = Objects.requireNonNull(subtitleConverter);
|
||||||
this.subtitleCollection = Objects.requireNonNull(subtitleCollection);
|
this.subtitleCollection = Objects.requireNonNull(subtitleCollection);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.github.gtache.autosubtitle.subtitle.extractor;
|
|||||||
import com.github.gtache.autosubtitle.Audio;
|
import com.github.gtache.autosubtitle.Audio;
|
||||||
import com.github.gtache.autosubtitle.Language;
|
import com.github.gtache.autosubtitle.Language;
|
||||||
import com.github.gtache.autosubtitle.Video;
|
import com.github.gtache.autosubtitle.Video;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.Subtitle;
|
||||||
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
import com.github.gtache.autosubtitle.subtitle.SubtitleCollection;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
@@ -18,14 +19,14 @@ import static org.mockito.Mockito.when;
|
|||||||
@ExtendWith(MockitoExtension.class)
|
@ExtendWith(MockitoExtension.class)
|
||||||
class TestSubtitleExtractor {
|
class TestSubtitleExtractor {
|
||||||
|
|
||||||
private final SubtitleExtractor subtitleExtractor;
|
private final SubtitleExtractor<Subtitle> subtitleExtractor;
|
||||||
private final SubtitleCollection subtitleCollection;
|
private final SubtitleCollection<Subtitle> subtitleCollection;
|
||||||
private final Audio audio;
|
private final Audio audio;
|
||||||
private final Video video;
|
private final Video video;
|
||||||
private final ExtractionModel extractionModel;
|
private final ExtractionModel extractionModel;
|
||||||
|
|
||||||
TestSubtitleExtractor(@Mock final SubtitleExtractor subtitleExtractor,
|
TestSubtitleExtractor(@Mock final SubtitleExtractor<Subtitle> subtitleExtractor,
|
||||||
@Mock final SubtitleCollection subtitleCollection,
|
@Mock final SubtitleCollection<Subtitle> subtitleCollection,
|
||||||
@Mock final Audio audio,
|
@Mock final Audio audio,
|
||||||
@Mock final Video video,
|
@Mock final Video video,
|
||||||
@Mock final ExtractionModel extractionModel) {
|
@Mock final ExtractionModel extractionModel) {
|
||||||
|
|||||||
@@ -6,4 +6,5 @@ module com.github.gtache.autosubtitle.cli {
|
|||||||
requires com.github.gtache.autosubtitle.ffmpeg;
|
requires com.github.gtache.autosubtitle.ffmpeg;
|
||||||
requires com.github.gtache.autosubtitle.whisperx;
|
requires com.github.gtache.autosubtitle.whisperx;
|
||||||
requires info.picocli;
|
requires info.picocli;
|
||||||
|
requires guava;
|
||||||
}
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.github.gtache.autosubtitle.archive.client;
|
|
||||||
|
|
||||||
import com.github.gtache.autosubtitle.archive.Archiver;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Archiver} using a remote API
|
|
||||||
*/
|
|
||||||
public class RemoteArchiver implements Archiver {
|
|
||||||
@Override
|
|
||||||
public void compress(final List<Path> files, final Path destination) throws IOException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void decompress(final Path archive, final Path destination) throws IOException {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String archiveExtension() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,10 +7,10 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Implementation of {@link AudioInfo}
|
* Implementation of {@link AudioInfo}
|
||||||
*/
|
*/
|
||||||
public record AudioInfoImpl(String audioFormat, long duration) implements AudioInfo {
|
public record AudioInfoImpl(String format, long duration) implements AudioInfo {
|
||||||
|
|
||||||
public AudioInfoImpl {
|
public AudioInfoImpl {
|
||||||
Objects.requireNonNull(audioFormat);
|
Objects.requireNonNull(format);
|
||||||
if (duration < 0) {
|
if (duration < 0) {
|
||||||
throw new IllegalArgumentException("Duration must be positive");
|
throw new IllegalArgumentException("Duration must be positive");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import java.util.Objects;
|
|||||||
/**
|
/**
|
||||||
* Implementation of {@link VideoInfo}
|
* Implementation of {@link VideoInfo}
|
||||||
*/
|
*/
|
||||||
public record VideoInfoImpl(String videoFormat, int width, int height, long duration) implements VideoInfo {
|
public record VideoInfoImpl(String format, int width, int height, long duration) implements VideoInfo {
|
||||||
|
|
||||||
public VideoInfoImpl {
|
public VideoInfoImpl {
|
||||||
Objects.requireNonNull(videoFormat);
|
Objects.requireNonNull(format);
|
||||||
if (width <= 0) {
|
if (width <= 0) {
|
||||||
throw new IllegalArgumentException("Width must be greater than 0 : " + width);
|
throw new IllegalArgumentException("Width must be greater than 0 : " + width);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ class TestAudioInfoImpl {
|
|||||||
private final long duration;
|
private final long duration;
|
||||||
|
|
||||||
TestAudioInfoImpl() {
|
TestAudioInfoImpl() {
|
||||||
this.audioFormat = "audioFormat";
|
this.audioFormat = "format";
|
||||||
this.duration = 1000L;
|
this.duration = 1000L;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGetters() {
|
void testGetters() {
|
||||||
final var audioInfo = new AudioInfoImpl(audioFormat, duration);
|
final var audioInfo = new AudioInfoImpl(audioFormat, duration);
|
||||||
assertEquals(audioFormat, audioInfo.audioFormat());
|
assertEquals(audioFormat, audioInfo.format());
|
||||||
assertEquals(duration, audioInfo.duration());
|
assertEquals(duration, audioInfo.duration());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class TestVideoInfoImpl {
|
|||||||
private final long duration;
|
private final long duration;
|
||||||
|
|
||||||
TestVideoInfoImpl() {
|
TestVideoInfoImpl() {
|
||||||
this.videoFormat = "videoFormat";
|
this.videoFormat = "format";
|
||||||
this.width = 1;
|
this.width = 1;
|
||||||
this.height = 2;
|
this.height = 2;
|
||||||
this.duration = 3;
|
this.duration = 3;
|
||||||
@@ -22,7 +22,7 @@ class TestVideoInfoImpl {
|
|||||||
@Test
|
@Test
|
||||||
void testGetters() {
|
void testGetters() {
|
||||||
final var videoInfo = new VideoInfoImpl(videoFormat, width, height, duration);
|
final var videoInfo = new VideoInfoImpl(videoFormat, width, height, duration);
|
||||||
assertEquals(videoFormat, videoInfo.videoFormat());
|
assertEquals(videoFormat, videoInfo.format());
|
||||||
assertEquals(width, videoInfo.width());
|
assertEquals(width, videoInfo.width());
|
||||||
assertEquals(height, videoInfo.height());
|
assertEquals(height, videoInfo.height());
|
||||||
assertEquals(duration, videoInfo.duration());
|
assertEquals(duration, videoInfo.duration());
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class TestAbstractSubtitleExtractor {
|
|||||||
private static final class DummySubtitleExtractor extends AbstractSubtitleExtractor {
|
private static final class DummySubtitleExtractor extends AbstractSubtitleExtractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubtitleCollection<Subtitle> extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException {
|
public SubtitleCollection extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<deepl.version>1.5.0</deepl.version>
|
<deepl.version>1.5.0</deepl.version>
|
||||||
<lingua.version>1.2.2</lingua.version>
|
<lingua.version>1.2.2</lingua.version>
|
||||||
|
<tika.version>2.9.2</tika.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
@@ -28,9 +29,15 @@
|
|||||||
<version>${deepl.version}</version>
|
<version>${deepl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.pemistahl</groupId>
|
<groupId>org.apache.tika</groupId>
|
||||||
<artifactId>lingua</artifactId>
|
<artifactId>tika-core</artifactId>
|
||||||
<version>${lingua.version}</version>
|
<version>${tika.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tika</groupId>
|
||||||
|
<artifactId>tika-langdetect-optimaize</artifactId>
|
||||||
|
<version>${tika.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
@@ -3,13 +3,14 @@ package com.github.gtache.autosubtitle.modules.deepl;
|
|||||||
import com.github.gtache.autosubtitle.modules.setup.deepl.DeepLSetupModule;
|
import com.github.gtache.autosubtitle.modules.setup.deepl.DeepLSetupModule;
|
||||||
import com.github.gtache.autosubtitle.translation.Translator;
|
import com.github.gtache.autosubtitle.translation.Translator;
|
||||||
import com.github.gtache.autosubtitle.translation.deepl.DeepLTranslator;
|
import com.github.gtache.autosubtitle.translation.deepl.DeepLTranslator;
|
||||||
import com.github.pemistahl.lingua.api.LanguageDetector;
|
|
||||||
import com.github.pemistahl.lingua.api.LanguageDetectorBuilder;
|
|
||||||
import dagger.Binds;
|
import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
import org.apache.tika.language.detect.LanguageDetector;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UncheckedIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dagger module for DeepL
|
* Dagger module for DeepL
|
||||||
@@ -23,6 +24,10 @@ public abstract class DeepLModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
static LanguageDetector providesLanguageDetector() {
|
static LanguageDetector providesLanguageDetector() {
|
||||||
return LanguageDetectorBuilder.fromAllSpokenLanguages().build();
|
try {
|
||||||
|
return LanguageDetector.getDefaultLanguageDetector().loadModels();
|
||||||
|
} catch (final IOException e) {
|
||||||
|
throw new UncheckedIOException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class DeepLSetupManager extends AbstractSetupManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SetupStatus getStatus() throws SetupException {
|
protected SetupStatus getStatus() {
|
||||||
final var key = preferences.get(DEEPL_API_KEY, null);
|
final var key = preferences.get(DEEPL_API_KEY, null);
|
||||||
return key == null ? SetupStatus.NOT_INSTALLED : SetupStatus.BUNDLE_INSTALLED;
|
return key == null ? SetupStatus.NOT_INSTALLED : SetupStatus.BUNDLE_INSTALLED;
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ public class DeepLSetupManager extends AbstractSetupManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update() throws SetupException {
|
public void update() {
|
||||||
//No need to update
|
//No need to update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import com.github.gtache.autosubtitle.subtitle.impl.SubtitleCollectionImpl;
|
|||||||
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
|
||||||
import com.github.gtache.autosubtitle.translation.TranslationException;
|
import com.github.gtache.autosubtitle.translation.TranslationException;
|
||||||
import com.github.gtache.autosubtitle.translation.Translator;
|
import com.github.gtache.autosubtitle.translation.Translator;
|
||||||
import com.github.pemistahl.lingua.api.LanguageDetector;
|
import org.apache.tika.language.detect.LanguageDetector;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -37,7 +37,7 @@ public class DeepLTranslator implements Translator<Subtitle> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Language getLanguage(final String text) {
|
public Language getLanguage(final String text) {
|
||||||
return Language.getLanguage(languageDetector.detectLanguageOf(text).getIsoCode639_1().toString());
|
return Language.getLanguage(languageDetector.detect(text).getLanguage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
module com.github.gtache.autosubtitle.deepl {
|
module com.github.gtache.autosubtitle.deepl {
|
||||||
requires transitive com.github.gtache.autosubtitle.core;
|
requires transitive com.github.gtache.autosubtitle.core;
|
||||||
requires transitive deepl.java;
|
requires transitive deepl.java;
|
||||||
requires transitive com.github.pemistahl.lingua;
|
|
||||||
requires transitive java.prefs;
|
requires transitive java.prefs;
|
||||||
|
requires transitive org.apache.tika.core;
|
||||||
|
requires transitive language.detector;
|
||||||
exports com.github.gtache.autosubtitle.modules.deepl;
|
exports com.github.gtache.autosubtitle.modules.deepl;
|
||||||
exports com.github.gtache.autosubtitle.translation.deepl;
|
exports com.github.gtache.autosubtitle.translation.deepl;
|
||||||
exports com.github.gtache.autosubtitle.setup.deepl;
|
exports com.github.gtache.autosubtitle.setup.deepl;
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.github.gtache.autosubtitle.modules.deepl;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class TestDeepLModule {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testLanguageDetector() {
|
||||||
|
final var languageDetector = DeepLModule.providesLanguageDetector();
|
||||||
|
assertEquals("fr", languageDetector.detect("bonjour tout le monde").getLanguage());
|
||||||
|
assertEquals("en", languageDetector.detect("hello everyone this is a text").getLanguage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package com.github.gtache.autosubtitle.setup.deepl;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.process.ProcessRunner;
|
||||||
|
import com.github.gtache.autosubtitle.setup.SetupException;
|
||||||
|
import com.github.gtache.autosubtitle.setup.SetupStatus;
|
||||||
|
import com.github.gtache.autosubtitle.setup.SetupUserBridge;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.prefs.BackingStoreException;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class TestDeepLSetupManager {
|
||||||
|
|
||||||
|
private final SetupUserBridge userBridge;
|
||||||
|
private final Preferences preferences;
|
||||||
|
private final ProcessRunner processRunner;
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
private final DeepLSetupManager setupManager;
|
||||||
|
|
||||||
|
TestDeepLSetupManager(@Mock final SetupUserBridge userBridge, @Mock final Preferences preferences,
|
||||||
|
@Mock final ProcessRunner processRunner, @Mock final HttpClient httpClient) {
|
||||||
|
this.userBridge = Objects.requireNonNull(userBridge);
|
||||||
|
this.preferences = Objects.requireNonNull(preferences);
|
||||||
|
this.processRunner = Objects.requireNonNull(processRunner);
|
||||||
|
this.httpClient = Objects.requireNonNull(httpClient);
|
||||||
|
this.setupManager = new DeepLSetupManager(userBridge, preferences, processRunner, httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetStatus() {
|
||||||
|
assertEquals(SetupStatus.NOT_INSTALLED, setupManager.getStatus());
|
||||||
|
when(preferences.get("deepl.api.key", null)).thenReturn("key");
|
||||||
|
assertEquals(SetupStatus.BUNDLE_INSTALLED, setupManager.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstall() throws BackingStoreException, SetupException {
|
||||||
|
final var key = "key";
|
||||||
|
when(userBridge.askForUserInput(any())).thenReturn(key);
|
||||||
|
setupManager.install();
|
||||||
|
verify(preferences).put("deepl.api.key", key);
|
||||||
|
verify(preferences).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallException() throws BackingStoreException {
|
||||||
|
final var key = "key";
|
||||||
|
when(userBridge.askForUserInput(any())).thenReturn(key);
|
||||||
|
doThrow(BackingStoreException.class).when(preferences).flush();
|
||||||
|
assertThrows(SetupException.class, setupManager::install);
|
||||||
|
verify(preferences).put("deepl.api.key", key);
|
||||||
|
verify(preferences).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallNull() {
|
||||||
|
assertThrows(SetupException.class, setupManager::install);
|
||||||
|
verifyNoInteractions(preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUninstall() throws BackingStoreException, SetupException {
|
||||||
|
setupManager.uninstall();
|
||||||
|
verify(preferences).remove("deepl.api.key");
|
||||||
|
verify(preferences).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUninstallException() throws BackingStoreException {
|
||||||
|
doThrow(BackingStoreException.class).when(preferences).flush();
|
||||||
|
assertThrows(SetupException.class, setupManager::uninstall);
|
||||||
|
verify(preferences).remove("deepl.api.key");
|
||||||
|
verify(preferences).flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testName() {
|
||||||
|
assertEquals("DeepL", setupManager.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIllegal() {
|
||||||
|
assertThrows(NullPointerException.class, () -> new DeepLSetupManager(null, preferences, processRunner, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DeepLSetupManager(userBridge, null, processRunner, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DeepLSetupManager(userBridge, preferences, null, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DeepLSetupManager(userBridge, preferences, processRunner, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.github.gtache.autosubtitle.translation.deepl;
|
||||||
|
|
||||||
|
//TODO mock, postman, ...
|
||||||
|
class TestDeepLTranslator {
|
||||||
|
}
|
||||||
@@ -58,9 +58,9 @@ public class FFmpegVideoConverter implements VideoConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Video addSoftSubtitles(final Video video, final Collection<? extends SubtitleCollection<?>> subtitles) throws IOException {
|
public Video addSoftSubtitles(final Video video, final Collection<? extends SubtitleCollection<?>> subtitles) throws IOException {
|
||||||
final var out = getTempFile(video.info().videoFormat());
|
final var out = getTempFile(video.info().format());
|
||||||
addSoftSubtitles(video, subtitles, out);
|
addSoftSubtitles(video, subtitles, out);
|
||||||
return new FileVideoImpl(out, new VideoInfoImpl(video.info().videoFormat(), video.info().width(), video.info().height(), video.info().duration()));
|
return new FileVideoImpl(out, new VideoInfoImpl(video.info().format(), video.info().width(), video.info().height(), video.info().duration()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -110,7 +110,7 @@ public class FFmpegVideoConverter implements VideoConverter {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Video addHardSubtitles(final Video video, final SubtitleCollection<?> subtitles) throws IOException {
|
public Video addHardSubtitles(final Video video, final SubtitleCollection<?> subtitles) throws IOException {
|
||||||
final var out = getTempFile(video.info().videoFormat());
|
final var out = getTempFile(video.info().format());
|
||||||
addHardSubtitles(video, subtitles, out);
|
addHardSubtitles(video, subtitles, out);
|
||||||
return new FileVideoImpl(out, video.info());
|
return new FileVideoImpl(out, video.info());
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ public class FFmpegVideoConverter implements VideoConverter {
|
|||||||
public Audio getAudio(final Video video) throws IOException {
|
public Audio getAudio(final Video video) throws IOException {
|
||||||
final var videoPath = getPath(video);
|
final var videoPath = getPath(video);
|
||||||
final var audioPath = getTempFile(".wav");
|
final var audioPath = getTempFile(".wav");
|
||||||
final var dumpVideoPath = getTempFile("." + video.info().videoFormat());
|
final var dumpVideoPath = getTempFile("." + video.info().format());
|
||||||
final var args = List.of(
|
final var args = List.of(
|
||||||
getFFmpegPath(),
|
getFFmpegPath(),
|
||||||
"-y",
|
"-y",
|
||||||
@@ -172,7 +172,7 @@ public class FFmpegVideoConverter implements VideoConverter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Path dumpVideo(final Video video) throws IOException {
|
private static Path dumpVideo(final Video video) throws IOException {
|
||||||
final var path = getTempFile(video.info().videoFormat());
|
final var path = getTempFile(video.info().format());
|
||||||
try (final var out = Files.newOutputStream(path)) {
|
try (final var out = Files.newOutputStream(path)) {
|
||||||
video.getInputStream().transferTo(out);
|
video.getInputStream().transferTo(out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public interface ParametersModel {
|
|||||||
List<ExtractionModel> availableExtractionModels();
|
List<ExtractionModel> availableExtractionModels();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current extraction model
|
* @return The current extraction model setting
|
||||||
*/
|
*/
|
||||||
ExtractionModel extractionModel();
|
ExtractionModel extractionModel();
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ public interface ParametersModel {
|
|||||||
List<OutputFormat> availableOutputFormats();
|
List<OutputFormat> availableOutputFormats();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current output format
|
* @return The current output format setting
|
||||||
*/
|
*/
|
||||||
OutputFormat outputFormat();
|
OutputFormat outputFormat();
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ public interface ParametersModel {
|
|||||||
List<String> availableFontFamilies();
|
List<String> availableFontFamilies();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current font family
|
* @return The current font family setting
|
||||||
*/
|
*/
|
||||||
String fontName();
|
String fontName();
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ public interface ParametersModel {
|
|||||||
void setFontName(String fontFamily);
|
void setFontName(String fontFamily);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The current font size
|
* @return The current font size setting
|
||||||
*/
|
*/
|
||||||
int fontSize();
|
int fontSize();
|
||||||
|
|
||||||
@@ -65,11 +65,27 @@ public interface ParametersModel {
|
|||||||
*/
|
*/
|
||||||
void setFontSize(int fontSize);
|
void setFontSize(int fontSize);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The current max line length setting
|
||||||
|
*/
|
||||||
int maxLineLength();
|
int maxLineLength();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the max line length
|
||||||
|
*
|
||||||
|
* @param maxLineLength The new max line length
|
||||||
|
*/
|
||||||
void setMaxLineLength(int maxLineLength);
|
void setMaxLineLength(int maxLineLength);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The current max lines setting
|
||||||
|
*/
|
||||||
int maxLines();
|
int maxLines();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the max lines
|
||||||
|
*
|
||||||
|
* @param maxLines The new max lines
|
||||||
|
*/
|
||||||
void setMaxLines(int maxLines);
|
void setMaxLines(int maxLines);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ class TestColonTimeFormatter {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@CsvSource({
|
@CsvSource({
|
||||||
"12:34:56,45296000",
|
"12:34:56.000,45296000",
|
||||||
"12:34,754000",
|
"12:34.321,754321",
|
||||||
"01:02,62000",
|
"01:02.000,62000",
|
||||||
"1:2,62000",
|
"1:2.555,62555",
|
||||||
"01:02:03,3723000",
|
"01:02:03.000,3723000",
|
||||||
"1:2:3,3723000",
|
"1:2:3.000,3723000",
|
||||||
"00:00:03,3000",
|
"00:00:03.000,3000",
|
||||||
"00:03,3000",
|
"00:03.000,3000",
|
||||||
"1234:00:01,4442401000"
|
"1234:00:01.000,4442401000"
|
||||||
})
|
})
|
||||||
void testParse(final String time, final long millis) {
|
void testParse(final String time, final long millis) {
|
||||||
assertEquals(millis, timeFormatter.parse(time));
|
assertEquals(millis, timeFormatter.parse(time));
|
||||||
@@ -28,14 +28,14 @@ class TestColonTimeFormatter {
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@CsvSource({
|
@CsvSource({
|
||||||
"45296000,12:34:56",
|
"45296000,12:34:56.000",
|
||||||
"45296521,12:34:56",
|
"45296521,12:34:56.521",
|
||||||
"754000,12:34",
|
"754000,12:34.000",
|
||||||
"754620,12:34",
|
"754620,12:34.620",
|
||||||
"62000,01:02",
|
"62000,01:02.000",
|
||||||
"3723000,1:02:03",
|
"3723000,1:02:03.000",
|
||||||
"3000,00:03",
|
"3000,00:03.000",
|
||||||
"4442401000,1234:00:01"
|
"4442401000,1234:00:01.000"
|
||||||
})
|
})
|
||||||
void testFormat(final long millis, final String time) {
|
void testFormat(final long millis, final String time) {
|
||||||
assertEquals(time, timeFormatter.format(millis));
|
assertEquals(time, timeFormatter.format(millis));
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ module com.github.gtache.autosubtitle.gui.run {
|
|||||||
requires com.github.gtache.autosubtitle.whisperx;
|
requires com.github.gtache.autosubtitle.whisperx;
|
||||||
requires javafx.fxml;
|
requires javafx.fxml;
|
||||||
requires javafx.graphics;
|
requires javafx.graphics;
|
||||||
|
requires guava;
|
||||||
|
|
||||||
opens com.github.gtache.autosubtitle.gui.run to javafx.graphics;
|
opens com.github.gtache.autosubtitle.gui.run to javafx.graphics;
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@ import com.github.gtache.autosubtitle.modules.setup.whisper.base.WhisperSetupMod
|
|||||||
import com.github.gtache.autosubtitle.modules.subtitle.extractor.whisper.base.WhisperExtractorModule;
|
import com.github.gtache.autosubtitle.modules.subtitle.extractor.whisper.base.WhisperExtractorModule;
|
||||||
import com.github.gtache.autosubtitle.modules.subtitle.parser.json.whisper.base.WhisperJsonModule;
|
import com.github.gtache.autosubtitle.modules.subtitle.parser.json.whisper.base.WhisperJsonModule;
|
||||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
||||||
import com.github.gtache.autosubtitle.whisper.WhisperExtractionModelProvider;
|
import com.github.gtache.autosubtitle.whisper.base.WhisperExtractionModelProvider;
|
||||||
import dagger.Binds;
|
import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package com.github.gtache.autosubtitle.whisper;
|
package com.github.gtache.autosubtitle.whisper.base;
|
||||||
|
|
||||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||||
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
||||||
|
import com.github.gtache.autosubtitle.whisper.WhisperModels;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
@@ -8,8 +8,9 @@ module com.github.gtache.autosubtitle.whisper.base {
|
|||||||
requires com.google.gson;
|
requires com.google.gson;
|
||||||
|
|
||||||
exports com.github.gtache.autosubtitle.setup.whisper.base;
|
exports com.github.gtache.autosubtitle.setup.whisper.base;
|
||||||
exports com.github.gtache.autosubtitle.modules.whisper.base;
|
|
||||||
exports com.github.gtache.autosubtitle.modules.setup.whisper.base;
|
|
||||||
exports com.github.gtache.autosubtitle.subtitle.extractor.whisper.base;
|
exports com.github.gtache.autosubtitle.subtitle.extractor.whisper.base;
|
||||||
|
exports com.github.gtache.autosubtitle.whisper.base;
|
||||||
|
exports com.github.gtache.autosubtitle.modules.setup.whisper.base;
|
||||||
exports com.github.gtache.autosubtitle.modules.subtitle.extractor.whisper.base;
|
exports com.github.gtache.autosubtitle.modules.subtitle.extractor.whisper.base;
|
||||||
|
exports com.github.gtache.autosubtitle.modules.whisper.base;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.github.gtache.autosubtitle.whisper.base;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModelProvider;
|
||||||
|
import com.github.gtache.autosubtitle.whisper.WhisperModels;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class TestWhisperExtractionModelProvider {
|
||||||
|
|
||||||
|
private final ExtractionModelProvider provider = new WhisperExtractionModelProvider();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetAvailableExtractionModels() {
|
||||||
|
assertEquals(Arrays.asList(WhisperModels.values()), provider.getAvailableExtractionModels());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetDefaultExtractionModel() {
|
||||||
|
assertEquals(WhisperModels.MEDIUM, provider.getDefaultExtractionModel());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetExtractionModel() {
|
||||||
|
for (final var value : WhisperModels.values()) {
|
||||||
|
assertEquals(value, provider.getExtractionModel(value.name()));
|
||||||
|
assertEquals(value, provider.getExtractionModel(value.name().toLowerCase()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,5 +22,4 @@ public final class WhisperCommonSetupModule {
|
|||||||
final OS os) {
|
final OS os) {
|
||||||
return new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
return new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.Logger;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -72,45 +73,40 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
|
|||||||
listeners.clear();
|
listeners.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyListeners(final ExtractEvent event) {
|
void notifyListeners(final ExtractEvent event) {
|
||||||
listeners.forEach(listener -> listener.listen(event));
|
listeners.forEach(listener -> listener.listen(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SubtitleCollection<Subtitle> extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException {
|
public SubtitleCollection<Subtitle> extract(final Video video, final Language language, final ExtractionModel model) throws ExtractException {
|
||||||
if (video instanceof final File f) {
|
return extract(new AudioOrVideo(video), language, model);
|
||||||
return extract(f.path(), language, model, video.info().duration());
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SubtitleCollection<Subtitle> extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException {
|
||||||
|
return extract(new AudioOrVideo(audio), language, model);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SubtitleCollection<Subtitle> extract(final AudioOrVideo av, final Language language, final ExtractionModel model) throws ExtractException {
|
||||||
|
if (av.inner() instanceof final File f) {
|
||||||
|
return extract(f.path(), language, model, av.info().duration());
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
final var path = Files.createTempFile(AUTOSUBTITLE, video.info().videoFormat());
|
return dumpExtract(av, language, model);
|
||||||
try (final var in = video.getInputStream()) {
|
|
||||||
Files.copy(in, path);
|
|
||||||
final var ret = extract(path, language, model, video.info().duration());
|
|
||||||
Files.deleteIfExists(path);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
throw new ExtractException(e);
|
throw new ExtractException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private SubtitleCollection<Subtitle> dumpExtract(final AudioOrVideo av, final Language language, final ExtractionModel model) throws ExtractException, IOException {
|
||||||
public SubtitleCollection<Subtitle> extract(final Audio audio, final Language language, final ExtractionModel model) throws ExtractException {
|
final var path = Files.createTempFile(AUTOSUBTITLE, "." + av.info().format());
|
||||||
if (audio instanceof final File f) {
|
try (final var in = av.getInputStream()) {
|
||||||
return extract(f.path(), language, model, audio.info().duration());
|
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
|
||||||
} else {
|
return extract(path, language, model, av.info().duration());
|
||||||
try {
|
} finally {
|
||||||
final var path = Files.createTempFile(AUTOSUBTITLE, audio.info().audioFormat());
|
Files.deleteIfExists(path);
|
||||||
try (final var in = audio.getInputStream()) {
|
|
||||||
Files.copy(in, path);
|
|
||||||
final var ret = extract(path, language, model, audio.info().duration());
|
|
||||||
Files.deleteIfExists(path);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new ExtractException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package com.github.gtache.autosubtitle.subtitle.extractor.whisper;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.Audio;
|
||||||
|
import com.github.gtache.autosubtitle.AudioInfo;
|
||||||
|
import com.github.gtache.autosubtitle.Video;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import static java.util.Objects.requireNonNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used internally for the Whisper subtitle extractor. Either audio or video must be not null
|
||||||
|
*
|
||||||
|
* @param audio The possible audio
|
||||||
|
* @param video The possible video
|
||||||
|
*/
|
||||||
|
public record AudioOrVideo(Audio audio, Video video) implements Audio {
|
||||||
|
|
||||||
|
public AudioOrVideo {
|
||||||
|
if (audio == null) {
|
||||||
|
requireNonNull(video);
|
||||||
|
} else if (video != null) {
|
||||||
|
throw new IllegalArgumentException("Either audio or video must be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioOrVideo(final Audio audio) {
|
||||||
|
this(audio, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioOrVideo(final Video video) {
|
||||||
|
this(null, video);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T inner() {
|
||||||
|
return (T) (audio == null ? video : audio);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
if (audio == null) {
|
||||||
|
return video.getInputStream();
|
||||||
|
} else {
|
||||||
|
return audio.getInputStream();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AudioInfo info() {
|
||||||
|
if (audio == null) {
|
||||||
|
return video.info();
|
||||||
|
} else {
|
||||||
|
return audio.info();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.github.gtache.autosubtitle.modules.setup.whisper;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.impl.OS;
|
||||||
|
import com.github.gtache.autosubtitle.setup.whisper.WhisperSetupConfiguration;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
class TestWhisperCommonSetupModule {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testWhisperSetupConfiguration() {
|
||||||
|
final var root = mock(Path.class);
|
||||||
|
final var venvPath = mock(Path.class);
|
||||||
|
final var pythonVersion = "3.10";
|
||||||
|
final var os = OS.LINUX;
|
||||||
|
final var expected = new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||||
|
assertEquals(expected, WhisperCommonSetupModule.providesWhisperSetupConfiguration(root, venvPath, pythonVersion, os));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,171 @@
|
|||||||
|
package com.github.gtache.autosubtitle.setup.whisper;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.impl.OS;
|
||||||
|
import com.github.gtache.autosubtitle.process.ProcessRunner;
|
||||||
|
import com.github.gtache.autosubtitle.setup.SetupException;
|
||||||
|
import com.github.gtache.autosubtitle.setup.conda.CondaSetupManager;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static com.github.gtache.autosubtitle.setup.SetupStatus.BUNDLE_INSTALLED;
|
||||||
|
import static com.github.gtache.autosubtitle.setup.SetupStatus.NOT_INSTALLED;
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class TestAbstractWhisperSetupManager {
|
||||||
|
|
||||||
|
private final CondaSetupManager condaSetupManager;
|
||||||
|
private final WhisperSetupConfiguration configuration;
|
||||||
|
private final ProcessRunner processRunner;
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
private final AbstractWhisperSetupManager setupManager;
|
||||||
|
|
||||||
|
TestAbstractWhisperSetupManager(@Mock final CondaSetupManager condaSetupManager, @Mock final WhisperSetupConfiguration configuration,
|
||||||
|
@Mock final ProcessRunner processRunner, @Mock final HttpClient httpClient) {
|
||||||
|
this.condaSetupManager = Objects.requireNonNull(condaSetupManager);
|
||||||
|
when(condaSetupManager.name()).thenReturn("conda");
|
||||||
|
this.configuration = Objects.requireNonNull(configuration);
|
||||||
|
this.processRunner = Objects.requireNonNull(processRunner);
|
||||||
|
this.httpClient = Objects.requireNonNull(httpClient);
|
||||||
|
this.setupManager = spy(new DummyWhisperSetupManager(condaSetupManager, configuration, processRunner, httpClient));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetStatus() throws SetupException {
|
||||||
|
assertEquals(NOT_INSTALLED, setupManager.getStatus());
|
||||||
|
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||||
|
assertEquals(BUNDLE_INSTALLED, setupManager.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallAlreadyInstalled() throws SetupException {
|
||||||
|
final var venvPath = Paths.get("path");
|
||||||
|
when(configuration.venvPath()).thenReturn(venvPath);
|
||||||
|
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||||
|
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||||
|
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||||
|
setupManager.install();
|
||||||
|
verify(condaSetupManager, never()).install();
|
||||||
|
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||||
|
verify(setupManager, never()).installWhisper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallWhisper() throws SetupException {
|
||||||
|
final var venvPath = Paths.get("path");
|
||||||
|
when(configuration.venvPath()).thenReturn(venvPath);
|
||||||
|
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||||
|
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||||
|
setupManager.install();
|
||||||
|
verify(condaSetupManager, never()).install();
|
||||||
|
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||||
|
verify(setupManager).installWhisper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallVenv() throws SetupException {
|
||||||
|
final var venvPath = Paths.get("path");
|
||||||
|
final var pythonVersion = "3.10";
|
||||||
|
when(configuration.venvPath()).thenReturn(venvPath);
|
||||||
|
when(configuration.pythonVersion()).thenReturn(pythonVersion);
|
||||||
|
when(condaSetupManager.isInstalled()).thenReturn(true);
|
||||||
|
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||||
|
setupManager.install();
|
||||||
|
verify(condaSetupManager, never()).install();
|
||||||
|
verify(condaSetupManager).createVenv(venvPath, pythonVersion);
|
||||||
|
verify(setupManager, never()).installWhisper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInstallConda() throws SetupException {
|
||||||
|
final var venvPath = Paths.get("path");
|
||||||
|
final var pythonVersion = "3.10";
|
||||||
|
when(configuration.venvPath()).thenReturn(venvPath);
|
||||||
|
when(configuration.pythonVersion()).thenReturn(pythonVersion);
|
||||||
|
when(condaSetupManager.isInstalled()).thenReturn(false);
|
||||||
|
when(condaSetupManager.venvExists(venvPath)).thenReturn(true);
|
||||||
|
doReturn(true).when(setupManager).isWhisperInstalled();
|
||||||
|
setupManager.install();
|
||||||
|
verify(condaSetupManager).install();
|
||||||
|
verify(condaSetupManager, never()).createVenv(any(), any());
|
||||||
|
verify(setupManager, never()).installWhisper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUninstall(@TempDir final Path tempDir) throws SetupException, IOException {
|
||||||
|
final var subfolder = tempDir.resolve("subfolder");
|
||||||
|
Files.createDirectory(subfolder);
|
||||||
|
final var subfile = subfolder.resolve("subfile");
|
||||||
|
Files.createFile(subfile);
|
||||||
|
final var rootFile = tempDir.resolve("rootfile");
|
||||||
|
Files.createFile(rootFile);
|
||||||
|
when(configuration.root()).thenReturn(tempDir);
|
||||||
|
setupManager.uninstall();
|
||||||
|
assertFalse(Files.exists(tempDir));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateNotAvailable() throws SetupException {
|
||||||
|
setupManager.update();
|
||||||
|
verify(condaSetupManager).isUpdateAvailable();
|
||||||
|
verify(condaSetupManager, never()).update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testUpdateAvailable() throws SetupException {
|
||||||
|
when(condaSetupManager.isUpdateAvailable()).thenReturn(true);
|
||||||
|
setupManager.update();
|
||||||
|
verify(condaSetupManager).isUpdateAvailable();
|
||||||
|
verify(condaSetupManager).update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPythonPath() {
|
||||||
|
final var path = Paths.get("path");
|
||||||
|
when(configuration.venvPath()).thenReturn(path);
|
||||||
|
when(configuration.os()).thenReturn(OS.WINDOWS);
|
||||||
|
assertEquals(path.resolve("python.exe"), setupManager.getPythonPath());
|
||||||
|
when(configuration.os()).thenReturn(OS.LINUX);
|
||||||
|
assertEquals(path.resolve("python"), setupManager.getPythonPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIllegal() {
|
||||||
|
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(null, configuration, processRunner, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, null, processRunner, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, configuration, null, httpClient));
|
||||||
|
assertThrows(NullPointerException.class, () -> new DummyWhisperSetupManager(condaSetupManager, configuration, processRunner, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class DummyWhisperSetupManager extends AbstractWhisperSetupManager {
|
||||||
|
|
||||||
|
private DummyWhisperSetupManager(final CondaSetupManager condaSetupManager, final WhisperSetupConfiguration configuration, final ProcessRunner processRunner, final HttpClient httpClient) {
|
||||||
|
super(condaSetupManager, configuration, processRunner, httpClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void installWhisper() throws SetupException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isWhisperInstalled() throws SetupException {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "Dummy";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.github.gtache.autosubtitle.setup.whisper;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.impl.OS;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class TestWhisperSetupConfiguration {
|
||||||
|
|
||||||
|
private final Path root;
|
||||||
|
private final Path venvPath;
|
||||||
|
private final String pythonVersion;
|
||||||
|
private final OS os;
|
||||||
|
|
||||||
|
TestWhisperSetupConfiguration(@Mock final Path root, @Mock final Path venvPath) {
|
||||||
|
this.root = Objects.requireNonNull(root);
|
||||||
|
this.venvPath = Objects.requireNonNull(venvPath);
|
||||||
|
this.pythonVersion = "3.10";
|
||||||
|
this.os = OS.LINUX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetters() {
|
||||||
|
final var configuration = new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
|
||||||
|
assertEquals(root, configuration.root());
|
||||||
|
assertEquals(venvPath, configuration.venvPath());
|
||||||
|
assertEquals(pythonVersion, configuration.pythonVersion());
|
||||||
|
assertEquals(os, configuration.os());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testIllegal() {
|
||||||
|
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(null, venvPath, pythonVersion, os));
|
||||||
|
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, null, pythonVersion, os));
|
||||||
|
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, venvPath, null, os));
|
||||||
|
assertThrows(NullPointerException.class, () -> new WhisperSetupConfiguration(root, venvPath, pythonVersion, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
package com.github.gtache.autosubtitle.subtitle.extractor.whisper;
|
||||||
|
|
||||||
|
import com.github.gtache.autosubtitle.Audio;
|
||||||
|
import com.github.gtache.autosubtitle.AudioInfo;
|
||||||
|
import com.github.gtache.autosubtitle.Language;
|
||||||
|
import com.github.gtache.autosubtitle.Video;
|
||||||
|
import com.github.gtache.autosubtitle.VideoInfo;
|
||||||
|
import com.github.gtache.autosubtitle.impl.FileAudioImpl;
|
||||||
|
import com.github.gtache.autosubtitle.impl.OS;
|
||||||
|
import com.github.gtache.autosubtitle.process.ProcessListener;
|
||||||
|
import com.github.gtache.autosubtitle.process.ProcessResult;
|
||||||
|
import com.github.gtache.autosubtitle.process.ProcessRunner;
|
||||||
|
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.converter.SubtitleConverterProvider;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractEvent;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractException;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.ExtractionModel;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
|
||||||
|
import com.github.gtache.autosubtitle.subtitle.extractor.impl.ExtractEventImpl;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class TestAbstractWhisperSubtitleExtractor {
|
||||||
|
|
||||||
|
private final Path venvPath;
|
||||||
|
private final SubtitleConverter<Subtitle> converter;
|
||||||
|
private final SubtitleConverterProvider converterProvider;
|
||||||
|
private final ProcessRunner processRunner;
|
||||||
|
private final ProcessListener processListener;
|
||||||
|
private final ProcessResult processResult;
|
||||||
|
private final OS os;
|
||||||
|
private final DummyWhisperSubtitleExtractor extractor;
|
||||||
|
|
||||||
|
private final AudioInfo audioInfo;
|
||||||
|
private final VideoInfo videoInfo;
|
||||||
|
private final ExtractionModel extractionModel;
|
||||||
|
private final SubtitleCollection<Subtitle> collection;
|
||||||
|
|
||||||
|
|
||||||
|
TestAbstractWhisperSubtitleExtractor(@Mock final SubtitleConverterProvider converterProvider, @Mock final SubtitleConverter<Subtitle> converter,
|
||||||
|
@Mock final ProcessRunner processRunner, @Mock final ProcessListener processListener,
|
||||||
|
@Mock final ProcessResult processResult, @Mock final VideoInfo videoInfo,
|
||||||
|
@Mock final AudioInfo audioInfo, @Mock final ExtractionModel extractionModel,
|
||||||
|
@Mock final SubtitleCollection<Subtitle> collection) throws IOException {
|
||||||
|
this.venvPath = Path.of("venv");
|
||||||
|
this.os = OS.LINUX;
|
||||||
|
this.converterProvider = Objects.requireNonNull(converterProvider);
|
||||||
|
this.converter = Objects.requireNonNull(converter);
|
||||||
|
doReturn(converter).when(converterProvider).getConverter("json");
|
||||||
|
this.processRunner = Objects.requireNonNull(processRunner);
|
||||||
|
this.processListener = Objects.requireNonNull(processListener);
|
||||||
|
this.processResult = Objects.requireNonNull(processResult);
|
||||||
|
when(processRunner.startListen(anyList())).thenReturn(processListener);
|
||||||
|
when(processListener.join(Duration.ofHours(1))).thenReturn(processResult);
|
||||||
|
this.extractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, os);
|
||||||
|
|
||||||
|
this.audioInfo = Objects.requireNonNull(audioInfo);
|
||||||
|
when(audioInfo.format()).thenReturn("mp3");
|
||||||
|
this.videoInfo = Objects.requireNonNull(videoInfo);
|
||||||
|
when(videoInfo.format()).thenReturn("mp4");
|
||||||
|
this.extractionModel = Objects.requireNonNull(extractionModel);
|
||||||
|
this.collection = Objects.requireNonNull(collection);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testNotifyListeners() {
|
||||||
|
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||||
|
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||||
|
final var event = mock(ExtractEvent.class);
|
||||||
|
extractor.addListener(listener1);
|
||||||
|
extractor.addListener(listener2);
|
||||||
|
|
||||||
|
extractor.notifyListeners(event);
|
||||||
|
|
||||||
|
verify(listener1).listen(event);
|
||||||
|
verify(listener2).listen(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRemoveListener() {
|
||||||
|
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||||
|
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||||
|
extractor.addListener(listener1);
|
||||||
|
extractor.addListener(listener2);
|
||||||
|
extractor.removeListener(listener2);
|
||||||
|
extractor.notifyListeners(mock(ExtractEvent.class));
|
||||||
|
verify(listener1).listen(any());
|
||||||
|
verifyNoInteractions(listener2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testRemoveListeners() {
|
||||||
|
final var listener1 = mock(SubtitleExtractorListener.class);
|
||||||
|
final var listener2 = mock(SubtitleExtractorListener.class);
|
||||||
|
extractor.addListener(listener1);
|
||||||
|
extractor.addListener(listener2);
|
||||||
|
extractor.removeListeners();
|
||||||
|
extractor.notifyListeners(mock(ExtractEvent.class));
|
||||||
|
verifyNoInteractions(listener1, listener2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractAudioNotFileException() throws IOException {
|
||||||
|
final var audio = mock(Audio.class);
|
||||||
|
when(audio.info()).thenReturn(audioInfo);
|
||||||
|
when(audio.getInputStream()).thenThrow(IOException.class);
|
||||||
|
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractAudioFileException() throws IOException {
|
||||||
|
final var path = Paths.get("path");
|
||||||
|
final var audio = new FileAudioImpl(path, audioInfo);
|
||||||
|
doThrow(IOException.class).when(processListener).readLine();
|
||||||
|
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractAudioFileParseException() throws ParseException {
|
||||||
|
final var path = Paths.get("path.path");
|
||||||
|
final var audio = new FileAudioImpl(path, audioInfo);
|
||||||
|
doThrow(ParseException.class).when(converter).parse(any(Path.class));
|
||||||
|
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||||
|
verify(converter).parse(any(Path.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractAudioFileBadResultCode() {
|
||||||
|
final var path = Paths.get("path");
|
||||||
|
final var audio = new FileAudioImpl(path, audioInfo);
|
||||||
|
when(processResult.exitCode()).thenReturn(1);
|
||||||
|
assertThrows(ExtractException.class, () -> extractor.extract(audio, Language.EN, extractionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractVideoNotFileException() throws IOException {
|
||||||
|
final var video = mock(Video.class);
|
||||||
|
when(video.info()).thenReturn(videoInfo);
|
||||||
|
when(video.getInputStream()).thenThrow(IOException.class);
|
||||||
|
assertThrows(ExtractException.class, () -> extractor.extract(video, Language.EN, extractionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testExtractVideoFile() throws IOException, ParseException, ExtractException {
|
||||||
|
final var video = mock(Video.class);
|
||||||
|
when(video.info()).thenReturn(videoInfo);
|
||||||
|
final var in = new ByteArrayInputStream("test".getBytes());
|
||||||
|
when(video.getInputStream()).thenReturn(in);
|
||||||
|
when(converter.parse(any(Path.class))).thenReturn(collection);
|
||||||
|
assertEquals(collection, extractor.extract(video, Language.EN, extractionModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testReadLines() throws IOException, ExtractException, ParseException {
|
||||||
|
final var video = mock(Video.class);
|
||||||
|
when(video.info()).thenReturn(videoInfo);
|
||||||
|
when(videoInfo.duration()).thenReturn(100000L);
|
||||||
|
final var in = new ByteArrayInputStream("test".getBytes());
|
||||||
|
when(video.getInputStream()).thenReturn(in);
|
||||||
|
when(converter.parse(any(Path.class))).thenReturn(collection);
|
||||||
|
when(processListener.readLine()).thenReturn("Progress: 1.7abcd", "[00:12.234 --> 00:13.234] Hello", "98%|bbb", "abcd", null);
|
||||||
|
final var listener = mock(SubtitleExtractorListener.class);
|
||||||
|
extractor.addListener(listener);
|
||||||
|
assertEquals(collection, extractor.extract(video, Language.EN, extractionModel));
|
||||||
|
verify(listener).listen(new ExtractEventImpl("Progress: 1.7abcd", 0.017));
|
||||||
|
verify(listener).listen(new ExtractEventImpl("[00:12.234 --> 00:13.234] Hello", 0.13234));
|
||||||
|
verify(listener).listen(new ExtractEventImpl("98%|bbb", 0.98));
|
||||||
|
verify(listener).listen(new ExtractEventImpl("abcd", 0.98));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPythonPath() {
|
||||||
|
assertEquals(venvPath.resolve("python"), extractor.getPythonPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGetPythonPathWindows() {
|
||||||
|
final var windowsExtractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, OS.WINDOWS);
|
||||||
|
assertEquals(venvPath.resolve("python.exe"), windowsExtractor.getPythonPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class DummyWhisperSubtitleExtractor extends AbstractWhisperSubtitleExtractor {
|
||||||
|
|
||||||
|
private DummyWhisperSubtitleExtractor(final Path venvPath, final SubtitleConverterProvider converterProvider, final ProcessRunner processRunner, final OS os) {
|
||||||
|
super(venvPath, converterProvider, processRunner, os);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<String> createArgs(final Path path, final Language language, final ExtractionModel model, final Path outputDir) {
|
||||||
|
return List.of(path.toString(), language.toString(), model.toString(), outputDir.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.github.gtache.autosubtitle.whisper;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
class TestWhisperModels {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testHasEnglishSpecific() {
|
||||||
|
for (final var model : WhisperModels.values()) {
|
||||||
|
assertEquals(model != WhisperModels.LARGE, model.hasEnglishSpecific());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user