From 5194345c0c49166b137e520f27dfdadd4ba21cd0 Mon Sep 17 00:00:00 2001 From: 0xb00bface <0xboobface@gmail.com> Date: Fri, 1 Oct 2021 16:38:21 +0200 Subject: [PATCH] Fix on-the-fly writing of playlist --- .../download/hls/AbstractHlsDownload.java | 14 ++++++------ .../recorder/download/hls/HlsDownload.java | 22 ++++++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java index c5f52eab..4428ddc9 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/AbstractHlsDownload.java @@ -77,7 +77,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { private static final int A_FEW_SECONDS = 10_000; private static final int MAX_SECONDS_WITHOUT_TRANSFER = 30; - private NumberFormat nf = new DecimalFormat("000000"); + private final NumberFormat nf = new DecimalFormat("000000"); private int playlistEmptyCount = 0; private int segmentCounter = 1; @@ -94,7 +94,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { private Instant lastSegmentDownload = Instant.MAX; private int selectedResolution = UNKNOWN; - private List recordingEvents = new LinkedList<>(); + private final List recordingEvents = new LinkedList<>(); protected ExecutorCompletionService segmentDownloadService; protected AbstractHlsDownload(HttpClient client) { @@ -176,7 +176,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { } protected void processFinishedSegments() { - downloadExecutor.submit((Runnable)() -> { + downloadExecutor.submit(() -> { Future future; while ((future = segmentDownloadService.poll()) != null) { try { @@ -193,7 +193,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { protected abstract void execute(SegmentDownload segmentDownload); - protected void handleHttpException(HttpException e) throws IOException { + protected void handleHttpException(HttpException e) { if (e.getResponseCode() == 404) { checkIfModelIsStillOnline("Playlist not found (404). Model {} probably went offline. Model state: {}"); } else if (e.getResponseCode() == 403) { @@ -207,7 +207,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { } } - protected void checkIfModelIsStillOnline(String errorMsg) throws IOException { + protected void checkIfModelIsStillOnline(String errorMsg) { ctbrec.Model.State modelState; try { modelState = model.getOnlineState(false); @@ -323,7 +323,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { uri = new URL(context, uri).toExternalForm(); } lsp.totalDuration += trackData.getTrackInfo().duration; - lsp.segments.add(new Segment(uri, trackData.getTrackInfo().duration)); + lsp.segments.add(new Segment(uri, Math.max(0, trackData.getTrackInfo().duration))); if (trackData.hasEncryptionData()) { lsp.encrypted = true; EncryptionData data = trackData.getEncryptionData(); @@ -364,7 +364,7 @@ public abstract class AbstractHlsDownload extends AbstractDownload { DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_TIME; for (RecordingEvent recordingEvent : recordingEvents) { ZonedDateTime dateTime = recordingEvent.timestamp.atZone(ZoneId.systemDefault()); - br.append(dtf.format(dateTime) + " " + model + " " + recordingEvent.message); + br.append(dtf.format(dateTime)).append(' ').append(model.toString()).append(' ').append(recordingEvent.message); br.newLine(); } br.flush(); diff --git a/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java index f4da7927..0168b162 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java @@ -21,14 +21,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.regex.Pattern; +import com.iheartradio.m3u8.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.iheartradio.m3u8.Encoding; -import com.iheartradio.m3u8.Format; -import com.iheartradio.m3u8.ParseException; -import com.iheartradio.m3u8.PlaylistException; -import com.iheartradio.m3u8.PlaylistWriter; import com.iheartradio.m3u8.data.MediaPlaylist; import com.iheartradio.m3u8.data.Playlist; import com.iheartradio.m3u8.data.PlaylistType; @@ -48,9 +44,9 @@ public class HlsDownload extends AbstractHlsDownload { protected Path downloadDir; - private Queue> segmentDownloads = new LinkedList<>(); + private final Queue> segmentDownloads = new LinkedList<>(); - private List segments = new LinkedList<>(); + private final List segments = new LinkedList<>(); private float targetDuration; @@ -85,6 +81,9 @@ public class HlsDownload extends AbstractHlsDownload { private void updatePlaylist() { downloadExecutor.submit(() -> { addNewSegmentsToPlaylist(); + if (segments.isEmpty() || targetDuration <= 0) { + return; + } try { MediaPlaylist playlist = new MediaPlaylist.Builder() .withPlaylistType(PlaylistType.VOD) @@ -110,7 +109,14 @@ public class HlsDownload extends AbstractHlsDownload { .build(); writer.write(master); } - } catch (IOException | ParseException | PlaylistException e) { + } catch (PlaylistException e) { + LOG.error("Updating segment playlist failed", e); + if (e.getErrors() != null) { + for (PlaylistError error : e.getErrors()) { + LOG.error("Playlist Error: {}", error); + } + } + } catch (IOException | ParseException e) { LOG.error("Updating segment playlist failed", e); } LOG.trace("Segment queue size for {}: {}", model, segmentDownloads.size());