mirror of
https://github.com/Alfresco/alfresco-transform-core.git
synced 2025-08-14 17:58:27 +00:00
ATS-812: PoC FFmpeg (experimental) - add duration (in addition to timeOffset) to enable video/audio trim
- only set default frames num (1) if target is a supported image format (note: currently configured for jpg and png)
This commit is contained in:
@@ -38,6 +38,8 @@ import java.io.File;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.alfresco.transformer.util.RequestParamMap.FRAMES_NUM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the FFmpeg transformer.
|
* Controller for the FFmpeg transformer.
|
||||||
*
|
*
|
||||||
@@ -67,6 +69,14 @@ public class FFmpegController extends AbstractTransformerController
|
|||||||
FFmpegController
|
FFmpegController
|
||||||
.class);
|
.class);
|
||||||
|
|
||||||
|
public static final String PREFIX_IMAGE = "image/";
|
||||||
|
|
||||||
|
public static final String FILE_EXT_PNG = "png";
|
||||||
|
public static final String FILE_EXT_JPG = "jpg";
|
||||||
|
public static final String FILE_EXT_JPEG = "jpeg";
|
||||||
|
|
||||||
|
private static final int DEFAULT_FRAMES_NUM_1 = 1;
|
||||||
|
|
||||||
@Value("${transform.core.ffmpeg.exe}")
|
@Value("${transform.core.ffmpeg.exe}")
|
||||||
private String execPath;
|
private String execPath;
|
||||||
|
|
||||||
@@ -117,6 +127,34 @@ public class FFmpegController extends AbstractTransformerController
|
|||||||
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
|
public void transformImpl(String transformName, String sourceMimetype, String targetMimetype,
|
||||||
Map<String, String> transformOptions, File sourceFile, File targetFile)
|
Map<String, String> transformOptions, File sourceFile, File targetFile)
|
||||||
{
|
{
|
||||||
|
// TODO PoC FFmpeg - initially "single frame" for image target
|
||||||
|
if (isTargetImage(targetMimetype, targetFile))
|
||||||
|
{
|
||||||
|
transformOptions.put(FRAMES_NUM, Integer.toString(DEFAULT_FRAMES_NUM_1));
|
||||||
|
}
|
||||||
|
|
||||||
commandExecutor.transform(sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
|
commandExecutor.transform(sourceMimetype, targetMimetype, transformOptions, sourceFile, targetFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO PoC FFmpeg - refactor and enhance (for configured / supported image formats etc)
|
||||||
|
private boolean isTargetImage(String targetMimetype, File targetFile)
|
||||||
|
{
|
||||||
|
if ((targetMimetype != null) && (targetMimetype.startsWith(PREFIX_IMAGE)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetFile != null) {
|
||||||
|
String[] split = targetFile.getName().split("\\.");
|
||||||
|
if (split.length > 0) {
|
||||||
|
String ext = split[split.length - 1];
|
||||||
|
|
||||||
|
return (FILE_EXT_JPEG.equalsIgnoreCase(ext) ||
|
||||||
|
FILE_EXT_JPG.equalsIgnoreCase(ext) ||
|
||||||
|
FILE_EXT_PNG.equalsIgnoreCase(ext));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
|
<tr><td><div style="text-align:right">testDelay</div></td><td><input type="text" name="testDelay" value="" /></td></tr>
|
||||||
|
|
||||||
<tr><td><div style="text-align:right">timeOffset</div></td><td><input type="text" name="timeOffset" value="" /></td></tr>
|
<tr><td><div style="text-align:right">timeOffset</div></td><td><input type="text" name="timeOffset" value="" /></td></tr>
|
||||||
|
<tr><td><div style="text-align:right">duration</div></td><td><input type="text" name="duration" value="" /></td></tr>
|
||||||
|
|
||||||
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
|
<tr><td></td><td><input type="submit" value="Transform" /></td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"transformOptions": {
|
"transformOptions": {
|
||||||
"ffmpegOptions": [
|
"ffmpegOptions": [
|
||||||
{"value": {"name": "timeOffset"}}
|
{"value": {"name": "timeOffset"}},
|
||||||
|
{"value": {"name": "duration"}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transformers": [
|
"transformers": [
|
||||||
|
@@ -37,6 +37,8 @@ import java.util.StringJoiner;
|
|||||||
public final class FFmpegOptionsBuilder
|
public final class FFmpegOptionsBuilder
|
||||||
{
|
{
|
||||||
private String timeOffset;
|
private String timeOffset;
|
||||||
|
private String duration;
|
||||||
|
|
||||||
private Integer framesNum;
|
private Integer framesNum;
|
||||||
|
|
||||||
// TODO PoC - add other FFmpeg transform options ...
|
// TODO PoC - add other FFmpeg transform options ...
|
||||||
@@ -54,6 +56,12 @@ public final class FFmpegOptionsBuilder
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FFmpegOptionsBuilder withDuration(final String duration)
|
||||||
|
{
|
||||||
|
this.duration = duration;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public String build()
|
public String build()
|
||||||
{
|
{
|
||||||
StringJoiner args = new StringJoiner(" ");
|
StringJoiner args = new StringJoiner(" ");
|
||||||
@@ -68,6 +76,11 @@ public final class FFmpegOptionsBuilder
|
|||||||
args.add("-frames:v "+framesNum);
|
args.add("-frames:v "+framesNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (duration != null)
|
||||||
|
{
|
||||||
|
args.add("-t "+duration);
|
||||||
|
}
|
||||||
|
|
||||||
return args.toString();
|
return args.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -33,8 +33,8 @@ import java.io.File;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.alfresco.transformer.util.RequestParamMap.TIMEOUT;
|
import static org.alfresco.transformer.util.RequestParamMap.*;
|
||||||
import static org.alfresco.transformer.util.RequestParamMap.TIME_OFFSET;
|
import static org.alfresco.transformer.util.Util.stringToInteger;
|
||||||
import static org.alfresco.transformer.util.Util.stringToLong;
|
import static org.alfresco.transformer.util.Util.stringToLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +78,9 @@ public class FFmpegCommandExecutor extends AbstractCommandExecutor
|
|||||||
RuntimeExec runtimeExec = new RuntimeExec();
|
RuntimeExec runtimeExec = new RuntimeExec();
|
||||||
Map<String, String[]> commandsAndArguments = new HashMap<>();
|
Map<String, String[]> commandsAndArguments = new HashMap<>();
|
||||||
|
|
||||||
// TODO PoC for FFmpeg - check against Gytheio: -y SPLIT:${sourceOptions} -i ${source} SPLIT:${targetOptions} ${target}
|
// TODO PoC for FFmpeg
|
||||||
|
// - for now, current options are all target options (ie. after -i)
|
||||||
|
// - check against Gytheio: -y SPLIT:${sourceOptions} -i ${source} SPLIT:${targetOptions} ${target}
|
||||||
commandsAndArguments.put(".*",
|
commandsAndArguments.put(".*",
|
||||||
new String[]{EXE, "-y", "-i", "${source}", "SPLIT:${options}", "${target}"});
|
new String[]{EXE, "-y", "-i", "${source}", "SPLIT:${options}", "${target}"});
|
||||||
|
|
||||||
@@ -113,11 +115,17 @@ public class FFmpegCommandExecutor extends AbstractCommandExecutor
|
|||||||
String timeOffset = transformOptions.get(TIME_OFFSET);
|
String timeOffset = transformOptions.get(TIME_OFFSET);
|
||||||
if (timeOffset != null)
|
if (timeOffset != null)
|
||||||
{
|
{
|
||||||
// TODO check target mimetype (to be supported image formats) for "single frame" option
|
|
||||||
optionsBuilder.withTimeOffset(transformOptions.get(TIME_OFFSET));
|
optionsBuilder.withTimeOffset(transformOptions.get(TIME_OFFSET));
|
||||||
optionsBuilder.withFramesNum(FRAMES_NUM_1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String duration = transformOptions.get(DURATION);
|
||||||
|
if (duration != null)
|
||||||
|
{
|
||||||
|
optionsBuilder.withDuration(transformOptions.get(DURATION));
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsBuilder.withFramesNum(stringToInteger(transformOptions.get(FRAMES_NUM)));
|
||||||
|
|
||||||
final String options = optionsBuilder.build();
|
final String options = optionsBuilder.build();
|
||||||
|
|
||||||
Long timeout = stringToLong(transformOptions.get(TIMEOUT));
|
Long timeout = stringToLong(transformOptions.get(TIMEOUT));
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"transformOptions": {
|
"transformOptions": {
|
||||||
"ffmpegOptions": [
|
"ffmpegOptions": [
|
||||||
{"value": {"name": "timeOffset"}}
|
{"value": {"name": "timeOffset"}},
|
||||||
|
{"value": {"name": "duration"}}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"transformers": [
|
"transformers": [
|
||||||
|
@@ -75,4 +75,6 @@ public interface RequestParamMap
|
|||||||
|
|
||||||
// TODO PoC for FFmpeg
|
// TODO PoC for FFmpeg
|
||||||
String TIME_OFFSET = "timeOffset";
|
String TIME_OFFSET = "timeOffset";
|
||||||
|
String DURATION = "duration";
|
||||||
|
String FRAMES_NUM = "framesNum";
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user