feat(streaming): add backend streaming support with nginx-rtmp #1

Merged
dylan merged 31 commits from feat/rtmp-streaming into master 2026-06-20 01:33:56 +01:00
3 changed files with 11 additions and 16 deletions
Showing only changes of commit 37e9b6c1e7 - Show all commits

View File

@@ -59,15 +59,10 @@ public class DirectoryService {
return file; return file;
} }
public File getVodFile(String filename) { public File getVodFile(String filename) throws IOException {
String dir = outputDir + File.separator + "vods" + File.separator + filename; String dir = outputDir + File.separator + "vods" + File.separator + filename;
File file = new File(dir); File file = new File(dir);
createDirectory(file.getParent());
try {
createDirectory(file.getParent());
} catch (IOException e) {
logger.error("Error creating vods directory: {}", e.getMessage());
}
return file; return file;
} }

View File

@@ -19,10 +19,7 @@ import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Arrays; import java.util.*;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
@@ -36,16 +33,19 @@ public class StreamService {
private final StreamRepository streamRepository; private final StreamRepository streamRepository;
private final UserService userService; private final UserService userService;
private final StreamActionsService streamActionsService; private final StreamActionsService streamActionsService;
private final DirectoryService directoryService;
@Value("${storage.stream}") @Value("${storage.stream}")
private String streamDataPath; private String streamDataPath;
public StreamService(StreamRepository streamRepository, public StreamService(StreamRepository streamRepository,
UserService userService, UserService userService,
StreamActionsService streamActionsService) { StreamActionsService streamActionsService,
DirectoryService directoryService) {
this.streamRepository = streamRepository; this.streamRepository = streamRepository;
this.userService = userService; this.userService = userService;
this.streamActionsService = streamActionsService; this.streamActionsService = streamActionsService;
this.directoryService = directoryService;
} }
public Stream startStream(String streamKey) { public Stream startStream(String streamKey) {
@@ -141,7 +141,8 @@ public class StreamService {
float trimOffset = Math.max(0f, (startTime.toEpochMilli() - firstSegmentMs) / 1000f); float trimOffset = Math.max(0f, (startTime.toEpochMilli() - firstSegmentMs) / 1000f);
float duration = (endTime.toEpochMilli() - startTime.toEpochMilli()) / 1000f; float duration = (endTime.toEpochMilli() - startTime.toEpochMilli()) / 1000f;
streamActionsService.saveSection(fileSegments, trimOffset, duration); File outputFile = directoryService.getVodFile(UUID.randomUUID() + ".mp4");
streamActionsService.saveSection(fileSegments, trimOffset, duration, outputFile);
} }
/** /**

View File

@@ -27,14 +27,13 @@ public class StreamActionsService {
public CompletableFuture<File> saveSection( public CompletableFuture<File> saveSection(
List<File> segments, List<File> segments,
float trimOffset, float trimOffset,
float duration float duration,
File outputFile
) throws IOException, InterruptedException { ) throws IOException, InterruptedException {
String concatInput = segments.stream() String concatInput = segments.stream()
.map(File::getAbsolutePath) .map(File::getAbsolutePath)
.collect(Collectors.joining("|")); .collect(Collectors.joining("|"));
File outputFile = directoryService.getVodFile(UUID.randomUUID() + ".mp4");
List<String> command = List.of( List<String> command = List.of(
"ffmpeg", "ffmpeg",
"-y", "-y",