In order to mitigate against the brute force attacks against Gitlab accounts, we are moving to all edu-ID Logins. We would like to remind you to link your account with your edu-id. Login will be possible only by edu-ID after November 30, 2021. Here you can find the instructions for linking your account.

If you don't have a SWITCH edu-ID, you can create one with this guide here

kind regards

This Server has been upgraded to GitLab release 14.2.6

Unverified Commit 8e392aa6 authored by Sebastian Schüpbach's avatar Sebastian Schüpbach
Browse files

create audio snippet along with audo dissemination file


Signed-off-by: Sebastian Schüpbach's avatarSebastian Schüpbach <sebastian.schuepbach@unibas.ch>
parent 2d2de825
Pipeline #13778 passed with stages
in 11 minutes and 57 seconds
......@@ -32,6 +32,8 @@ spec:
value: /data
- name: VIDEO_SINK_DIR
value: /data
- name: AUDIO_SNIPPET_DURATION
value: "30"
- name: INTERNAL_BASE_URL
value: "http://mb-fd1.memobase.unibas.ch:8080/fcrepo/rest/"
- name: EXTERNAL_BASE_URL
......
......@@ -2,6 +2,7 @@ app:
audioSinkDir: ${AUDIO_SINK_DIR:?system}
imageSinkDir: ${IMAGE_SINK_DIR:?system}
videoSinkDir: ${VIDEO_SINK_DIR:?system}
audioSnippetDuration: ${AUDIO_SNIPPET_DURATION:?system}
internalBaseUrl: ${INTERNAL_BASE_URL:?system}
externalBaseUrl: ${EXTERNAL_BASE_URL:?system}
fedoraUser: ${FEDORA_USER:?system}
......
......@@ -47,7 +47,8 @@ object App extends scala.App with Logging {
val fileHandler = new DisseminationCopyHandler(
settings.getAppSettings.getProperty("audioSinkDir"),
settings.getAppSettings.getProperty("imageSinkDir"),
settings.getAppSettings.getProperty("videoSinkDir"))
settings.getAppSettings.getProperty("videoSinkDir"),
settings.getAppSettings.getProperty("audioSnippetDuration").toInt)
val fCWrapper = FedoraClientWrapper(
settings.getAppSettings.getProperty("internalBaseUrl"),
settings.getAppSettings.getProperty("externalBaseUrl"),
......
......@@ -33,7 +33,7 @@ import scala.util.{Failure, Success, Try}
* @param imageDestPath Path to folder containing image dissemination copies
* @param videoDestPath Path to folder containing video dissemination copies
*/
class DisseminationCopyHandler(audioDestPath: String, imageDestPath: String, videoDestPath: String) {
class DisseminationCopyHandler(audioDestPath: String, imageDestPath: String, videoDestPath: String, audioSnippetDuration: Int) {
private def writeData(data: ByteArrayOutputStream, destFile: Path): Try[Path] = {
Try(new FileOutputStream(destFile.toFile)) match {
......@@ -63,8 +63,10 @@ class DisseminationCopyHandler(audioDestPath: String, imageDestPath: String, vid
def createAudioCopy(data: ByteArrayOutputStream, destId: String, sourceFileType: MediaFileType): Try[Path] = Try {
val tempFilePath = Files.createTempFile("media-", "." + Conversions.getFileTypeExtension(sourceFileType).get)
val destFile = Paths.get(audioDestPath, destId + ".mp4")
val snippetFile = Paths.get(audioDestPath, destId + "-intro." + Conversions.getFileTypeExtension(sourceFileType).get)
writeData(data, tempFilePath)
Transformations.audioToMp4(tempFilePath.toString, destFile.toString).get
Transformations.createAudioSnippet(tempFilePath.toString, snippetFile.toString, audioSnippetDuration)
Files.delete(tempFilePath)
destFile
}
......@@ -108,6 +110,7 @@ class DisseminationCopyHandler(audioDestPath: String, imageDestPath: String, vid
def deleteAudioCopy(destId: String): Try[Boolean] =
Try {
Paths.get(audioDestPath, destId + ".mp4").toFile.delete()
Paths.get(audioDestPath, destId + "-intro.mp3").toFile.delete()
}
/**
......
......@@ -58,6 +58,26 @@ object Transformations extends Logging {
}
}
/**
* Creates an audio snippet used as a base for producing sonograms
*
* @param sourceFilePath Path to the source file
* @param destFilePath Path to the final file
* @param duration Duration of snippet (counts from beginning of track)
* @return
*/
def createAudioSnippet(sourceFilePath: String, destFilePath: String, duration: Int): Try[String] = {
val minutes = (duration / 60) % 60
val hours = (duration / 60 / 60) % 24
val time = "%02d:%02d:%02d".format(hours, minutes, duration % 60)
val copyStream = sourceFilePath.endsWith(".mp3")
val externalCommand = s"ffmpeg -i $sourceFilePath ${if (copyStream) "-acodec copy"} -loglevel warning -hide_banner -y -t $time $destFilePath"
Try {
executeCommand(externalCommand)
destFilePath
}
}
/**
* Converts image file to jpeg2000
*
......
......@@ -33,21 +33,23 @@ class DisseminationCopyHandlerTest extends AnyFunSuite with BeforeAndAfter {
private def fixture = {
new {
val resPath = "src/test/resources"
val fileHandler = new DisseminationCopyHandler(resPath, resPath, resPath)
val fileHandler = new DisseminationCopyHandler(resPath, resPath, resPath, 30)
}
}
after {
val paths = List(
new File("src/test/resources/test.jp2").toPath,
new File("src/test/resources/test.mp4").toPath,
)
for (p <- paths) {
private def deleteFiles(files: String*): Unit = {
for (file <- files) {
val p = new File(file).toPath
Files.deleteIfExists(p)
}
}
private def testCopy(pathToTmpDir: String, sourceFileName: String, destFileName: String, fileType: MediaFileType, copyFun: (ByteArrayOutputStream, String, MediaFileType) => Try[Path]): Assertion = {
private def testCopy(pathToTmpDir: String,
sourceFileName: String,
destFileName: String,
fileType: MediaFileType,
copyFun: (ByteArrayOutputStream, String, MediaFileType)
=> Try[Path]): Assertion = {
val file = Paths.get(pathToTmpDir, sourceFileName).toFile
val data = new ByteArrayOutputStream(file.length().toInt)
val buffer = new Array[Byte](1024)
......@@ -65,23 +67,36 @@ class DisseminationCopyHandlerTest extends AnyFunSuite with BeforeAndAfter {
test("calling the deleteAudio function should delete temporary audio file") {
val f = fixture
val testFile = Files.createFile(Paths.get(f.resPath, "test.mp4"))
val testSnippetFile = Files.createFile(Paths.get(f.resPath, "test-intro.mp3"))
f.fileHandler.deleteAudioCopy("test")
assert(!testFile.toFile.exists())
}
/**
* ATTENTION: Requires that ffmpeg is properly installed!
*/
test("calling the copyAudio function should create temporary file") {
val f = fixture
testCopy(f.resPath, "sample.mp3", "test.mp4", Mp3File, f.fileHandler.createAudioCopy)
deleteFiles("src/test/resources/test.mp4", "src/test/resources/test-intro.mp3")
}
/**
* ATTENTION: Requires that Kakadu and imagemagick are properly installed!
*/
test("calling the copyImage function should create temporary file") {
val f = fixture
testCopy(f.resPath, "sample.jpg", "test.jp2", JpegFile, f.fileHandler.createImageCopy)
deleteFiles("src/test/resources/test.jp2")
}
/**
* ATTENTION: Requires that ffmpeg is properly installed!
*/
test("calling the copyVideo function should create temporary file") {
val f = fixture
testCopy(f.resPath, "sample.mp4", "test.mp4", VideoMpeg4File, f.fileHandler.createVideoCopy)
deleteFiles("src/test/resources/test.mp4")
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment