Allows choosing and managing each tool

This commit is contained in:
Guillaume Tâche
2024-10-03 21:55:14 +02:00
parent 0a2f9e0c31
commit df58cf4585
117 changed files with 1547 additions and 1515 deletions

View File

@@ -1,16 +0,0 @@
package com.github.gtache.autosubtitle.modules.setup.whisper;
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 PythonVersion {
}

View File

@@ -1,16 +0,0 @@
package com.github.gtache.autosubtitle.modules.setup.whisper;
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 WhisperBundledRoot {
}

View File

@@ -1,25 +0,0 @@
package com.github.gtache.autosubtitle.modules.setup.whisper;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.modules.setup.conda.CondaSetupModule;
import com.github.gtache.autosubtitle.setup.whisper.WhisperSetupConfiguration;
import dagger.Module;
import dagger.Provides;
import java.nio.file.Path;
@Module(includes = CondaSetupModule.class)
public final class WhisperCommonSetupModule {
private WhisperCommonSetupModule() {
}
@Provides
static WhisperSetupConfiguration providesWhisperSetupConfiguration(@WhisperBundledRoot final Path root,
@WhisperVenvPath final Path venvPath,
@PythonVersion final String pythonVersion,
final OS os) {
return new WhisperSetupConfiguration(root, venvPath, pythonVersion, os);
}
}

View File

