From eac716abf90ac65bf1f83ce7b0de7dbb1ccbd2ac Mon Sep 17 00:00:00 2001 From: pabloFuente Date: Tue, 29 Jan 2019 00:08:52 +0100 Subject: [PATCH] openvidu-test-e2e: use ffmpeg to get media files metadata --- .../server/recording/RecordingInfoUtils.java | 2 +- openvidu-test-e2e/docker/Dockerfile | 5 + openvidu-test-e2e/pom.xml | 10 - .../test/e2e/OpenViduTestAppE2eTest.java | 5 +- .../e2e/utils/MultimediaFileMetadata.java | 187 +++++++++--------- 5 files changed, 103 insertions(+), 106 deletions(-) diff --git a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java index 5fd58231..04cb8f91 100644 --- a/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java +++ b/openvidu-server/src/main/java/io/openvidu/server/recording/RecordingInfoUtils.java @@ -103,7 +103,7 @@ public class RecordingInfoUtils { } public int getVideoFramerate() { - String frameRate = videoStream.get("r_frame_rate").toString(); + String frameRate = videoStream.get("r_frame_rate").getAsString(); String[] frameRateParts = frameRate.split("/"); return Integer.parseInt(frameRateParts[0]) / Integer.parseInt(frameRateParts[1]); diff --git a/openvidu-test-e2e/docker/Dockerfile b/openvidu-test-e2e/docker/Dockerfile index b02e9b37..ceb5927e 100644 --- a/openvidu-test-e2e/docker/Dockerfile +++ b/openvidu-test-e2e/docker/Dockerfile @@ -39,6 +39,11 @@ RUN npm install -g typescript@latest # sudo RUN apt-get -y install sudo +# ffmpeg (for ffprobe) +RUN add-apt-repository ppa:jonathonf/ffmpeg-4 +RUN apt-get update +RUN apt-get install -y ffmpeg + # Cleanup RUN rm -rf /var/lib/apt/lists/* RUN apt-get autoremove --purge -y diff --git a/openvidu-test-e2e/pom.xml b/openvidu-test-e2e/pom.xml index d3c5e571..c82dae5b 100644 --- a/openvidu-test-e2e/pom.xml +++ b/openvidu-test-e2e/pom.xml @@ -156,16 +156,6 @@ jcodec-javase 0.2.3 - - ws.schild - jave-core - 2.4.5 - - - ws.schild - jave-native-linux64 - 2.4.5 - io.openvidu diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java index e76fce0a..6dce3c03 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/OpenViduTestAppE2eTest.java @@ -1933,12 +1933,11 @@ public class OpenViduTestAppE2eTest { private void checkMultimediaFile(File file, boolean hasAudio, boolean hasVideo, double duration, String resolution, String audioDecoder, String videoDecoder) { // Check tracks, duration, resolution, framerate and decoders - MultimediaFileMetadata metadata = new MultimediaFileMetadata(file); - metadata.processMultimediaFile(0); + MultimediaFileMetadata metadata = new MultimediaFileMetadata(file.getAbsolutePath()); if (hasVideo) { if (hasAudio) { - Assert.assertTrue(metadata.hasAudioAndVideo()); + Assert.assertTrue(metadata.hasAudio() && metadata.hasVideo()); Assert.assertTrue(metadata.getAudioDecoder().toLowerCase().contains(audioDecoder)); } else { Assert.assertTrue(metadata.hasVideo()); diff --git a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java index 4d54462a..4f586999 100644 --- a/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java +++ b/openvidu-test-e2e/src/test/java/io/openvidu/test/e2e/utils/MultimediaFileMetadata.java @@ -18,148 +18,151 @@ package io.openvidu.test.e2e.utils; import java.io.BufferedReader; -import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import ws.schild.jave.AudioInfo; -import ws.schild.jave.EncoderException; -import ws.schild.jave.MultimediaInfo; -import ws.schild.jave.MultimediaObject; -import ws.schild.jave.VideoInfo; -import ws.schild.jave.VideoSize; +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; public class MultimediaFileMetadata { private static final Logger log = LoggerFactory.getLogger(MultimediaFileMetadata.class); - private File f; - private MultimediaInfo mediaInfo; - private AudioInfo audioInfo; - private VideoInfo videoInfo; - private VideoSize videoSize; + private JsonObject json; + private JsonObject formatJson; + private JsonObject audioStreamJson; + private JsonObject videoStreamJson; - public MultimediaFileMetadata(File f) { - this.f = f; - } + private double duration; + private String format; + private long bitrate; + private boolean hasAudio; + private boolean hasVideo; + private long audioSampleRate; + private String audioDecoder; + private String videoDecoder; + private int videoWidth; + private int videoHeight; + private int framerate; - public void processMultimediaFile(int iteration) { - try { - this.mediaInfo = new MultimediaObject(f).getInfo(); - this.audioInfo = mediaInfo.getAudio(); - this.videoInfo = mediaInfo.getVideo(); - if (videoInfo != null) { - this.videoSize = videoInfo.getSize(); - } - log.info("File {} {} an audio track", f.getName(), this.audioInfo != null ? "has" : "doesn't have"); - log.info("File {} {} a video track", f.getName(), this.videoInfo != null ? "has" : "doesn't have"); - } catch (EncoderException e) { - log.error("Error getting multimedia information from file {}. Error: {}", f.getAbsolutePath(), - e.getMessage()); - try { - Thread.sleep(1000); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - log.info(System.getProperty("user.name")); - this.executeCommand("ls -la /tmp/jave/"); - if (iteration == 0) { - this.executeCommand("chmod 777 /tmp/jave/ffmpeg*"); - } else if (iteration < 5) { - this.processMultimediaFile(++iteration); - } else { - log.error("Couldn't run jave in 5 iterations"); - return; + public MultimediaFileMetadata(String fileAbsolutePath) { + + log.info("Extracting media metadata info from file {}", fileAbsolutePath); + + this.json = this.executeFfprobeCommand(fileAbsolutePath); + this.formatJson = json.get("format").getAsJsonObject(); + JsonArray streams = json.get("streams").getAsJsonArray(); + + streams.forEach(e -> { // Only supposed for 2 streams max + String codecType = e.getAsJsonObject().get("codec_type").getAsString(); + switch (codecType) { + case "audio": + this.audioStreamJson = e.getAsJsonObject(); + break; + case "video": + this.videoStreamJson = e.getAsJsonObject(); + break; } + }); + + this.duration = formatJson.get("duration").getAsDouble(); + this.format = formatJson.get("format_name").getAsString(); + this.bitrate = formatJson.get("bit_rate").getAsLong(); + this.hasAudio = this.audioStreamJson != null; + this.hasVideo = this.videoStreamJson != null; + + if (this.hasAudio) { + this.audioDecoder = this.audioStreamJson.get("codec_name").getAsString(); + this.audioSampleRate = this.audioStreamJson.get("sample_rate").getAsLong(); } + + if (this.hasVideo) { + this.videoDecoder = this.videoStreamJson.get("codec_name").getAsString(); + this.videoWidth = this.videoStreamJson.get("width").getAsInt(); + this.videoHeight = this.videoStreamJson.get("height").getAsInt(); + + String frameRate = this.videoStreamJson.get("r_frame_rate").getAsString(); + String[] frameRateParts = frameRate.split("/"); + this.framerate = Integer.parseInt(frameRateParts[0]) / Integer.parseInt(frameRateParts[1]); + } + + log.info("Media metadata for {}: {}", fileAbsolutePath, this.toString()); } - public long getDuration() { - return mediaInfo.getDuration(); + public double getDuration() { + return duration; } - public String getFormat(String format) { - return mediaInfo.getFormat(); + public String getFormat() { + return format; + } + + public long getBitrate() { + return bitrate; } public boolean hasAudio() { - return audioInfo != null; + return hasAudio; } public boolean hasVideo() { - return videoInfo != null; + return hasVideo; } - public boolean hasAudioAndVideo() { - return this.hasAudio() && this.hasVideo(); - } - - public Integer getAudioBitrate() { - if (audioInfo != null) { - return audioInfo.getBitRate(); - } else { - return null; - } - } - - public Integer getVideoBitrate() { - if (videoInfo != null) { - return videoInfo.getBitRate(); - } else { - return null; - } + public long getAudioSampleRate() { + return audioSampleRate; } public String getAudioDecoder() { - return audioInfo.getDecoder(); + return audioDecoder; } public String getVideoDecoder() { - return videoInfo.getDecoder(); + return videoDecoder; } - public Integer getVideoWidth() { - if (videoSize != null) { - return videoSize.getWidth(); - } else { - return null; - } + public int getVideoWidth() { + return videoWidth; } - public Integer getVideoHeight() { - if (videoSize != null) { - return videoSize.getHeight(); - } else { - return null; - } + public int getVideoHeight() { + return videoHeight; } - public Integer getFrameRate() { - if (videoInfo != null) { - return Math.round(videoInfo.getFrameRate()); - } else { - return null; - } + public int getFrameRate() { + return framerate; } - private void executeCommand(String command) { - log.info("Running bash command '{}'", command); + private JsonObject executeFfprobeCommand(String filePath) { + log.info("Running ffprobe command on '{}'", filePath); + String jsonLines = ""; try { String s; Process p; - p = Runtime.getRuntime().exec(command); + p = Runtime.getRuntime().exec("ffprobe -v quiet -print_format json -show_format -show_streams " + filePath); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); - while ((s = br.readLine()) != null) - log.info("LINE: " + s); + while ((s = br.readLine()) != null) { + jsonLines += s; + } p.waitFor(); - System.out.println("EXIT VALUE: " + p.exitValue()); p.destroy(); } catch (IOException | InterruptedException e1) { log.info("Error updateing permissions of jave executable. Error: {}" + e1.getMessage()); } + JsonParser parser = new JsonParser(); + return parser.parse(jsonLines).getAsJsonObject(); + } + + @Override + public String toString() { + return "{duration=" + this.duration + ", format=" + this.format + ", bitrate=" + this.bitrate + ", hasAudio=" + + this.hasAudio + ", hasVideo=" + this.hasVideo + ", audioSampleRate=" + this.audioSampleRate + + ", audioDecoder=" + this.audioDecoder + ", videoDecoder=" + this.videoDecoder + ", videoWidth=" + + this.videoWidth + ", videoHeight=" + this.videoHeight + ", framerate=" + this.framerate + "}"; } }