From 4a2f782c830045e49c5e208a45eb3a11ddc7fddc Mon Sep 17 00:00:00 2001 From: Olha Omelianchuk Date: Wed, 27 Nov 2024 13:48:33 +0100 Subject: [PATCH] [#303] recalculate framerate after test --- .../common/recording/writers/VideoWriter.java | 49 +++++++++++++++++-- .../automatic/RecordingDurationTest.java | 24 ++++++--- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/xceptance/neodymium/common/recording/writers/VideoWriter.java b/src/main/java/com/xceptance/neodymium/common/recording/writers/VideoWriter.java index 964eafad..10a7ae73 100644 --- a/src/main/java/com/xceptance/neodymium/common/recording/writers/VideoWriter.java +++ b/src/main/java/com/xceptance/neodymium/common/recording/writers/VideoWriter.java @@ -9,10 +9,12 @@ import java.io.OutputStream; import java.lang.ProcessBuilder.Redirect; import java.util.Date; +import java.util.UUID; import javax.imageio.ImageIO; import javax.imageio.stream.ImageInputStream; +import org.apache.commons.lang3.math.Fraction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +33,14 @@ public class VideoWriter implements Writer { private static final Logger LOGGER = LoggerFactory.getLogger(VideoWriter.class); + private VideoRecordingConfigurations recordingConfigurations; + + private int screenshots; + + private long testDuration; + + private String videoFileName; + private ProcessBuilder pb; private OutputStream ffmpegInput; @@ -52,7 +62,8 @@ public class VideoWriter implements Writer protected VideoWriter(RecordingConfigurations recordingConfigurations, String videoFileName) throws FileNotFoundException { // check if ffmpeg binary is found - String ffmpegBinary = ((VideoRecordingConfigurations) recordingConfigurations).ffmpegBinaryPath(); + this.recordingConfigurations = ((VideoRecordingConfigurations) recordingConfigurations); + String ffmpegBinary = this.recordingConfigurations.ffmpegBinaryPath(); try { p = new ProcessBuilder(ffmpegBinary, "-h").start(); @@ -64,11 +75,12 @@ protected VideoWriter(RecordingConfigurations recordingConfigurations, String vi } double framerate = 1 / ((double) recordingConfigurations.oneImagePerMilliseconds() / 1000); - pb = new ProcessBuilder(ffmpegBinary, "-y", "-f", "image2pipe", "-r", " " - + framerate - + " ", "-i", "pipe:0", "-c:v", "libx264", videoFileName); + + this.videoFileName = videoFileName; + pb = new ProcessBuilder(ffmpegBinary, "-y", "-f", "image2pipe", "-r", Fraction.getFraction(framerate) + .toString(), "-i", "pipe:0", "-c:v", "libx264", videoFileName); pb.redirectErrorStream(true); - pb.redirectOutput(Redirect.appendTo(new File(((VideoRecordingConfigurations) recordingConfigurations).ffmpegLogFile()))); + pb.redirectOutput(Redirect.appendTo(new File((this.recordingConfigurations).ffmpegLogFile()))); } /** @@ -99,6 +111,8 @@ public void write(File image, long duration) ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(imageBytes)); BufferedImage img = ImageIO.read(iis); ImageIO.write(img, "PNG", ffmpegInput); + screenshots++; + testDuration += duration; } catch (IOException e) { @@ -134,7 +148,32 @@ public void stop() LOGGER.info("process video is processing"); Selenide.sleep(200); } + File tempFile = new File(recordingConfigurations.tempFolderToStoreRecording() + "/" + "temp" + UUID.randomUUID() + ".mp4"); + new File(videoFileName).renameTo(tempFile); + double actualFramerate = screenshots / ((double) testDuration / 1000); + pb = new ProcessBuilder(recordingConfigurations.ffmpegBinaryPath(), "-y", "-r", actualFramerate + "", "-i", tempFile.getPath(), videoFileName); + pb.redirectErrorStream(true); + pb.redirectOutput(Redirect.appendTo(new File((this.recordingConfigurations).ffmpegLogFile()))); + try + { + p = pb.start(); + } + catch (IOException e) + { + throw new RuntimeException("Could not adjust video frame rate", e); + } + while (p.isAlive()) + { + if (new Date().getTime() - videoProcessingStart > 200000) + { + LOGGER.error("something went wrong with adjusting frame rate"); + break; + } + LOGGER.info("video frame rate adjustment is processing"); + Selenide.sleep(200); + } AllureAddons.addToReport("video processing took " + (new Date().getTime() - videoProcessingStart + " ms"), ""); + tempFile.delete(); } } diff --git a/src/test/java/com/xceptance/neodymium/junit5/tests/recording/automatic/RecordingDurationTest.java b/src/test/java/com/xceptance/neodymium/junit5/tests/recording/automatic/RecordingDurationTest.java index 7e3bd45f..377c38f8 100644 --- a/src/test/java/com/xceptance/neodymium/junit5/tests/recording/automatic/RecordingDurationTest.java +++ b/src/test/java/com/xceptance/neodymium/junit5/tests/recording/automatic/RecordingDurationTest.java @@ -55,18 +55,28 @@ public double runTest(boolean isGif, String oneImagePerMilliseconds) throws IOEx @Test public void testVideoRecording() throws IOException { + double run100 = runTest(false, "100"); double run1000 = runTest(false, "1000"); - double run1500 = runTest(false, "1500"); - Assert.assertEquals("Videos with different oneImagePerMilliseconds value should have approximaty the same length (1/1000 = " + run1000 + ", 1/1500 = " - + run1500 + ")", run1000, run1500, 5.0); + + Assert.assertEquals("Videos with different oneImagePerMilliseconds value should have approximaty the same length (1/100 = " + run1000 + + ", 1/1000 = " + run100 + ")", run1000, run1000, 5.0); } @Test public void testGifRecording() throws IOException { - double run1000 = runTest(true, "1000"); - double run1500 = runTest(true, "1500"); - Assert.assertEquals("Gifs with different oneImagePerMilliseconds value should have approximaty the same length (1/1000 = " + run1000 + ", 1/1500 = " - + run1500 + ")", run1000, run1500, 5.0); + double run100 = runTest(true, "100"); + double run1500 = runTest(true, "1000"); + Assert.assertEquals("Gifs with different oneImagePerMilliseconds value should have approximaty the same length (1/100 = " + run100 + ", 1/1500 = " + + run1500 + ")", run100, run1500, 5.0); + } + + @Test + public void testMixedRecording() throws IOException + { + double runVideo1000 = runTest(false, "1000"); + double runGif1000 = runTest(true, "1000"); + Assert.assertEquals("Gifs with different oneImagePerMilliseconds value should have approximaty the same length (video = " + runVideo1000 + ", gif = " + + runGif1000 + ")", runVideo1000, runGif1000, 5.0); } }