Created a Java w/ Maven project structure; added a simple directory creation and executes an FFMPEG command to transcode videos
This commit is contained in:
parent
fd31df7d56
commit
898d1467c0
28
.gitignore
vendored
28
.gitignore
vendored
@ -1,23 +1,5 @@
|
|||||||
# ---> Go
|
.classpath
|
||||||
# If you prefer the allow list template instead of the deny list, see community template:
|
.project
|
||||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
.settings/
|
||||||
#
|
target/
|
||||||
# Binaries for programs and plugins
|
.idea/
|
||||||
*.exe
|
|
||||||
*.exe~
|
|
||||||
*.dll
|
|
||||||
*.so
|
|
||||||
*.dylib
|
|
||||||
|
|
||||||
# Test binary, built with `go test -c`
|
|
||||||
*.test
|
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
|
||||||
*.out
|
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
|
||||||
# vendor/
|
|
||||||
|
|
||||||
# Go workspace file
|
|
||||||
go.work
|
|
||||||
|
|
||||||
|
2
LICENSE
2
LICENSE
@ -1,4 +1,4 @@
|
|||||||
Copyright (c) <year> <owner>
|
Copyright (c) 2022, Bit Goblin
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
86
pom.xml
Normal file
86
pom.xml
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>tech.bitgoblin</groupId>
|
||||||
|
<artifactId>Dragoon</artifactId>
|
||||||
|
<version>0.1.0</version>
|
||||||
|
|
||||||
|
<name>Dragoon</name>
|
||||||
|
<url>https://www.bitgoblin.tech</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
||||||
|
<plugins>
|
||||||
|
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
</plugin>
|
||||||
|
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
<configuration>
|
||||||
|
<!-- DO NOT include log4j.properties file in your Jar -->
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/log4j.properties</exclude>
|
||||||
|
</excludes>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<!-- Jar file entry point -->
|
||||||
|
<mainClass>tech.bitgoblin.App</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-install-plugin</artifactId>
|
||||||
|
<version>2.5.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.8.2</version>
|
||||||
|
</plugin>
|
||||||
|
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-site-plugin</artifactId>
|
||||||
|
<version>3.7.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</project>
|
17
src/main/java/tech/bitgoblin/App.java
Normal file
17
src/main/java/tech/bitgoblin/App.java
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
package tech.bitgoblin;
|
||||||
|
|
||||||
|
import tech.bitgoblin.video.Transcoder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Bit Goblin video transcoder service.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// create new Transcoder object and start the service
|
||||||
|
Transcoder t = new Transcoder("~/dragoon");
|
||||||
|
t.transcode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
27
src/main/java/tech/bitgoblin/io/IOUtils.java
Normal file
27
src/main/java/tech/bitgoblin/io/IOUtils.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package tech.bitgoblin.io;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class IOUtils {
|
||||||
|
|
||||||
|
public static void createDirectory(String path) {
|
||||||
|
File f = new File(path);
|
||||||
|
boolean res = f.mkdir();
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
System.out.println(path + " was created.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String resolveTilda(String path) {
|
||||||
|
if (path.startsWith("~" + File.separator)) {
|
||||||
|
path = System.getProperty("user.home") + path.substring(1);
|
||||||
|
} else if (path.startsWith("~")) {
|
||||||
|
// here you can implement reading homedir of other users if you care
|
||||||
|
throw new UnsupportedOperationException("Home dir expansion not implemented for explicit usernames");
|
||||||
|
}
|
||||||
|
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
102
src/main/java/tech/bitgoblin/video/Transcoder.java
Normal file
102
src/main/java/tech/bitgoblin/video/Transcoder.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package tech.bitgoblin.video;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.InterruptedException;
|
||||||
|
import java.lang.Process;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
import tech.bitgoblin.io.IOUtils;
|
||||||
|
|
||||||
|
public class Transcoder {
|
||||||
|
|
||||||
|
private String repo_dir;
|
||||||
|
private String ffmpeg_path = "/usr/bin/ffmpeg";
|
||||||
|
|
||||||
|
// only define the working directory; use default FFMPEG path
|
||||||
|
public Transcoder(String repo_dir) {
|
||||||
|
this.repo_dir = IOUtils.resolveTilda(repo_dir);
|
||||||
|
this.initDirectory();
|
||||||
|
}
|
||||||
|
// define a custom FFMPEG binary path
|
||||||
|
public Transcoder(String repo_dir, String ffmpeg_path) {
|
||||||
|
this.repo_dir = IOUtils.resolveTilda(repo_dir);
|
||||||
|
this.ffmpeg_path = ffmpeg_path;
|
||||||
|
this.initDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
// transcode files in the working directory
|
||||||
|
public void transcode() {
|
||||||
|
// search for files
|
||||||
|
System.out.println("Searching for files to transcode in " + this.repo_dir);
|
||||||
|
File repo = new File(Paths.get(this.repo_dir, "ingest").toString());
|
||||||
|
File[] sourceFiles = repo.listFiles();
|
||||||
|
|
||||||
|
// transcode
|
||||||
|
System.out.println("Transcoding files in " + this.repo_dir + "/ingest...");
|
||||||
|
for (File f : sourceFiles) {
|
||||||
|
String filePath = f.toString().substring(0, f.toString().lastIndexOf("."));
|
||||||
|
String filename = Paths.get(filePath).getFileName().toString();
|
||||||
|
String outputPath = Paths.get(this.repo_dir, "output", String.format("%s.mov", filename)).toString();
|
||||||
|
|
||||||
|
String cmd = String.format("%s -i %s -c:v %s -vf \"%s\" -profile:v %s -c:a %s %s",
|
||||||
|
this.ffmpeg_path, // FFMPEG binary path
|
||||||
|
f.toString(), // input file
|
||||||
|
"dnxhd", // video codec
|
||||||
|
"scale=1920x1080,fps=60,format=yuv422p", // video format
|
||||||
|
"dnxhr_hq", // video profile
|
||||||
|
"pcm_s16le", // audio codec
|
||||||
|
outputPath // output file path
|
||||||
|
);
|
||||||
|
|
||||||
|
ProcessBuilder pb = new ProcessBuilder(cmd.split("\\s+"));
|
||||||
|
pb.redirectErrorStream(true);
|
||||||
|
pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
|
||||||
|
try {
|
||||||
|
Process process = pb.start();
|
||||||
|
int ret = process.waitFor();
|
||||||
|
System.out.printf("Program exited with code: %d", ret);
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// end output
|
||||||
|
System.out.println("------------ End of transcoding ------------");
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensures the transcoder's working directory is available
|
||||||
|
private void initDirectory() {
|
||||||
|
// create transcoder directory
|
||||||
|
IOUtils.createDirectory(this.repo_dir);
|
||||||
|
// create the sub-directories
|
||||||
|
IOUtils.createDirectory(Paths.get(this.repo_dir, "ingest").toString());
|
||||||
|
IOUtils.createDirectory(Paths.get(this.repo_dir, "archive").toString());
|
||||||
|
IOUtils.createDirectory(Paths.get(this.repo_dir, "output").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Stream handler class for the Transcoder
|
||||||
|
private static class StreamGobbler implements Runnable {
|
||||||
|
private InputStream inputStream;
|
||||||
|
private Consumer<String> consumer;
|
||||||
|
|
||||||
|
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
20
src/test/java/tech/bitgoblin/AppTest.java
Normal file
20
src/test/java/tech/bitgoblin/AppTest.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package tech.bitgoblin;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for simple App.
|
||||||
|
*/
|
||||||
|
public class AppTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Rigorous Test :-)
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void shouldAnswerWithTrue()
|
||||||
|
{
|
||||||
|
assertTrue( true );
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user