forked from j62/ctbrec
1
0
Fork 0

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:
0xb00bface 2020-10-11 19:14:22 +02:00
parent 24fa1a6ed6
commit 7eac934c7f
9 changed files with 21 additions and 88 deletions

View File

@ -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);
}
}

View File

@ -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);
/**

View File

@ -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 {

View File

@ -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) {
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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);