forked from j62/ctbrec
Remove getLength from download
The length has to be determined just in time for certain pp functions to work properly. The length can no longer be retrieved from the recording, but has to be determined with the help of VideoLengthDetector
This commit is contained in:
parent
24fa1a6ed6
commit
7eac934c7f
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<VideoLengthDetector> 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);
|
||||
|
|
Loading…
Reference in New Issue