@@ -1,16 +0,0 @@
package com.github.gtache.autosubtitle.modules.setup.whisper;
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 WhisperVenvPath {
}

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.setup.whisper;
import com.github.gtache.autosubtitle.ToolType;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.setup.SetupAction;
@@ -35,6 +36,11 @@ public abstract class AbstractWhisperSetupManager extends AbstractSetupManager {
this.configuration = requireNonNull(configuration);
}
@Override
public ToolType type() {
return ToolType.SUBTITLE_EXTRACTOR;
}
@Override
protected SetupStatus getStatus() throws SetupException {
if (isWhisperInstalled()) {

View File

@@ -5,17 +5,16 @@ import com.github.gtache.autosubtitle.File;
import com.github.gtache.autosubtitle.Video;
import com.github.gtache.autosubtitle.impl.OS;
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.ExtractOptions;
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractor;
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
import com.github.gtache.autosubtitle.subtitle.extractor.impl.ExtractEventImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -34,7 +33,7 @@ import static java.util.Objects.requireNonNull;
/**
* Base implementation of {@link SubtitleExtractor} for Whisper
*/
public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtractor<Subtitle> {
public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtractor<SubtitleImpl> {
private static final Logger logger = LogManager.getLogger(AbstractWhisperSubtitleExtractor.class);
@@ -44,14 +43,14 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
private static final Pattern TQDM_PROGRESS_PATTERN = Pattern.compile("^(?<progress>\\d{1,3})%\\|.+");
private final Path venvPath;
private final ProcessRunner processRunner;
private final SubtitleConverter converter;
private final SubtitleConverter<SubtitleImpl> converter;
private final OS os;
private final Set<SubtitleExtractorListener> listeners;
protected AbstractWhisperSubtitleExtractor(final Path venvPath, final SubtitleConverterProvider converterProvider,
protected AbstractWhisperSubtitleExtractor(final Path venvPath, final SubtitleConverter<SubtitleImpl> converter,
final ProcessRunner processRunner, final OS os) {
this.venvPath = requireNonNull(venvPath);
this.converter = requireNonNull(converterProvider.getConverter("json"));
this.converter = requireNonNull(converter);
this.processRunner = requireNonNull(processRunner);
this.os = requireNonNull(os);
this.listeners = new HashSet<>();
@@ -78,16 +77,16 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
@Override
public SubtitleCollection<Subtitle> extract(final Video video, final ExtractOptions options) throws ExtractException {
public SubtitleCollection<SubtitleImpl> extract(final Video video, final ExtractOptions options) throws ExtractException {
return extract(new AudioOrVideo(video), options);
}
@Override
public SubtitleCollection<Subtitle> extract(final Audio audio, final ExtractOptions options) throws ExtractException {
public SubtitleCollection<SubtitleImpl> extract(final Audio audio, final ExtractOptions options) throws ExtractException {
return extract(new AudioOrVideo(audio), options);
}
private SubtitleCollection<Subtitle> extract(final AudioOrVideo av, final ExtractOptions options) throws ExtractException {
private SubtitleCollection<SubtitleImpl> extract(final AudioOrVideo av, final ExtractOptions options) throws ExtractException {
if (av.inner() instanceof final File f) {
return extract(f.path(), options, av.info().duration());
} else {
@@ -99,7 +98,7 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
}
}
private SubtitleCollection<Subtitle> dumpExtract(final AudioOrVideo av, final ExtractOptions options) throws ExtractException, IOException {
private SubtitleCollection<SubtitleImpl> dumpExtract(final AudioOrVideo av, final ExtractOptions options) throws ExtractException, IOException {
final var path = Files.createTempFile(AUTOSUBTITLE, "." + av.info().format());
try (final var in = av.getInputStream()) {
Files.copy(in, path, StandardCopyOption.REPLACE_EXISTING);
@@ -109,7 +108,7 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
}
}
private SubtitleCollection<Subtitle> extract(final Path path, final ExtractOptions options, final long duration) throws ExtractException {
private SubtitleCollection<SubtitleImpl> extract(final Path path, final ExtractOptions options, final long duration) throws ExtractException {
try {
final var outputDir = Files.createTempDirectory(AUTOSUBTITLE);
final var args = createArgs(path, options, outputDir);
@@ -137,7 +136,7 @@ public abstract class AbstractWhisperSubtitleExtractor implements SubtitleExtrac
}
}
private SubtitleCollection<Subtitle> parseResult(final Path subtitleFile, final ExtractOptions options) throws ExtractException {
private SubtitleCollection<SubtitleImpl> parseResult(final Path subtitleFile, final ExtractOptions options) throws ExtractException {
try {
return converter.parse(subtitleFile, options.parseOptions());
} catch (final ParseException e) {

View File

@@ -10,5 +10,4 @@ module com.github.gtache.autosubtitle.whisper.common {
exports com.github.gtache.autosubtitle.whisper;
exports com.github.gtache.autosubtitle.setup.whisper;
exports com.github.gtache.autosubtitle.subtitle.extractor.whisper;
exports com.github.gtache.autosubtitle.modules.setup.whisper;
}

View File

@@ -1,23 +0,0 @@
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));
}
}

View File

@@ -1,5 +1,6 @@
package com.github.gtache.autosubtitle.setup.whisper;
import com.github.gtache.autosubtitle.ToolType;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.process.ProcessRunner;
import com.github.gtache.autosubtitle.setup.SetupException;
@@ -53,6 +54,11 @@ class TestAbstractWhisperSetupManager {
assertEquals(BUNDLE_INSTALLED, setupManager.getStatus());
}
@Test
void testType() {
assertEquals(ToolType.SUBTITLE_EXTRACTOR, setupManager.type());
}
@Test
void testInstallAlreadyInstalled() throws SetupException {
final var venvPath = Paths.get("path");

View File

@@ -9,17 +9,16 @@ 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.ParseOptions;
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.ExtractOptions;
import com.github.gtache.autosubtitle.subtitle.extractor.SubtitleExtractorListener;
import com.github.gtache.autosubtitle.subtitle.extractor.impl.ExtractEventImpl;
import com.github.gtache.autosubtitle.subtitle.impl.SubtitleImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -42,8 +41,7 @@ import static org.mockito.Mockito.*;
class TestAbstractWhisperSubtitleExtractor {
private final Path venvPath;
private final SubtitleConverter<Subtitle> converter;
private final SubtitleConverterProvider converterProvider;
private final SubtitleConverter<SubtitleImpl> converter;
private final ProcessRunner processRunner;
private final ProcessListener processListener;
private final ProcessResult processResult;
@@ -54,17 +52,16 @@ class TestAbstractWhisperSubtitleExtractor {
private final VideoInfo videoInfo;
private final ExtractOptions options;
private final ParseOptions parseOptions;
private final SubtitleCollection<Subtitle> collection;
private final SubtitleCollection<SubtitleImpl> collection;
TestAbstractWhisperSubtitleExtractor(@Mock final SubtitleConverterProvider converterProvider, @Mock final SubtitleConverter<Subtitle> converter,
TestAbstractWhisperSubtitleExtractor(@Mock final SubtitleConverter<SubtitleImpl> converter,
@Mock final ProcessRunner processRunner, @Mock final ProcessListener processListener,
@Mock final ProcessResult processResult, @Mock final VideoInfo videoInfo,
@Mock final AudioInfo audioInfo, @Mock final ExtractOptions options,
@Mock final ParseOptions parseOptions, @Mock final SubtitleCollection<Subtitle> collection) {
@Mock final ParseOptions parseOptions, @Mock final SubtitleCollection<SubtitleImpl> collection) {
this.venvPath = Path.of("venv");
this.os = OS.LINUX;
this.converterProvider = Objects.requireNonNull(converterProvider);
this.converter = Objects.requireNonNull(converter);
this.processRunner = Objects.requireNonNull(processRunner);
this.processListener = Objects.requireNonNull(processListener);
@@ -78,13 +75,12 @@ class TestAbstractWhisperSubtitleExtractor {
@BeforeEach
void beforeEach() throws IOException {
doReturn(converter).when(converterProvider).getConverter("json");
when(processRunner.startListen(anyList())).thenReturn(processListener);
when(processListener.join(Duration.ofHours(1))).thenReturn(processResult);
when(audioInfo.format()).thenReturn("mp3");
when(videoInfo.format()).thenReturn("mp4");
when(options.parseOptions()).thenReturn(parseOptions);
this.extractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, os);
this.extractor = new DummyWhisperSubtitleExtractor(venvPath, converter, processRunner, os);
}
@Test
@@ -200,14 +196,14 @@ class TestAbstractWhisperSubtitleExtractor {
@Test
void testGetPythonPathWindows() {
final var windowsExtractor = new DummyWhisperSubtitleExtractor(venvPath, converterProvider, processRunner, OS.WINDOWS);
final var windowsExtractor = new DummyWhisperSubtitleExtractor(venvPath, converter, 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);
private DummyWhisperSubtitleExtractor(final Path venvPath, final SubtitleConverter<SubtitleImpl> converter, final ProcessRunner processRunner, final OS os) {
super(venvPath, converter, processRunner, os);
}
@Override