diff --git a/src/main/java/com/ddf/vodsystem/services/MediaService.java b/src/main/java/com/ddf/vodsystem/services/MediaService.java index 50c88cc..c451822 100644 --- a/src/main/java/com/ddf/vodsystem/services/MediaService.java +++ b/src/main/java/com/ddf/vodsystem/services/MediaService.java @@ -13,13 +13,10 @@ import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; import java.time.Duration; import java.time.Instant; import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; @Service public class MediaService { @@ -31,7 +28,6 @@ public class MediaService { private final ClipService clipService; private static final float CLIP_MAX_LENGTH = 180; - private static final int HLS_SEGMENT_LENGTH = 3; private final StreamActionsService streamActionsService; private final VodService vodService; private final MarkerService markerService; @@ -234,11 +230,11 @@ public class MediaService { private SegmentContext resolveSegments(User user, Instant startTime, Instant endTime) throws IOException { Path streamDir = directoryService.getStreamDir(user.getStreamKey()); - List segments = getSegmentsInRange(streamDir, startTime, endTime); + List segments = streamActionsService.getSegmentsInRange(streamDir, startTime, endTime); if (segments.isEmpty()) { throw new IllegalArgumentException("No stream segments found in the given time range"); } - long firstMs = parseTimestampMs(segments.getFirst()); + long firstMs = streamActionsService.parseTimestampMs(segments.getFirst()); float trimOffset = Math.max(0f, (startTime.toEpochMilli() - firstMs) / 1000f); return new SegmentContext(segments, trimOffset); } @@ -260,26 +256,5 @@ public class MediaService { return job; } - private List getSegmentsInRange(Path streamDirectory, Instant startTime, Instant endTime) throws IOException { - long startMs = startTime.toEpochMilli(); - long endMs = endTime.toEpochMilli(); - try (Stream files = Files.list(streamDirectory)) { - return files - .filter(p -> p.getFileName().toString().endsWith(".ts")) - .filter(p -> { - long segMs = parseTimestampMs(p); - return segMs < endMs && (segMs + HLS_SEGMENT_LENGTH * 1000) > startMs; - }) - .sorted(Comparator.comparingLong(this::parseTimestampMs)) - .collect(Collectors.toList()); - } - } - - private long parseTimestampMs(Path path) { - String name = path.getFileName().toString().replace(".ts", ""); - long value = Long.parseLong(name); - // nginx hls_fragment_naming system uses seconds; convert to ms - return value < 1_000_000_000_000L ? value * 1000L : value; - } } diff --git a/src/main/java/com/ddf/vodsystem/services/media/StreamActionsService.java b/src/main/java/com/ddf/vodsystem/services/media/StreamActionsService.java index f8fec8a..5dcf2d9 100644 --- a/src/main/java/com/ddf/vodsystem/services/media/StreamActionsService.java +++ b/src/main/java/com/ddf/vodsystem/services/media/StreamActionsService.java @@ -6,10 +6,15 @@ import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.time.Instant; +import java.util.Comparator; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Service responsible for performing stream-related media actions, such as @@ -25,6 +30,8 @@ public class StreamActionsService { private static final Logger logger = LoggerFactory.getLogger(StreamActionsService.class); private final CommandRunner commandRunner; + private static final int HLS_SEGMENT_LENGTH = 3; + public StreamActionsService(CommandRunner commandRunner) { this.commandRunner = commandRunner; } @@ -85,4 +92,27 @@ public class StreamActionsService { return CompletableFuture.failedFuture(e); } } + + public List getSegmentsInRange(Path streamDirectory, Instant startTime, Instant endTime) throws IOException { + long startMs = startTime.toEpochMilli(); + long endMs = endTime.toEpochMilli(); + + try (Stream files = Files.list(streamDirectory)) { + return files + .filter(p -> p.getFileName().toString().endsWith(".ts")) + .filter(p -> { + long segMs = parseTimestampMs(p); + return segMs < endMs && (segMs + HLS_SEGMENT_LENGTH * 1000) > startMs; + }) + .sorted(Comparator.comparingLong(this::parseTimestampMs)) + .collect(Collectors.toList()); + } + } + + public long parseTimestampMs(Path path) { + String name = path.getFileName().toString().replace(".ts", ""); + long value = Long.parseLong(name); + // nginx hls_fragment_naming system uses seconds; convert to ms + return value < 1_000_000_000_000L ? value * 1000L : value; + } } \ No newline at end of file