/*
* https://webfolder.io/license.html
*/
package io.webfolder.cdp.video;
import static io.webfolder.cdp.JsonLibrary.Jackson;
import static io.webfolder.cdp.event.Events.PageScreencastFrame;
import static io.webfolder.cdp.logger.CdpLoggerType.Console;
import static io.webfolder.cdp.logger.CdpLogggerLevel.Info;
import static java.awt.Desktop.getDesktop;
import static java.awt.Desktop.isDesktopSupported;
import static java.util.EnumSet.of;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import io.webfolder.cdp.Example;
import io.webfolder.cdp.Launcher;
import io.webfolder.cdp.Options;
import io.webfolder.cdp.session.Session;
import io.webfolder.cdp.session.SessionFactory;
import io.webfolder.cdp.session.VideoRecorder;
import io.webfolder.cdp.session.VideoRecorderOptions;
import io.webfolder.cdp.session.VideoRecorderResult;
//
// Record video and encode with vp8 encoder
// this example uses embedded ffmpeg executable
//
// Please make sure to add io.webfolder:ffmpeg-executable:1.1.0 to your project's pom.xml
//
// @see https://github.com/webfolderio/ffmpeg-executable
//
@Example
public class VideoRecorderExample {
private static VideoRecorder recorder;
private static ExecutorService encoderThreadPool;
public static void main(String[] args) {
Launcher launcher = new Launcher(Options.builder()
.loggerType(Console)
.consoleLoggerLevel(Info)
.jsonLibrary(Jackson)
.build());
// cdp4j supports both sync and async video encoding
// use your encoding mode based on your requirements
boolean encodeSync = false;
CompletableFuture<VideoRecorderResult> videoRecorderResult = null;
// By default VideoRecorder uses Java common pool by default
// If you will encode video with encodeAsync()
// you might optional set your own thread pool for ffmpeg process
if ( !encodeSync ) {
encoderThreadPool = newSingleThreadExecutor();
}
try (SessionFactory factory = launcher.launch();
Session session = factory.create()) {
session.setRegisteredEventListeners(of(PageScreencastFrame));
recorder = session.createVideoRecoder(
// All options are optional
VideoRecorderOptions.builder()
.encodingTimeout(60, SECONDS) // default value is 30 seconds (ffmpeg process timeout)
.encoderThreadPool(encoderThreadPool)
.build()
);
recorder.start();
session
.navigate("https://webkit.org/blog-files/3d-transforms/poster-circle.html")
.waitDocumentReady()
.wait(5_000);
session.navigate("https://yahoo.com");
for (int i = 0; i < 50; i++) {
session.wait(100);
session.evaluate("window.scrollBy(0,10)");
}
recorder.stop();
if (encodeSync) {
// sync video encoding (blocks current/session thread)
VideoRecorderResult result = recorder.encode();
if (result.isSucceess() && isDesktopSupported()) {
try {
getDesktop().open(result.getVideoFile().toFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} else {
// async video encoding
videoRecorderResult = recorder.encodeAsync();
}
}
// it's better to prefer use async encoder instead of sync
// no need to keep Session open, video encoder hasn't direct dependency to Session
if ( ! encodeSync && videoRecorderResult != null ) {
try {
VideoRecorderResult result = videoRecorderResult.get();
if (result.isSucceess() && isDesktopSupported()) {
try {
getDesktop().open(result.getVideoFile().toFile());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
if ( encoderThreadPool != null ) {
encoderThreadPool.shutdownNow();
}
}
}