Pipeline working, implements FFmpegSetupManager

This commit is contained in:
Guillaume Tâche
2024-08-09 20:30:21 +02:00
parent c2efb71195
commit 155b011c2b
54 changed files with 984 additions and 314 deletions

View File

@@ -11,7 +11,7 @@ public enum Architecture {
//64 bit
X86, X86_64, AMD64,
//ARM 32 bit
ARM32, ARM, ARMV1, ARMV2, ARMV3, ARMV4, ARMV5, ARMV6, ARMV7, AARCH32,
ARM32, ARM, ARMV1, ARMV2, ARMV3, ARMV4, ARMV5, ARMV6, ARMV7, AARCH32, ARMHF, ARMEL,
//ARM 64 bit
ARM64, ARMV8, ARMV9, AARCH64,
UNKNOWN;

View File

@@ -21,9 +21,4 @@ public record VideoInfoImpl(String videoFormat, int width, int height, long dura
throw new IllegalArgumentException("Duration must be greater than 0 : " + duration);
}
}
@Override
public String videoFormat() {
return videoFormat;
}
}

View File

@@ -2,16 +2,22 @@ package com.github.gtache.autosubtitle.modules.impl;
import com.github.gtache.autosubtitle.impl.Architecture;
import com.github.gtache.autosubtitle.impl.OS;
import com.github.gtache.autosubtitle.modules.setup.impl.SetupModule;
import com.github.gtache.autosubtitle.modules.subtitle.impl.SubtitleModule;
import dagger.Module;
import dagger.Provides;
import javax.inject.Singleton;
/**
* Dagger module for Core
*/
@Module(includes = {SetupModule.class, SubtitleModule.class})
public final class CoreModule {
@Module
public abstract class CoreModule {
private CoreModule() {
}
@Provides
@Singleton
static OS providesOS() {
final var name = System.getProperty("os.name");
if (name.contains("Windows")) {
@@ -24,14 +30,12 @@ public abstract class CoreModule {
}
@Provides
@Singleton
static Architecture providesArchitecture() {
final var arch = System.getProperty("os.arch");
return Architecture.getArchitecture(arch);
}
@Provides
@Singleton
@ExecutableExtension
static String providesExecutableExtension(final OS os) {
return os == OS.WINDOWS ? ".exe" : "";

View File

@@ -0,0 +1,21 @@
package com.github.gtache.autosubtitle.modules.setup.impl;
import dagger.Module;
import dagger.Provides;
import java.net.http.HttpClient;
/**
* Dagger core module for setup
*/
@Module
public final class SetupModule {
private SetupModule() {
}
@Provides
static HttpClient providesHttpClient() {
return HttpClient.newHttpClient();
}
}

View File

@@ -11,10 +11,13 @@ import dagger.multibindings.StringKey;
* Dagger module for subtitles
*/
@Module
public interface SubtitleModule {
public abstract class SubtitleModule {
private SubtitleModule() {
}
@Binds
@IntoMap
@StringKey("srt")
SubtitleConverter bindsSubtitleConverter(final SRTSubtitleConverter converter);
abstract SubtitleConverter bindsSubtitleConverter(final SRTSubtitleConverter converter);
}

View File

@@ -36,6 +36,7 @@ public abstract class AbstractProcessRunner implements ProcessRunner {
@Override
public Process start(final List<String> args) throws IOException {
logger.info("Running {}", args);
final var builder = new ProcessBuilder(args);
builder.redirectErrorStream(true);
return builder.start();
@@ -46,4 +47,22 @@ public abstract class AbstractProcessRunner implements ProcessRunner {
final var process = start(args);
return new ProcessListenerImpl(process);
}
/**
* Runs a process and writes the output to the log
*
* @param args the command
* @return the result
* @throws IOException if an error occurs
*/
protected ProcessResult runListen(final List<String> args) throws IOException {
final var listener = startListen(args);
var line = listener.readLine();
final var processName = args.getFirst();
while (line != null) {
logger.info("[{}]: {}", processName, line);
line = listener.readLine();
}
return listener.join(Duration.ofHours(1));
}
}

View File

@@ -3,7 +3,6 @@ package com.github.gtache.autosubtitle.process.impl;
import com.github.gtache.autosubtitle.process.ProcessListener;
import com.github.gtache.autosubtitle.process.ProcessResult;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -30,7 +29,7 @@ public class ProcessListenerImpl implements ProcessListener {
*/
public ProcessListenerImpl(final Process process) {
this.process = Objects.requireNonNull(process);
this.reader = new BufferedReader(new InputStreamReader(new BufferedInputStream(process.getInputStream()), StandardCharsets.UTF_8));
this.reader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
this.output = new ArrayList<>();
}

View File

@@ -12,6 +12,10 @@ import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
@@ -19,6 +23,8 @@ import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.Objects.requireNonNull;
/**
* Base class for all {@link SetupManager} implementations
*/
@@ -26,12 +32,23 @@ public abstract class AbstractSetupManager extends AbstractProcessRunner impleme
private static final Logger logger = LogManager.getLogger(AbstractSetupManager.class);
private final Set<SetupListener> listeners;
private final HttpClient httpClient;
/**
* Instantiates the manager
* Instantiates the manager with a default client
*/
protected AbstractSetupManager() {
this(HttpClient.newHttpClient());
}
/**
* Instantiates the manager with the given client
*
* @param httpClient The HTTP client to use
*/
protected AbstractSetupManager(final HttpClient httpClient) {
this.listeners = new HashSet<>();
this.httpClient = requireNonNull(httpClient);
}
@Override
@@ -158,6 +175,30 @@ public abstract class AbstractSetupManager extends AbstractProcessRunner impleme
logger.info("{} deleted", path);
}
/**
* Downloads a file
*
* @param url The file url
* @param path The save path
* @throws SetupException If an error occurs
*/
protected void download(final String url, final Path path) throws SetupException {
final var request = HttpRequest.newBuilder().uri(URI.create(url)).GET().build();
try {
final var result = httpClient.send(request, HttpResponse.BodyHandlers.ofFile(path));
if (result.statusCode() == 200) {
logger.info("{} download successful", path);
} else {
throw new SetupException("Error downloading " + path + ": " + result.body());
}
} catch (final IOException e) {
throw new SetupException(e);
} catch (final InterruptedException e) {
Thread.currentThread().interrupt();
throw new SetupException(e);
}
}
private static long getFilesCount(final Path path) throws IOException {
try (final var stream = Files.walk(path)) {
return stream.count();

View File

@@ -35,11 +35,21 @@ public class SRTSubtitleConverter implements SubtitleConverter {
return IntStream.range(0, subtitles.size()).mapToObj(i -> {
final var subtitle = subtitles.get(i);
return (i + 1) + "\n" +
subtitle.start() + " --> " + subtitle.end() + "\n" +
formatTime(subtitle.start()) + " --> " + formatTime(subtitle.end()) + "\n" +
subtitle.content();
}).collect(Collectors.joining("\n\n"));
}
private static String formatTime(final long time) {
final var millisPerHour = 3600000;
final var millisPerMinute = 60000;
final var hours = time / millisPerHour;
final var minutes = (time - hours * millisPerHour) / millisPerMinute;
final var seconds = (time - hours * millisPerHour - minutes * millisPerMinute) / 1000;
final var millis = time - hours * millisPerHour - minutes * millisPerMinute - seconds * 1000;
return String.format("%02d:%02d:%02d,%03d", hours, minutes, seconds, millis);
}
@Override
public SubtitleCollection parse(final String content) throws ParseException {
try {

View File

@@ -4,6 +4,7 @@
module com.github.gtache.autosubtitle.core {
requires transitive com.github.gtache.autosubtitle.api;
requires transitive dagger;
requires transitive java.net.http;
requires transitive javax.inject;
requires org.apache.logging.log4j;