diff --git a/common/src/main/java/ctbrec/Recording.java b/common/src/main/java/ctbrec/Recording.java index 25cef8bd..6237baaa 100644 --- a/common/src/main/java/ctbrec/Recording.java +++ b/common/src/main/java/ctbrec/Recording.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import ctbrec.event.EventBusHolder; import ctbrec.event.RecordingStateChangedEvent; import ctbrec.recorder.download.Download; +import ctbrec.recorder.download.VideoLengthDetector; public class Recording implements Serializable { private static final transient Logger LOG = LoggerFactory.getLogger(Recording.class); @@ -208,10 +209,12 @@ public class Recording implements Serializable { } public Duration getLength() { - if (getDownload() != null) { - return getDownload().getLength(); + File ppFile = getPostProcessedFile(); + if (ppFile.isDirectory()) { + File playlist = new File(ppFile, "playlist.m3u8a"); + return VideoLengthDetector.getLength(playlist); } else { - return Duration.ofSeconds(0); + return VideoLengthDetector.getLength(ppFile); } } diff --git a/common/src/main/java/ctbrec/recorder/download/Download.java b/common/src/main/java/ctbrec/recorder/download/Download.java index fc500a27..171a8d98 100644 --- a/common/src/main/java/ctbrec/recorder/download/Download.java +++ b/common/src/main/java/ctbrec/recorder/download/Download.java @@ -3,7 +3,6 @@ package ctbrec.recorder.download; import java.io.File; import java.io.IOException; import java.io.Serializable; -import java.time.Duration; import java.time.Instant; import ctbrec.Config; @@ -16,7 +15,6 @@ public interface Download extends Serializable { public void stop(); public Model getModel(); public Instant getStartTime(); - public Duration getLength(); public void postprocess(Recording recording); /** diff --git a/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java b/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java index e3f1a170..9f57d93a 100644 --- a/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/dash/DashDownload.java @@ -18,7 +18,6 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; import java.util.Locale; -import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -29,8 +28,6 @@ import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; -import org.jcodec.containers.mp4.MP4Util; -import org.jcodec.containers.mp4.boxes.MovieBox; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -62,7 +59,6 @@ public class DashDownload extends AbstractDownload { private transient HttpClient httpClient; private transient Config config; private Model model; - private Instant endTime; private transient Path downloadDir; private String manifestUrl; private boolean running = false; @@ -272,7 +268,6 @@ public class DashDownload extends AbstractDownload { LOG.error("Error while downloading dash stream", e); } finally { running = false; - endTime = Instant.now(); downloadFinished.set(true); synchronized (downloadFinished) { downloadFinished.notifyAll(); @@ -374,18 +369,6 @@ public class DashDownload extends AbstractDownload { return model; } - @Override - public Duration getLength() { - try { - MovieBox movieBox = MP4Util.parseMovie(finalFile); - double lengthInSeconds = (double) movieBox.getDuration() / movieBox.getTimescale(); - return Duration.ofSeconds((long) Math.ceil(lengthInSeconds)); - } catch (IOException e) { - LOG.error("Couldn't determine length of MP4 file {}", getTarget(), e); - return Duration.between(startTime, Optional.ofNullable(endTime).orElse(Instant.now())); - } - } - @Override public void postprocess(Recording recording) { try { diff --git a/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java index a9eb03b3..1febf103 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/FFmpegDownload.java @@ -6,7 +6,6 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.time.Duration; import java.time.Instant; import java.util.Arrays; import java.util.concurrent.ExecutionException; @@ -119,11 +118,6 @@ public class FFmpegDownload extends AbstractHlsDownload { return model; } - @Override - public Duration getLength() { - return Duration.between(startTime, Instant.now()); - } - @Override public void postprocess(Recording recording) { } 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 adca2dc2..8491971a 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/HlsDownload.java @@ -2,7 +2,6 @@ package ctbrec.recorder.download.hls; import java.io.EOFException; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -31,15 +30,8 @@ import java.util.regex.Pattern; 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.ParsingMode; import com.iheartradio.m3u8.PlaylistException; -import com.iheartradio.m3u8.PlaylistParser; -import com.iheartradio.m3u8.data.MediaPlaylist; -import com.iheartradio.m3u8.data.Playlist; -import com.iheartradio.m3u8.data.TrackData; import ctbrec.Config; import ctbrec.Model; @@ -338,36 +330,6 @@ public class HlsDownload extends AbstractHlsDownload { return relativePath; } - @Override - public Duration getLength() { - try { - File playlist = new File(getTarget(), "playlist.m3u8"); - if (playlist.exists()) { - return Duration.ofSeconds((long) getPlaylistLength(playlist)); - } - } catch (IOException | ParseException | PlaylistException e) { - LOG.error("Couldn't determine recording length", e); - } - return Duration.ofSeconds(-1); - } - - private double getPlaylistLength(File playlist) throws IOException, ParseException, PlaylistException { - if (playlist.exists()) { - try (FileInputStream fin = new FileInputStream(playlist)) { - PlaylistParser playlistParser = new PlaylistParser(fin, Format.EXT_M3U, Encoding.UTF_8, ParsingMode.LENIENT); - Playlist m3u = playlistParser.parse(); - MediaPlaylist mediaPlaylist = m3u.getMediaPlaylist(); - double length = 0; - for (TrackData trackData : mediaPlaylist.getTracks()) { - length += trackData.getTrackInfo().duration; - } - return length; - } - } else { - throw new FileNotFoundException(playlist.getAbsolutePath() + " does not exist"); - } - } - @Override public boolean isSingleFile() { return false; diff --git a/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java b/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java index 7a2a114e..ed8f9d70 100644 --- a/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java +++ b/common/src/main/java/ctbrec/recorder/download/hls/MergedFfmpegHlsDownload.java @@ -44,7 +44,6 @@ import ctbrec.io.StreamRedirectThread; import ctbrec.recorder.ProgressListener; import ctbrec.recorder.download.HttpHeaderFactory; import ctbrec.recorder.download.ProcessExitedUncleanException; -import ctbrec.recorder.download.VideoLengthDetector; import okhttp3.Request; import okhttp3.Request.Builder; import okhttp3.Response; @@ -546,15 +545,6 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload { return fileLoadedBytes; } - @Override - public Duration getLength() { - try { - return VideoLengthDetector.getLength(targetFile); - } catch (Exception e) { - return Duration.between(getStartTime(), Instant.now()); - } - } - @Override public boolean isSingleFile() { return true; diff --git a/common/src/main/java/ctbrec/recorder/postprocessing/DeleteTooShort.java b/common/src/main/java/ctbrec/recorder/postprocessing/DeleteTooShort.java index 7e5cab21..39b3691a 100644 --- a/common/src/main/java/ctbrec/recorder/postprocessing/DeleteTooShort.java +++ b/common/src/main/java/ctbrec/recorder/postprocessing/DeleteTooShort.java @@ -25,10 +25,14 @@ public class DeleteTooShort extends AbstractPostProcessor { Duration minimumLengthInSeconds = Duration.ofSeconds(Integer.parseInt(getConfig().getOrDefault(MIN_LEN_IN_SECS, "0"))); if (minimumLengthInSeconds.getSeconds() > 0) { Duration recordingLength = rec.getLength(); - if (!(recordingLength.isNegative() || recordingLength.isZero()) && recordingLength.compareTo(minimumLengthInSeconds) < 0) { - LOG.info("Deleting too short recording {} [{} < {}]", rec, recordingLength, minimumLengthInSeconds); - recordingManager.delete(rec); - return false; + if (recordingLength.isNegative()) { + LOG.info("Video length couldn't be determined. Keeping the file!"); + } else { + if (!recordingLength.isZero() && recordingLength.compareTo(minimumLengthInSeconds) < 0) { + LOG.info("Deleting too short recording {} [{} < {}]", rec, recordingLength, minimumLengthInSeconds); + recordingManager.delete(rec); + return false; + } } } return true; diff --git a/common/src/main/java/ctbrec/sites/showup/ShowupDownload.java b/common/src/main/java/ctbrec/sites/showup/ShowupDownload.java index 0245b7d3..951e5e59 100644 --- a/common/src/main/java/ctbrec/sites/showup/ShowupDownload.java +++ b/common/src/main/java/ctbrec/sites/showup/ShowupDownload.java @@ -2,8 +2,6 @@ package ctbrec.sites.showup; import java.io.File; import java.io.IOException; -import java.time.Duration; -import java.time.Instant; import com.iheartradio.m3u8.ParseException; import com.iheartradio.m3u8.PlaylistException; @@ -31,9 +29,4 @@ public class ShowupDownload extends HlsDownload { recording.setProgress(-1); return playlist; } - - @Override - public Duration getLength() { - return Duration.between(getStartTime(), Instant.now()); - } } diff --git a/common/src/test/java/ctbrec/recorder/postprocessing/DeleteTooShortTest.java b/common/src/test/java/ctbrec/recorder/postprocessing/DeleteTooShortTest.java index 6c3a5e08..e99cbada 100644 --- a/common/src/test/java/ctbrec/recorder/postprocessing/DeleteTooShortTest.java +++ b/common/src/test/java/ctbrec/recorder/postprocessing/DeleteTooShortTest.java @@ -1,6 +1,7 @@ package ctbrec.recorder.postprocessing; import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.io.File; @@ -9,11 +10,13 @@ import java.time.Duration; import java.util.Collections; import org.junit.Test; +import org.mockito.MockedStatic; import ctbrec.Config; import ctbrec.Recording; import ctbrec.recorder.RecordingManager; import ctbrec.recorder.download.Download; +import ctbrec.recorder.download.VideoLengthDetector; public class DeleteTooShortTest extends AbstractPpTest { @@ -30,6 +33,8 @@ public class DeleteTooShortTest extends AbstractPpTest { private void testProcess(File original) throws IOException { Recording rec = createRec(original); Config config = mockConfig(); + MockedStatic videoLengthDetectorMock = mockStatic(VideoLengthDetector.class); + when(VideoLengthDetector.getLength(any())).thenReturn(Duration.ofSeconds(5)); RecordingManager recordingManager = new RecordingManager(config, Collections.emptyList()); recordingManager.add(rec); @@ -42,6 +47,8 @@ public class DeleteTooShortTest extends AbstractPpTest { assertFalse(rec.getAbsoluteFile().exists()); assertFalse(original.exists()); assertEquals(0, recordingManager.getAll().size()); + + videoLengthDetectorMock.close(); } @Test @@ -85,7 +92,6 @@ public class DeleteTooShortTest extends AbstractPpTest { private Recording createRec(File original) { Download download = mock(Download.class); - when(download.getLength()).thenReturn(Duration.ofSeconds(5)); Recording rec = new Recording(); rec.setModel(mockModel()); rec.setAbsoluteFile(original);