Adds WhisperX, reworks UI (still needs some work), theoretically usable
This commit is contained in:
20
conda/pom.xml
Normal file
20
conda/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.github.gtache.autosubtitle</groupId>
|
||||
<artifactId>autosubtitle</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>autosubtitle-conda</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.gtache.autosubtitle</groupId>
|
||||
<artifactId>autosubtitle-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaBundledPath {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaInstallerPath {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaMinimumMajorVersion {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaMinimumMinorVersion {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaRootPath {
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.Architecture;
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import com.github.gtache.autosubtitle.modules.setup.impl.CacheRoot;
|
||||
import com.github.gtache.autosubtitle.modules.setup.impl.ToolsRoot;
|
||||
import com.github.gtache.autosubtitle.setup.conda.CondaSetupConfiguration;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Setup module for Conda
|
||||
*/
|
||||
@Module
|
||||
public final class CondaSetupModule {
|
||||
|
||||
private static final String CONDA = "conda";
|
||||
private static final String MINICONDA3 = "miniconda3";
|
||||
|
||||
private CondaSetupModule() {
|
||||
|
||||
}
|
||||
|
||||
@Provides
|
||||
static CondaSetupConfiguration providesCondaSetupConfiguration(@CondaSystemPath final Path condaSystemPath, @CondaBundledPath final Path condaBundledPath,
|
||||
@CondaMinimumMajorVersion final int condaMinimumMajorVersion, @CondaMinimumMinorVersion final int condaMinimumMinorVersion,
|
||||
@CondaInstallerPath final Path condaInstallerPath, @CondaRootPath final Path condaRootPath,
|
||||
final OS os, final Architecture architecture) {
|
||||
return new CondaSetupConfiguration(condaRootPath, condaSystemPath, condaBundledPath, condaMinimumMajorVersion, condaMinimumMinorVersion, condaInstallerPath, os, architecture);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaSystemPath
|
||||
static Path providesCondaSystemPath(final OS os) {
|
||||
return Paths.get(os == OS.WINDOWS ? CONDA + ".bat" : CONDA);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaBundledPath
|
||||
static Path providesCondaBundledPath(@CondaRootPath final Path root, final OS os) {
|
||||
return root.resolve("condabin").resolve(Paths.get(os == OS.WINDOWS ? CONDA + ".bat" : CONDA));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaMinimumMajorVersion
|
||||
static int providesCondaMinimumMajorVersion() {
|
||||
return 24;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaMinimumMinorVersion
|
||||
static int providesCondaMinimumMinorVersion() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaRootPath
|
||||
static Path providesCondaRootPath(@ToolsRoot final Path root) {
|
||||
return root.resolve(MINICONDA3);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@CondaInstallerPath
|
||||
static Path providesCondaInstallerPath(@CacheRoot final Path root, final OS os) {
|
||||
return root.resolve("conda-install" + (os == OS.WINDOWS ? ".exe" : ".sh"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
|
||||
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 CondaSystemPath {
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.github.gtache.autosubtitle.setup.conda;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.Architecture;
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Configuration for conda setup
|
||||
*/
|
||||
public record CondaSetupConfiguration(Path condaRootPath, Path condaSystemPath, Path condaBundledPath,
|
||||
int condaMinimumMajorVersion, int condaMinimumMinorVersion,
|
||||
Path condaInstallerPath, OS os, Architecture architecture) {
|
||||
|
||||
public CondaSetupConfiguration {
|
||||
Objects.requireNonNull(condaRootPath);
|
||||
Objects.requireNonNull(condaSystemPath);
|
||||
Objects.requireNonNull(condaBundledPath);
|
||||
if (condaMinimumMajorVersion <= 0) {
|
||||
throw new IllegalArgumentException("Conda minimum major version must be > 0 : " + condaMinimumMajorVersion);
|
||||
}
|
||||
if (condaMinimumMinorVersion < 0) {
|
||||
throw new IllegalArgumentException("Conda minimum minor version must be >= 0 : " + condaMinimumMinorVersion);
|
||||
}
|
||||
Objects.requireNonNull(condaInstallerPath);
|
||||
Objects.requireNonNull(os);
|
||||
Objects.requireNonNull(architecture);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.github.gtache.autosubtitle.setup.conda;
|
||||
|
||||
import com.github.gtache.autosubtitle.impl.OS;
|
||||
import com.github.gtache.autosubtitle.setup.SetupException;
|
||||
import com.github.gtache.autosubtitle.setup.SetupStatus;
|
||||
import com.github.gtache.autosubtitle.setup.impl.AbstractSetupManager;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.net.http.HttpClient;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
/**
|
||||
* Setup manager for Conda
|
||||
*/
|
||||
@Singleton
|
||||
public class CondaSetupManager extends AbstractSetupManager {
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(CondaSetupManager.class);
|
||||
|
||||
private final CondaSetupConfiguration configuration;
|
||||
|
||||
@Inject
|
||||
CondaSetupManager(final CondaSetupConfiguration configuration, final HttpClient httpClient) {
|
||||
super(httpClient);
|
||||
this.configuration = requireNonNull(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "conda";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SetupStatus getStatus() throws SetupException {
|
||||
if (isSystemCondaInstalled()) {
|
||||
return SetupStatus.SYSTEM_INSTALLED;
|
||||
} else if (isBundledCondaInstalled()) {
|
||||
return SetupStatus.BUNDLE_INSTALLED;
|
||||
} else {
|
||||
return SetupStatus.NOT_INSTALLED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void install() throws SetupException {
|
||||
if (!isSystemCondaInstalled() && !isBundledCondaInstalled()) {
|
||||
installConda();
|
||||
}
|
||||
}
|
||||
|
||||
private void installConda() throws SetupException {
|
||||
final var installerPath = configuration.condaInstallerPath();
|
||||
if (Files.exists(installerPath)) {
|
||||
logger.info("Conda exists at {}", installerPath);
|
||||
} else {
|
||||
logger.info("Conda installer not found, downloading");
|
||||
downloadConda();
|
||||
logger.info("Conda downloaded");
|
||||
}
|
||||
switch (configuration.os()) {
|
||||
case OS.WINDOWS -> installWindows();
|
||||
case OS.MAC, OS.LINUX -> installLinux();
|
||||
}
|
||||
}
|
||||
|
||||
private void installLinux() throws SetupException {
|
||||
try {
|
||||
final var installerPath = configuration.condaInstallerPath();
|
||||
final var rootPath = configuration.condaRootPath();
|
||||
logger.info("Installing conda using {}", installerPath);
|
||||
final var result = run(List.of("bash", installerPath.toString(), "-b", "-p", rootPath.toString()), Duration.ofMinutes(15));
|
||||
if (result.exitCode() == 0) {
|
||||
logger.info("Installed conda to {}", rootPath);
|
||||
} else {
|
||||
throw new SetupException("Error installing conda: " + result);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void installWindows() throws SetupException {
|
||||
try {
|
||||
final var installerPath = configuration.condaInstallerPath();
|
||||
final var rootPath = configuration.condaRootPath();
|
||||
logger.info("Installing conda using {}", installerPath);
|
||||
final var result = run(List.of(installerPath.toString(), "/InstallationType=JustMe", "/RegisterPython=0", "/S", "/D=" + rootPath.toString()), Duration.ofMinutes(15));
|
||||
if (result.exitCode() == 0) {
|
||||
logger.info("Installed conda to {}", rootPath);
|
||||
} else {
|
||||
throw new SetupException("Error installing conda: " + result);
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadConda() throws SetupException {
|
||||
switch (configuration.os()) {
|
||||
case OS.WINDOWS -> downloadCondaWindows();
|
||||
case OS.MAC -> downloadCondaMac();
|
||||
case OS.LINUX -> downloadCondaLinux();
|
||||
}
|
||||
logger.info("Downloaded conda to {}", configuration.condaInstallerPath());
|
||||
}
|
||||
|
||||
private void downloadCondaLinux() throws SetupException {
|
||||
final var architecture = configuration.architecture();
|
||||
if (architecture.isAMD64()) {
|
||||
downloadConda("https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh");
|
||||
} else if (architecture.isARM64()) {
|
||||
downloadConda("https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh");
|
||||
} else {
|
||||
throw new SetupException("Unsupported architecture: " + architecture);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadCondaMac() throws SetupException {
|
||||
final var architecture = configuration.architecture();
|
||||
if (architecture.isAMD64()) {
|
||||
downloadConda("https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh");
|
||||
} else if (architecture.isARM64()) {
|
||||
downloadConda("https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-arm64.sh");
|
||||
} else {
|
||||
throw new SetupException("Unsupported architecture: " + architecture);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloadCondaWindows() throws SetupException {
|
||||
final var url = "https://repo.anaconda.com/miniconda/Miniconda3-latest-Windows-x86_64.exe";
|
||||
downloadConda(url);
|
||||
}
|
||||
|
||||
private void downloadConda(final String url) throws SetupException {
|
||||
download(url, configuration.condaInstallerPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstall() throws SetupException {
|
||||
deleteFolder(configuration.condaRootPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update() throws SetupException {
|
||||
try {
|
||||
final var result = run(List.of(getCondaPath().toString(), "update", "-y", "conda"), Duration.ofMinutes(15));
|
||||
if (result.exitCode() == 0) {
|
||||
logger.info("Conda updated");
|
||||
} else {
|
||||
throw new SetupException("Error updating conda: " + result.output());
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createVenv(final Path path, final String pythonVersion, final String... packages) throws SetupException {
|
||||
final var args = Stream.concat(Stream.of(getCondaPath().toString(), "create", "-y", "-p", path.toString(), "python=" + pythonVersion), Arrays.stream(packages)).toList();
|
||||
try {
|
||||
logger.info("Creating venv {}", path);
|
||||
final var result = run(args, Duration.ofMinutes(15));
|
||||
if (result.exitCode() == 0) {
|
||||
logger.info("Created venv {}", path);
|
||||
} else {
|
||||
throw new SetupException("Error creating venv " + path + ": " + result.output());
|
||||
}
|
||||
// On Windows, we need to copy the DLLs otherwise pip may not work
|
||||
if (configuration.os() == OS.WINDOWS) {
|
||||
final var sourceFolder = path.resolve("Library").resolve("bin");
|
||||
try (final var files = Files.find(sourceFolder, 1, (p, a) -> p.getFileName().toString().contains("libcrypto") || p.getFileName().toString().contains("libssl"))) {
|
||||
final var fileList = files.toList();
|
||||
final var targetFolder = path.resolve("DLLs");
|
||||
for (final var s : fileList) {
|
||||
Files.copy(s, targetFolder.resolve(s.getFileName()));
|
||||
}
|
||||
}
|
||||
logger.info("Copied DLLs (Windows)");
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean venvExists(final Path path) {
|
||||
return Files.exists(path.resolve("bin").resolve(configuration.os() == OS.WINDOWS ? "python.exe" : "python"));
|
||||
}
|
||||
|
||||
private Path getCondaPath() throws SetupException {
|
||||
return isSystemCondaInstalled() ? configuration.condaSystemPath() : configuration.condaBundledPath();
|
||||
}
|
||||
|
||||
private boolean isSystemCondaInstalled() throws SetupException {
|
||||
try {
|
||||
final var result = run(List.of(configuration.condaSystemPath().toString(), "--version"), Duration.ofSeconds(5));
|
||||
if (result.exitCode() == 0) {
|
||||
final var output = result.output().getFirst();
|
||||
final var versionString = output.substring(output.indexOf(' ') + 1);
|
||||
final var version = versionString.split("\\.");
|
||||
if (version.length == 3) {
|
||||
final var major = Integer.parseInt(version[0]);
|
||||
final var minor = Integer.parseInt(version[1]);
|
||||
return major >= configuration.condaMinimumMajorVersion() && minor >= configuration.condaMinimumMinorVersion();
|
||||
} else {
|
||||
throw new SetupException("Unexpected python version: " + versionString);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (final IOException e) {
|
||||
throw new SetupException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isBundledCondaInstalled() {
|
||||
return Files.isRegularFile(configuration.condaBundledPath());
|
||||
}
|
||||
}
|
||||
10
conda/src/main/java/module-info.java
Normal file
10
conda/src/main/java/module-info.java
Normal file
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Module for conda
|
||||
*/
|
||||
module com.github.gtache.autosubtitle.conda {
|
||||
requires transitive com.github.gtache.autosubtitle.core;
|
||||
requires org.apache.logging.log4j;
|
||||
|
||||
exports com.github.gtache.autosubtitle.setup.conda;
|
||||
exports com.github.gtache.autosubtitle.modules.setup.conda;
|
||||
}
|
||||
Reference in New Issue
Block a user