From a71b74d0b6812585b0e0a1153831bdd90067c11e Mon Sep 17 00:00:00 2001 From: faberf Date: Thu, 8 Jun 2023 16:51:01 +0200 Subject: [PATCH 1/4] refactored AudioSegmentExporter --- .../abstracts/AbstractSegmentExporter.java | 121 ++++++++++++++++++ .../exporter/AudioSegmentExporter.java | 36 +----- 2 files changed, 127 insertions(+), 30 deletions(-) create mode 100644 cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java new file mode 100644 index 000000000..fa848432e --- /dev/null +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java @@ -0,0 +1,121 @@ +package org.vitrivr.cineast.core.features.abstracts; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Base64; +import java.util.HashMap; +import java.util.function.Supplier; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.vitrivr.cineast.core.data.segments.SegmentContainer; +import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; +import org.vitrivr.cineast.core.db.setup.EntityCreator; +import org.vitrivr.cineast.core.features.extractor.Extractor; +import org.vitrivr.cineast.core.util.LogHelper; + +abstract public class AbstractSegmentExporter implements Extractor { + + protected static final Logger LOGGER = LogManager.getLogger(); + + private static final String PROPERTY_NAME_DESTINATION = "destination"; + + /** + * Destination path for the audio-segment. + */ + private Path destination; + + protected String fileExtension; + + protected String dataUrlPrefix; + + /** + * Default constructor + */ + public AbstractSegmentExporter() { + this(new HashMap<>()); + } + + /** + * Default constructor. The AudioSegmentExport can be configured via named properties in the provided HashMap. + *

+ * Supported parameters: + * + *

    + *
  1. destination: Path where files should be stored.
  2. + *
+ * + * @param properties HashMap containing named properties + */ + public AbstractSegmentExporter(HashMap properties) { + this.destination = Path.of(properties.getOrDefault(PROPERTY_NAME_DESTINATION, ".")); + } + + abstract public void exportToStream(SegmentContainer sc, OutputStream stream); + + @Override + public void processSegment(SegmentContainer shot) { + try { + /* Prepare folder and OutputStream. */ + Path folder = this.destination.resolve(shot.getSuperId()); + if (!folder.toFile().exists()) { + folder.toFile().mkdirs(); + } + Path path = folder.resolve(shot.getId() + this.fileExtension); + OutputStream os = Files.newOutputStream(path); + + /* Write audio data to OutputStream. */ + exportToStream(shot, os); + + /* Close OutputStream. */ + os.close(); + } catch (Exception e) { + LOGGER.error("Could not write audio data to file for segment {} due to {}.", shot.getId(), LogHelper.getStackTrace(e)); + } + } + + public String exportToDataUrl(SegmentContainer shot) throws IOException { + // create a ByteArrayOutputStream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // call the exportToStream method with the ByteArrayOutputStream + exportToStream(shot, baos); + + // convert the ByteArrayOutputStream's data to a byte array + byte[] bytes = baos.toByteArray(); + + // encode the byte array to a Base64 string + String base64 = Base64.getEncoder().encodeToString(bytes); + + // concatenate the data URL prefix and the Base64 string + return this.dataUrlPrefix + base64; + } + + public byte[] exportToBinary(SegmentContainer shot) throws IOException { + // create a ByteArrayOutputStream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + // call the exportToStream method with the ByteArrayOutputStream + exportToStream(shot, baos); + + // convert the ByteArrayOutputStream's data to a byte array + byte[] bytes = baos.toByteArray(); + + return bytes; + } + + @Override + public void init(PersistencyWriterSupplier phandlerSupply) { /* Nothing to init. */ } + + @Override + public void finish() { /* Nothing to finish. */} + + @Override + public void initalizePersistentLayer(Supplier supply) { /* Nothing to init. */ } + + @Override + public void dropPersistentLayer(Supplier supply) { /* Nothing to drop. */} + +} diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java index 9c08ed0dd..9a20388e7 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java @@ -19,23 +19,14 @@ import org.vitrivr.cineast.core.data.segments.SegmentContainer; import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; import org.vitrivr.cineast.core.db.setup.EntityCreator; +import org.vitrivr.cineast.core.features.abstracts.AbstractSegmentExporter; import org.vitrivr.cineast.core.features.extractor.Extractor; import org.vitrivr.cineast.core.util.LogHelper; /** * Exports the audio in a given segment as mono WAV file. */ -public class AudioSegmentExporter implements Extractor { - - - private static final Logger LOGGER = LogManager.getLogger(); - - private static final String PROPERTY_NAME_DESTINATION = "destination"; - - /** - * Destination path for the audio-segment. - */ - private Path destination; +public class AudioSegmentExporter extends AbstractSegmentExporter { /** * Default constructor @@ -56,7 +47,9 @@ public AudioSegmentExporter() { * @param properties HashMap containing named properties */ public AudioSegmentExporter(HashMap properties) { - this.destination = Paths.get(properties.getOrDefault(PROPERTY_NAME_DESTINATION, ".")); + super(properties); + this.fileExtension = ".wav"; + this.dataUrlPrefix = "data:audio/wav;base64,"; } /** @@ -65,12 +58,8 @@ public AudioSegmentExporter(HashMap properties) { * @param shot SegmentContainer to process. */ @Override - public void processSegment(SegmentContainer shot) { + public void exportToStream(SegmentContainer shot, OutputStream stream) { try { - /* Prepare folder and OutputStream. */ - Path directory = this.destination.resolve(shot.getSuperId()); - Files.createDirectories(directory); - OutputStream stream = Files.newOutputStream(directory.resolve(shot.getId() + ".wav"), CREATE, TRUNCATE_EXISTING); /* Extract mean samples and perpare byte buffer. */ short[] data = shot.getMeanSamplesAsShort(); @@ -85,7 +74,6 @@ public void processSegment(SegmentContainer shot) { } stream.write(buffer.array()); - stream.close(); } catch (IOException | BufferOverflowException e) { LOGGER.fatal("Could not export audio segment {} due to a serious IO error ({}).", shot.getId(), LogHelper.getStackTrace(e)); } @@ -123,16 +111,4 @@ private void writeWaveHeader(ByteBuffer buffer, float samplingrate, short channe buffer.putInt(subChunk2Length); /* Length of the data chunk. */ } - - @Override - public void init(PersistencyWriterSupplier phandlerSupply) { /* Nothing to init. */ } - - @Override - public void finish() { /* Nothing to finish. */} - - @Override - public void initalizePersistentLayer(Supplier supply) { /* Nothing to init. */ } - - @Override - public void dropPersistentLayer(Supplier supply) { /* Nothing to drop. */} } From 168b480bde6fa0d4cd8c1998dde129ae9beabca6 Mon Sep 17 00:00:00 2001 From: faberf Date: Thu, 8 Jun 2023 18:05:14 +0200 Subject: [PATCH 2/4] Added isExtractable and refactored AudioSpectogramExporter as an example --- .../abstracts/AbstractSegmentExporter.java | 17 ++++---- .../exporter/AudioSegmentExporter.java | 17 +++----- .../exporter/AudioSpectogramExporter.java | 41 ++++--------------- 3 files changed, 24 insertions(+), 51 deletions(-) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java index fa848432e..feb276320 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java @@ -25,7 +25,7 @@ abstract public class AbstractSegmentExporter implements Extractor { /** * Destination path for the audio-segment. */ - private Path destination; + private final Path destination; protected String fileExtension; @@ -55,8 +55,13 @@ public AbstractSegmentExporter(HashMap properties) { abstract public void exportToStream(SegmentContainer sc, OutputStream stream); + abstract public boolean isExportable(SegmentContainer sc); + @Override public void processSegment(SegmentContainer shot) { + if (!isExportable(shot)) { + return; + } try { /* Prepare folder and OutputStream. */ Path folder = this.destination.resolve(shot.getSuperId()); @@ -72,11 +77,11 @@ public void processSegment(SegmentContainer shot) { /* Close OutputStream. */ os.close(); } catch (Exception e) { - LOGGER.error("Could not write audio data to file for segment {} due to {}.", shot.getId(), LogHelper.getStackTrace(e)); + LOGGER.error("Could not data to file for segment {} due to {}.", shot.getId(), LogHelper.getStackTrace(e)); } } - public String exportToDataUrl(SegmentContainer shot) throws IOException { + public String exportToDataUrl(SegmentContainer shot) { // create a ByteArrayOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -93,7 +98,7 @@ public String exportToDataUrl(SegmentContainer shot) throws IOException { return this.dataUrlPrefix + base64; } - public byte[] exportToBinary(SegmentContainer shot) throws IOException { + public byte[] exportToBinary(SegmentContainer shot) { // create a ByteArrayOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -101,9 +106,7 @@ public byte[] exportToBinary(SegmentContainer shot) throws IOException { exportToStream(shot, baos); // convert the ByteArrayOutputStream's data to a byte array - byte[] bytes = baos.toByteArray(); - - return bytes; + return baos.toByteArray(); } @Override diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java index 9a20388e7..f39532bce 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java @@ -1,26 +1,14 @@ package org.vitrivr.cineast.core.features.exporter; -import static java.nio.file.StandardOpenOption.CREATE; -import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; - import java.io.IOException; import java.io.OutputStream; import java.nio.BufferOverflowException; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.HashMap; -import java.util.function.Supplier; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.vitrivr.cineast.core.data.frames.AudioFrame; import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; -import org.vitrivr.cineast.core.db.setup.EntityCreator; import org.vitrivr.cineast.core.features.abstracts.AbstractSegmentExporter; -import org.vitrivr.cineast.core.features.extractor.Extractor; import org.vitrivr.cineast.core.util.LogHelper; /** @@ -79,6 +67,11 @@ public void exportToStream(SegmentContainer shot, OutputStream stream) { } } + @Override + public boolean isExportable(SegmentContainer sc) { + return sc.getNumberOfSamples() > 0; + } + /** * Writes the WAV header to the ByteBuffer (1 channel). * diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java index 7185576af..00f918018 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java @@ -2,19 +2,14 @@ import java.awt.image.BufferedImage; import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.OutputStream; import java.util.HashMap; import java.util.List; -import java.util.function.Supplier; import javax.imageio.ImageIO; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.vitrivr.cineast.core.data.segments.SegmentContainer; -import org.vitrivr.cineast.core.db.PersistencyWriterSupplier; -import org.vitrivr.cineast.core.db.setup.EntityCreator; -import org.vitrivr.cineast.core.features.extractor.Extractor; +import org.vitrivr.cineast.core.features.abstracts.AbstractSegmentExporter; import org.vitrivr.cineast.core.util.LogHelper; import org.vitrivr.cineast.core.util.dsp.fft.STFT; import org.vitrivr.cineast.core.util.dsp.fft.Spectrum; @@ -24,7 +19,7 @@ /** * Visualizes and exporst the power spectogram (time vs. frequency vs. power) of the provided AudioSegment. */ -public class AudioSpectogramExporter implements Extractor { +public class AudioSpectogramExporter extends AbstractSegmentExporter { private static final Logger LOGGER = LogManager.getLogger(); @@ -32,15 +27,10 @@ public class AudioSpectogramExporter implements Extractor { /** * Property names that can be used in the configuration hash map. */ - private static final String PROPERTY_NAME_DESTINATION = "destination"; private static final String PROPERTY_NAME_WIDTH = "width"; private static final String PROPERTY_NAME_HEIGHT = "height"; private static final String PROPERTY_NAME_FORMAT = "format"; - /** - * Destination path; can be set in the AudioWaveformExporter properties. - */ - private final Path destination; /** * Width of the resulting image in pixels. @@ -78,21 +68,15 @@ public AudioSpectogramExporter() { * @param properties HashMap containing named properties */ public AudioSpectogramExporter(HashMap properties) { - this.destination = Paths.get(properties.getOrDefault(PROPERTY_NAME_DESTINATION, ".")); + super(properties); this.width = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_WIDTH, "800")); this.height = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_HEIGHT, "600")); this.format = properties.getOrDefault(PROPERTY_NAME_FORMAT, "JPG"); } @Override - public void processSegment(SegmentContainer shot) { - /* If shot has no samples, this step is skipped. */ - if (shot.getNumberOfSamples() == 0) { - return; - } - + public void exportToStream(SegmentContainer shot, OutputStream stream) { /* Prepare STFT and Spectrum for the segment. */ - final Path directory = this.destination.resolve(shot.getSuperId()); final STFT stft = shot.getSTFT(2048, 512, new HanningWindow()); final List spectrums = stft.getPowerSpectrum(); @@ -100,8 +84,7 @@ public void processSegment(SegmentContainer shot) { try { BufferedImage image = AudioSignalVisualizer.visualizeSpectogram(spectrums, this.width, this.height); if (image != null) { - Files.createDirectories(directory); - ImageIO.write(image, format, directory.resolve(shot.getId() + "." + format.toLowerCase()).toFile()); + ImageIO.write(image, format, stream); } else { LOGGER.warn("Spectrum could not be visualized!"); } @@ -111,14 +94,8 @@ public void processSegment(SegmentContainer shot) { } @Override - public void init(PersistencyWriterSupplier phandlerSupplier) { /* Noting to init. */} - - @Override - public void finish() { /* Nothing to finish. */} - - @Override - public void initalizePersistentLayer(Supplier supply) {/* Nothing to initialize. */} + public boolean isExportable(SegmentContainer sc) { + return sc.getNumberOfSamples() > 0; + } - @Override - public void dropPersistentLayer(Supplier supply) {/* Nothing to drop. */} } From f589f942b5647227de157faebae04752544e4a34 Mon Sep 17 00:00:00 2001 From: faberf Date: Thu, 8 Jun 2023 18:18:39 +0200 Subject: [PATCH 3/4] added the correct file extension and dataurlprefix --- .../core/features/exporter/AudioSpectogramExporter.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java index 00f918018..6e6f26eb0 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java @@ -43,7 +43,7 @@ public class AudioSpectogramExporter extends AbstractSegmentExporter { private final int height; /** - * Output format for thumbnails. Defaults to PNG. + * Output format for thumbnails. Defaults to JPG. */ private final String format; @@ -72,6 +72,8 @@ public AudioSpectogramExporter(HashMap properties) { this.width = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_WIDTH, "800")); this.height = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_HEIGHT, "600")); this.format = properties.getOrDefault(PROPERTY_NAME_FORMAT, "JPG"); + this.fileExtension = "." + format.toLowerCase(); + this.dataUrlPrefix = "data:image/" + format.toLowerCase() + ";base64,"; } @Override From 63f1f5c2f7e8a84784bb188d85cc79c573492438 Mon Sep 17 00:00:00 2001 From: faberf Date: Tue, 13 Jun 2023 17:17:46 +0200 Subject: [PATCH 4/4] Added Documentation refactored the dataurl and fileextension to use getters --- .../abstracts/AbstractSegmentExporter.java | 61 +++++++++++++------ .../exporter/AudioSegmentExporter.java | 14 ++++- .../exporter/AudioSpectogramExporter.java | 12 +++- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java index feb276320..577c0e652 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/abstracts/AbstractSegmentExporter.java @@ -27,9 +27,19 @@ abstract public class AbstractSegmentExporter implements Extractor { */ private final Path destination; - protected String fileExtension; + /** + * Returns the file extension for the exported data. + * + * @return String containing the file extension without the dot. + */ + protected abstract String getFileExtension(); - protected String dataUrlPrefix; + /** + * Returns the data-url prefix for the exported data. + * + * @return String containing the data-url prefix. + */ + protected abstract String getDataUrlPrefix(); /** * Default constructor @@ -39,7 +49,7 @@ public AbstractSegmentExporter() { } /** - * Default constructor. The AudioSegmentExport can be configured via named properties in the provided HashMap. + * Default constructor. A segment exporter can be configured via named properties in the provided HashMap. *

* Supported parameters: * @@ -50,11 +60,23 @@ public AbstractSegmentExporter() { * @param properties HashMap containing named properties */ public AbstractSegmentExporter(HashMap properties) { - this.destination = Path.of(properties.getOrDefault(PROPERTY_NAME_DESTINATION, ".")); + this.destination = Path.of(properties.getOrDefault(PROPERTY_NAME_DESTINATION, "./export")); } + + /** + * Exports the data of a segment container to an output stream. + * + * @param sc SegmentContainer to export. + * @param stream OutputStream to write to. + */ abstract public void exportToStream(SegmentContainer sc, OutputStream stream); + /** + * Determines whether a segment can be exported or not, i.e. if there is enough data to create an export. For example, a segment without audio cannot be exported as audio. Does not check if the segment is already exported. + * + * @param sc The segment to be checked. + */ abstract public boolean isExportable(SegmentContainer sc); @Override @@ -68,36 +90,39 @@ public void processSegment(SegmentContainer shot) { if (!folder.toFile().exists()) { folder.toFile().mkdirs(); } - Path path = folder.resolve(shot.getId() + this.fileExtension); + Path path = folder.resolve(shot.getId() +'.' + this.getFileExtension()); OutputStream os = Files.newOutputStream(path); - /* Write audio data to OutputStream. */ exportToStream(shot, os); /* Close OutputStream. */ os.close(); } catch (Exception e) { - LOGGER.error("Could not data to file for segment {} due to {}.", shot.getId(), LogHelper.getStackTrace(e)); + LOGGER.error("Could not write data to file for segment {} due to {}.", shot.getId(), LogHelper.getStackTrace(e)); } } - public String exportToDataUrl(SegmentContainer shot) { - // create a ByteArrayOutputStream + /** + * Exports a segment to a data-url. + * + * @param shot The segment to be exported. + * @return A String containing the data-url. + */ + public String exportToDataUrl(SegmentContainer shot) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - // call the exportToStream method with the ByteArrayOutputStream exportToStream(shot, baos); - - // convert the ByteArrayOutputStream's data to a byte array byte[] bytes = baos.toByteArray(); - - // encode the byte array to a Base64 string + baos.close(); String base64 = Base64.getEncoder().encodeToString(bytes); - - // concatenate the data URL prefix and the Base64 string - return this.dataUrlPrefix + base64; + return this.getDataUrlPrefix() + base64; } + /** + * Exports a segment to a byte array. + * + * @param shot The segment to be exported. + * @return A byte array containing the exported data. + */ public byte[] exportToBinary(SegmentContainer shot) { // create a ByteArrayOutputStream ByteArrayOutputStream baos = new ByteArrayOutputStream(); diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java index f39532bce..e89782956 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSegmentExporter.java @@ -16,6 +16,16 @@ */ public class AudioSegmentExporter extends AbstractSegmentExporter { + @Override + protected String getFileExtension() { + return "wav"; + } + + @Override + protected String getDataUrlPrefix() { + return "data:audio/wav;base64,"; + } + /** * Default constructor */ @@ -36,10 +46,10 @@ public AudioSegmentExporter() { */ public AudioSegmentExporter(HashMap properties) { super(properties); - this.fileExtension = ".wav"; - this.dataUrlPrefix = "data:audio/wav;base64,"; } + + /** * Processes a SegmentContainer: Extract audio-data and writes to a WAVE file. * diff --git a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java index 6e6f26eb0..59e72b79a 100644 --- a/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java +++ b/cineast-core/src/main/java/org/vitrivr/cineast/core/features/exporter/AudioSpectogramExporter.java @@ -47,6 +47,16 @@ public class AudioSpectogramExporter extends AbstractSegmentExporter { */ private final String format; + @Override + protected String getFileExtension() { + return this.format.toLowerCase(); + } + + @Override + protected String getDataUrlPrefix() { + return "data:image/" + format.toLowerCase() + ";base64,"; + } + /** * Default constructor */ @@ -72,8 +82,6 @@ public AudioSpectogramExporter(HashMap properties) { this.width = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_WIDTH, "800")); this.height = Integer.parseInt(properties.getOrDefault(PROPERTY_NAME_HEIGHT, "600")); this.format = properties.getOrDefault(PROPERTY_NAME_FORMAT, "JPG"); - this.fileExtension = "." + format.toLowerCase(); - this.dataUrlPrefix = "data:image/" + format.toLowerCase() + ";base64,"; } @Override