Add new class RecordingDownload for recording downloads
This class inherits from MergedFfmpegHlsDownload, but doesn't create a directory and start FFmpeg in the init method. Moved the dedicated methods for recording downloads from MergedFfmpegHlsDownload to RecordingDownload.
This commit is contained in:
parent
e48df6cd1f
commit
73eb13944c
|
@ -0,0 +1,88 @@
|
|||
package ctbrec;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import com.iheartradio.m3u8.ParseException;
|
||||
import com.iheartradio.m3u8.PlaylistException;
|
||||
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.recorder.ProgressListener;
|
||||
import ctbrec.recorder.download.hls.MergedFfmpegHlsDownload;
|
||||
import ctbrec.recorder.download.hls.SegmentPlaylist;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class RecordingDownload extends MergedFfmpegHlsDownload {
|
||||
|
||||
public RecordingDownload(HttpClient client) {
|
||||
super(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Config config, Model model, Instant startTime, ExecutorService executorService) throws IOException {
|
||||
this.config = config;
|
||||
this.model = model;
|
||||
this.startTime = startTime;
|
||||
this.downloadExecutor = executorService;
|
||||
splittingStrategy = initSplittingStrategy(config.getSettings());
|
||||
}
|
||||
|
||||
public void downloadFinishedRecording(String segmentPlaylistUri, File target, ProgressListener progressListener, long sizeInBytes)
|
||||
throws InvalidKeyException, NoSuchAlgorithmException, IllegalStateException, InterruptedException, IOException, ParseException, PlaylistException {
|
||||
running = true;
|
||||
if (Config.getInstance().getSettings().requireAuthentication) {
|
||||
URL u = new URL(segmentPlaylistUri);
|
||||
String path = u.getPath();
|
||||
byte[] key = Config.getInstance().getSettings().key;
|
||||
if (!Config.getInstance().getContextPath().isEmpty()) {
|
||||
path = path.substring(Config.getInstance().getContextPath().length());
|
||||
}
|
||||
String hmac = Hmac.calculate(path, key);
|
||||
segmentPlaylistUri = segmentPlaylistUri + "?hmac=" + hmac;
|
||||
}
|
||||
|
||||
startFfmpegProcess(target);
|
||||
for (int i = 0; i < 10 && ffmpegStdIn == null; i++) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
SegmentPlaylist segmentPlaylist = getNextSegments(segmentPlaylistUri);
|
||||
long loadedBytes = 0;
|
||||
for (String segmentUrl : segmentPlaylist.segments) {
|
||||
loadedBytes += downloadFile(segmentUrl, loadedBytes, sizeInBytes, progressListener);
|
||||
int progress = (int) (loadedBytes / (double) sizeInBytes * 100);
|
||||
progressListener.update(progress);
|
||||
}
|
||||
|
||||
internalStop();
|
||||
}
|
||||
|
||||
private long downloadFile(String fileUri, long loadedBytes, long totalBytes, ProgressListener progressListener) throws IOException {
|
||||
long fileLoadedBytes = 0;
|
||||
Request request = new Request.Builder().url(fileUri).addHeader("connection", "keep-alive").build();
|
||||
try (Response response = client.execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
InputStream in = response.body().byteStream();
|
||||
byte[] b = new byte[1024 * 100];
|
||||
int length = -1;
|
||||
while ((length = in.read(b)) >= 0) {
|
||||
ffmpegStdIn.write(b, 0, length);
|
||||
fileLoadedBytes += length;
|
||||
int progress = (int) ((loadedBytes + fileLoadedBytes) / (double) totalBytes * 100);
|
||||
progressListener.update(progress);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
return fileLoadedBytes;
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ import ctbrec.GlobalThreadPool;
|
|||
import ctbrec.Model;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.Recording.State;
|
||||
import ctbrec.RecordingDownload;
|
||||
import ctbrec.StringUtil;
|
||||
import ctbrec.event.EventBusHolder;
|
||||
import ctbrec.event.RecordingStateChangedEvent;
|
||||
|
@ -39,7 +40,6 @@ import ctbrec.io.UrlUtil;
|
|||
import ctbrec.recorder.ProgressListener;
|
||||
import ctbrec.recorder.Recorder;
|
||||
import ctbrec.recorder.RecordingPinnedException;
|
||||
import ctbrec.recorder.download.hls.MergedFfmpegHlsDownload;
|
||||
import ctbrec.ui.AutosizeAlert;
|
||||
import ctbrec.ui.CamrecApplication;
|
||||
import ctbrec.ui.DesktopIntegration;
|
||||
|
@ -702,7 +702,7 @@ public class RecordingsTab extends Tab implements TabSelectionListener, Shutdown
|
|||
download.start(url, target);
|
||||
} else {
|
||||
URL url = new URL(hlsBase + '/' + recording.getId() + "/playlist.m3u8");
|
||||
MergedFfmpegHlsDownload download = new MergedFfmpegHlsDownload(CamrecApplication.httpClient);
|
||||
RecordingDownload download = new RecordingDownload(CamrecApplication.httpClient);
|
||||
download.init(config, recording.getModel(), Instant.now(), Executors.newSingleThreadExecutor());
|
||||
LOG.info("Downloading {}", url);
|
||||
download.downloadFinishedRecording(url.toString(), target, createDownloadListener(recording), recording.getSizeInByte());
|
||||
|
|
|
@ -3,9 +3,7 @@ package ctbrec.recorder.download.hls;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
@ -21,17 +19,12 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ctbrec.Config;
|
||||
import ctbrec.Hmac;
|
||||
import ctbrec.Model;
|
||||
import ctbrec.OS;
|
||||
import ctbrec.Recording;
|
||||
import ctbrec.io.HttpClient;
|
||||
import ctbrec.io.HttpException;
|
||||
import ctbrec.recorder.FFmpeg;
|
||||
import ctbrec.recorder.ProgressListener;
|
||||
import ctbrec.recorder.download.ProcessExitedUncleanException;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
||||
|
||||
|
@ -118,7 +111,7 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
|||
internalStop();
|
||||
}
|
||||
|
||||
private void startFfmpegProcess(File target) {
|
||||
protected void startFfmpegProcess(File target) {
|
||||
try {
|
||||
String[] cmdline = prepareCommandLine(target);
|
||||
ffmpeg = new FFmpeg.Builder()
|
||||
|
@ -204,56 +197,6 @@ public class MergedFfmpegHlsDownload extends AbstractHlsDownload {
|
|||
// nothing to do
|
||||
}
|
||||
|
||||
public void downloadFinishedRecording(String segmentPlaylistUri, File target, ProgressListener progressListener, long sizeInBytes) throws Exception {
|
||||
running = true;
|
||||
if (Config.getInstance().getSettings().requireAuthentication) {
|
||||
URL u = new URL(segmentPlaylistUri);
|
||||
String path = u.getPath();
|
||||
byte[] key = Config.getInstance().getSettings().key;
|
||||
if (!Config.getInstance().getContextPath().isEmpty()) {
|
||||
path = path.substring(Config.getInstance().getContextPath().length());
|
||||
}
|
||||
String hmac = Hmac.calculate(path, key);
|
||||
segmentPlaylistUri = segmentPlaylistUri + "?hmac=" + hmac;
|
||||
}
|
||||
|
||||
startFfmpegProcess(target);
|
||||
for (int i = 0; i < 10 && ffmpegStdIn == null; i++) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
SegmentPlaylist segmentPlaylist = getNextSegments(segmentPlaylistUri);
|
||||
long loadedBytes = 0;
|
||||
for (String segmentUrl : segmentPlaylist.segments) {
|
||||
loadedBytes += downloadFile(segmentUrl, loadedBytes, sizeInBytes, progressListener);
|
||||
int progress = (int) (loadedBytes / (double) sizeInBytes * 100);
|
||||
progressListener.update(progress);
|
||||
}
|
||||
|
||||
internalStop();
|
||||
}
|
||||
|
||||
private long downloadFile(String fileUri, long loadedBytes, long totalBytes, ProgressListener progressListener) throws IOException {
|
||||
long fileLoadedBytes = 0;
|
||||
Request request = new Request.Builder().url(fileUri).addHeader("connection", "keep-alive").build();
|
||||
try (Response response = client.execute(request)) {
|
||||
if (response.isSuccessful()) {
|
||||
InputStream in = response.body().byteStream();
|
||||
byte[] b = new byte[1024 * 100];
|
||||
int length = -1;
|
||||
while ((length = in.read(b)) >= 0) {
|
||||
ffmpegStdIn.write(b, 0, length);
|
||||
fileLoadedBytes += length;
|
||||
int progress = (int) ((loadedBytes + fileLoadedBytes) / (double) totalBytes * 100);
|
||||
progressListener.update(progress);
|
||||
}
|
||||
} else {
|
||||
throw new HttpException(response.code(), response.message());
|
||||
}
|
||||
}
|
||||
return fileLoadedBytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFile() {
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue