refactor(command): inject CommandRunner instead of static
This commit is contained in:
@@ -2,6 +2,7 @@ package com.ddf.vodsystem.services.media;
|
|||||||
|
|
||||||
import com.ddf.vodsystem.dto.CommandOutput;
|
import com.ddf.vodsystem.dto.CommandOutput;
|
||||||
import com.ddf.vodsystem.dto.ProgressTracker;
|
import com.ddf.vodsystem.dto.ProgressTracker;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -11,10 +12,11 @@ import java.util.function.Consumer;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@Component
|
||||||
public class CommandRunner {
|
public class CommandRunner {
|
||||||
private static final Pattern timePattern = Pattern.compile("out_time_ms=(\\d+)");
|
private static final Pattern timePattern = Pattern.compile("out_time_ms=(\\d+)");
|
||||||
|
|
||||||
public static CommandOutput run(List<String> command, Consumer<String> onOutput) throws IOException, InterruptedException {
|
public CommandOutput run(List<String> command, Consumer<String> onOutput) throws IOException, InterruptedException {
|
||||||
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
ProcessBuilder processBuilder = new ProcessBuilder(command);
|
||||||
processBuilder.redirectErrorStream(true);
|
processBuilder.redirectErrorStream(true);
|
||||||
|
|
||||||
@@ -41,19 +43,15 @@ public class CommandRunner {
|
|||||||
return commandOutput;
|
return commandOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CommandOutput run(List<String> command) throws IOException, InterruptedException {
|
public CommandOutput run(List<String> command) throws IOException, InterruptedException {
|
||||||
return run(command, null);
|
return run(command, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setProgress(String line, ProgressTracker progress, float length) {
|
public void setProgress(String line, ProgressTracker progress, float length) {
|
||||||
Matcher matcher = timePattern.matcher(line);
|
Matcher matcher = timePattern.matcher(line);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
float timeInMs = Float.parseFloat(matcher.group(1)) / 1000000f;
|
float timeInMs = Float.parseFloat(matcher.group(1)) / 1000000f;
|
||||||
progress.setProgress(timeInMs / length);
|
progress.setProgress(timeInMs / length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private CommandRunner() {
|
|
||||||
// Private constructor to prevent instantiation
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -13,17 +13,19 @@ import java.nio.file.Path;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CompressionService {
|
public class CompressionService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(CompressionService.class);
|
private static final Logger logger = LoggerFactory.getLogger(CompressionService.class);
|
||||||
|
private final CommandRunner commandRunner;
|
||||||
|
|
||||||
private static final float AUDIO_RATIO = 0.15f;
|
private static final float AUDIO_RATIO = 0.15f;
|
||||||
private static final float MAX_AUDIO_BITRATE = 128f;
|
private static final float MAX_AUDIO_BITRATE = 128f;
|
||||||
private static final float BITRATE_MULTIPLIER = 0.9f;
|
private static final float BITRATE_MULTIPLIER = 0.9f;
|
||||||
private final Pattern timePattern = Pattern.compile("out_time_ms=(\\d+)");
|
|
||||||
|
public CompressionService(CommandRunner commandRunner) {
|
||||||
|
this.commandRunner = commandRunner;
|
||||||
|
}
|
||||||
|
|
||||||
@Async("ffmpegTaskExecutor")
|
@Async("ffmpegTaskExecutor")
|
||||||
public CompletableFuture<CommandOutput> compress(Path inputFile,
|
public CompletableFuture<CommandOutput> compress(Path inputFile,
|
||||||
@@ -38,20 +40,12 @@ public class CompressionService {
|
|||||||
outputFile,
|
outputFile,
|
||||||
clipOptions
|
clipOptions
|
||||||
);
|
);
|
||||||
CommandOutput result = CommandRunner.run(command, line -> CommandRunner.setProgress(line, progress, clipOptions.getDuration()));
|
CommandOutput result = commandRunner.run(command, line -> commandRunner.setProgress(line, progress, clipOptions.getDuration()));
|
||||||
progress.markComplete();
|
progress.markComplete();
|
||||||
|
|
||||||
return CompletableFuture.completedFuture(result);
|
return CompletableFuture.completedFuture(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setProgress(String line, ProgressTracker progress, float length) {
|
|
||||||
Matcher matcher = timePattern.matcher(line);
|
|
||||||
if (matcher.find()) {
|
|
||||||
float timeInMs = Float.parseFloat(matcher.group(1)) / 1000000f;
|
|
||||||
progress.setProgress(timeInMs / length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> buildFilters(Float fps, Integer width, Integer height) {
|
private List<String> buildFilters(Float fps, Integer width, Integer height) {
|
||||||
List<String> command = new ArrayList<>();
|
List<String> command = new ArrayList<>();
|
||||||
command.add("-vf");
|
command.add("-vf");
|
||||||
|
|||||||
@@ -19,9 +19,14 @@ import java.util.concurrent.Future;
|
|||||||
@Service
|
@Service
|
||||||
public class MetadataService {
|
public class MetadataService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MetadataService.class);
|
private static final Logger logger = LoggerFactory.getLogger(MetadataService.class);
|
||||||
|
public final CommandRunner commandRunner;
|
||||||
|
|
||||||
private static final String DURATION = "duration";
|
private static final String DURATION = "duration";
|
||||||
|
|
||||||
|
public MetadataService(CommandRunner commandRunner) {
|
||||||
|
this.commandRunner = commandRunner;
|
||||||
|
}
|
||||||
|
|
||||||
@Async("ffmpegTaskExecutor")
|
@Async("ffmpegTaskExecutor")
|
||||||
public Future<ClipOptions> getVideoMetadata(Path file) {
|
public Future<ClipOptions> getVideoMetadata(Path file) {
|
||||||
logger.info("Getting metadata for file {}", file);
|
logger.info("Getting metadata for file {}", file);
|
||||||
@@ -39,7 +44,7 @@ public class MetadataService {
|
|||||||
StringBuilder outputBuilder = new StringBuilder();
|
StringBuilder outputBuilder = new StringBuilder();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CommandOutput output = CommandRunner.run(command);
|
CommandOutput output = commandRunner.run(command);
|
||||||
|
|
||||||
for (String line : output.getOutput()) {
|
for (String line : output.getOutput()) {
|
||||||
outputBuilder.append(line);
|
outputBuilder.append(line);
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class RemuxService {
|
public class RemuxService {
|
||||||
private final Pattern timePattern = Pattern.compile("out_time_ms=(\\d+)");
|
private final CommandRunner commandRunner;
|
||||||
|
|
||||||
|
public RemuxService(CommandRunner commandRunner) {
|
||||||
|
this.commandRunner = commandRunner;
|
||||||
|
}
|
||||||
|
|
||||||
@Async("ffmpegTaskExecutor")
|
@Async("ffmpegTaskExecutor")
|
||||||
public CompletableFuture<CommandOutput> remux(File inputFile,
|
public CompletableFuture<CommandOutput> remux(File inputFile,
|
||||||
@@ -33,14 +35,7 @@ public class RemuxService {
|
|||||||
outputFile.getAbsolutePath()
|
outputFile.getAbsolutePath()
|
||||||
);
|
);
|
||||||
|
|
||||||
return CompletableFuture.completedFuture(CommandRunner.run(command, line -> setProgress(line, remuxProgress, length)));
|
return CompletableFuture.completedFuture(commandRunner.run(command, line ->
|
||||||
}
|
commandRunner.setProgress(line, remuxProgress, length)));
|
||||||
|
|
||||||
private void setProgress(String line, ProgressTracker progress, float length) {
|
|
||||||
Matcher matcher = timePattern.matcher(line);
|
|
||||||
if (matcher.find()) {
|
|
||||||
float timeInMs = Float.parseFloat(matcher.group(1)) / 1000000f;
|
|
||||||
progress.setProgress(timeInMs / length);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ import java.util.stream.Collectors;
|
|||||||
@Service
|
@Service
|
||||||
public class StreamActionsService {
|
public class StreamActionsService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(StreamActionsService.class);
|
private static final Logger logger = LoggerFactory.getLogger(StreamActionsService.class);
|
||||||
|
private final CommandRunner commandRunner;
|
||||||
|
|
||||||
|
public StreamActionsService(CommandRunner commandRunner) {
|
||||||
|
this.commandRunner = commandRunner;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concatenates a list of video segments and extracts a trimmed section
|
* Concatenates a list of video segments and extracts a trimmed section
|
||||||
@@ -71,7 +76,7 @@ public class StreamActionsService {
|
|||||||
|
|
||||||
logger.info("Saving section with ({} segments) to '{}'",
|
logger.info("Saving section with ({} segments) to '{}'",
|
||||||
segments.size(), outputFile);
|
segments.size(), outputFile);
|
||||||
CommandRunner.run(command, line -> CommandRunner.setProgress(line, progressTracker, duration));
|
commandRunner.run(command, line -> commandRunner.setProgress(line, progressTracker, duration));
|
||||||
progressTracker.markComplete();
|
progressTracker.markComplete();
|
||||||
|
|
||||||
return CompletableFuture.completedFuture(outputFile);
|
return CompletableFuture.completedFuture(outputFile);
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ import java.util.List;
|
|||||||
@Service
|
@Service
|
||||||
public class ThumbnailService {
|
public class ThumbnailService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ThumbnailService.class);
|
private static final Logger logger = LoggerFactory.getLogger(ThumbnailService.class);
|
||||||
|
private final CommandRunner commandRunner;
|
||||||
|
|
||||||
|
public ThumbnailService(CommandRunner commandRunner) {
|
||||||
|
this.commandRunner = commandRunner;
|
||||||
|
}
|
||||||
|
|
||||||
@Async("ffmpegTaskExecutor")
|
@Async("ffmpegTaskExecutor")
|
||||||
public void createThumbnail(Path inputFile, Path outputFile, Float timeInVideo) throws IOException, InterruptedException {
|
public void createThumbnail(Path inputFile, Path outputFile, Float timeInVideo) throws IOException, InterruptedException {
|
||||||
@@ -25,6 +30,6 @@ public class ThumbnailService {
|
|||||||
outputFile.toAbsolutePath().toString()
|
outputFile.toAbsolutePath().toString()
|
||||||
);
|
);
|
||||||
|
|
||||||
CommandRunner.run(command);
|
commandRunner.run(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user