@@ -75,7 +75,7 @@ Split an audio/video asset into multiple assets | |||||
Concatenate audio/video assets together into one asset | Concatenate audio/video assets together into one asset | ||||
### trim | ### trim | ||||
Trim audio/video - crop from beginning, end, or both | |||||
Trim audio/video; crop a section of an asset, becomes a new asset | |||||
### overlay | ### overlay | ||||
Overlay one video file onto another | Overlay one video file onto another | ||||
@@ -24,8 +24,7 @@ import java.util.stream.Collectors; | |||||
import static java.util.Comparator.comparing; | import static java.util.Comparator.comparing; | ||||
import static org.cobbzilla.util.daemon.ZillaRuntime.*; | import static org.cobbzilla.util.daemon.ZillaRuntime.*; | ||||
import static org.cobbzilla.util.http.HttpSchemes.isHttpOrHttps; | import static org.cobbzilla.util.http.HttpSchemes.isHttpOrHttps; | ||||
import static org.cobbzilla.util.io.FileUtil.abs; | |||||
import static org.cobbzilla.util.io.FileUtil.mkdirOrDie; | |||||
import static org.cobbzilla.util.io.FileUtil.*; | |||||
import static org.cobbzilla.util.io.StreamUtil.loadResourceAsStream; | import static org.cobbzilla.util.io.StreamUtil.loadResourceAsStream; | ||||
import static org.cobbzilla.util.json.JsonUtil.json; | import static org.cobbzilla.util.json.JsonUtil.json; | ||||
import static org.cobbzilla.util.reflect.ReflectionUtil.copy; | import static org.cobbzilla.util.reflect.ReflectionUtil.copy; | ||||
@@ -43,6 +42,7 @@ public class JAsset { | |||||
@Getter @Setter private String name; | @Getter @Setter private String name; | ||||
@Getter @Setter private String path; | @Getter @Setter private String path; | ||||
public boolean hasPath() { return !empty(path); } | |||||
// an asset can specify where its file should live | // an asset can specify where its file should live | ||||
// if the file already exists, it is used and not overwritten | // if the file already exists, it is used and not overwritten | ||||
@@ -67,7 +67,21 @@ public class JAsset { | |||||
} | } | ||||
public boolean hasDest() { return !empty(dest); } | public boolean hasDest() { return !empty(dest); } | ||||
public boolean destExists() { return new File(dest).exists(); } | |||||
public boolean destExists() { return new File(destPath()).exists(); } | |||||
public String destPath() { | |||||
if (destIsDirectory()) { | |||||
if (hasPath()) { | |||||
return abs(new File(destDirectory(), basename(getPath()))); | |||||
} else { | |||||
return abs(destDirectory()); | |||||
} | |||||
} else { | |||||
return abs(new File(dest)); | |||||
} | |||||
} | |||||
public boolean destIsDirectory() { return new File(dest).isDirectory(); } | public boolean destIsDirectory() { return new File(dest).isDirectory(); } | ||||
public File destDirectory() { | public File destDirectory() { | ||||
return mkdirOrDie(new File(dest.endsWith("/") ? dest.substring(0, dest.length()-1) : dest)); | return mkdirOrDie(new File(dest.endsWith("/") ? dest.substring(0, dest.length()-1) : dest)); | ||||
@@ -76,6 +90,7 @@ public class JAsset { | |||||
// if path was not a file, it got resolved to a file | // if path was not a file, it got resolved to a file | ||||
// the original value of 'path' is stored here | // the original value of 'path' is stored here | ||||
@Getter @Setter private String originalPath; | @Getter @Setter private String originalPath; | ||||
public boolean hasOriginalPath () { return !empty(originalPath); } | |||||
@Getter @Setter private JAsset[] list; | @Getter @Setter private JAsset[] list; | ||||
public boolean hasList () { return list != null; } | public boolean hasList () { return list != null; } | ||||
@@ -143,10 +158,12 @@ public class JAsset { | |||||
if (empty(path)) return die("initPath: no path!"); | if (empty(path)) return die("initPath: no path!"); | ||||
// if dest already exists, use that | // if dest already exists, use that | ||||
if (hasDest() && destExists()) { | |||||
setOriginalPath(path); | |||||
setPath(getDest()); | |||||
return this; | |||||
if (hasDest()) { | |||||
if (destExists()) { | |||||
setOriginalPath(path); | |||||
setPath(destPath()); | |||||
return this; | |||||
} | |||||
} | } | ||||
final File sourcePath = hasDest() ? new File(getDest()) : assetManager.sourcePath(getName()); | final File sourcePath = hasDest() ? new File(getDest()) : assetManager.sourcePath(getName()); | ||||
@@ -58,7 +58,7 @@ public class ConcatOperation implements JOperator { | |||||
// create output object | // create output object | ||||
final JAsset output = json2asset(op.getCreates()); | final JAsset output = json2asset(op.getCreates()); | ||||
if (output.hasDest() && output.destExists()) { | if (output.hasDest() && output.destExists()) { | ||||
log.info("operate: dest exists, not re-creating: "+output.getDest()); | |||||
log.info("operate: dest exists, not re-creating: "+output.destPath()); | |||||
return; | return; | ||||
} | } | ||||
@@ -68,7 +68,7 @@ public class ConcatOperation implements JOperator { | |||||
// set the path, check if output asset already exists | // set the path, check if output asset already exists | ||||
final JFileExtension formatType = output.getFormat().getFileExtension(); | final JFileExtension formatType = output.getFormat().getFileExtension(); | ||||
final File outfile = output.hasDest() | final File outfile = output.hasDest() | ||||
? new File(output.getDest()) | |||||
? new File(output.destPath()) | |||||
: assetManager.assetPath(op, sources, formatType); | : assetManager.assetPath(op, sources, formatType); | ||||
if (outfile.exists()) { | if (outfile.exists()) { | ||||
log.info("operate: outfile exists, not re-creating: "+abs(outfile)); | log.info("operate: outfile exists, not re-creating: "+abs(outfile)); | ||||
@@ -80,6 +80,7 @@ public class SplitOperation implements JOperator { | |||||
} | } | ||||
final JAsset slice = new JAsset(output); | final JAsset slice = new JAsset(output); | ||||
slice.setPath(abs(outfile)); | slice.setPath(abs(outfile)); | ||||
slice.setName(source.getName()+"_"+i+"_"+incr); | |||||
ctx.put("output", slice); | ctx.put("output", slice); | ||||
ctx.put("startSeconds", i); | ctx.put("startSeconds", i); | ||||
@@ -95,7 +96,7 @@ public class SplitOperation implements JOperator { | |||||
} | } | ||||
private File sliceFile(JAsset output, JFileExtension formatType, BigDecimal i, BigDecimal incr) { | private File sliceFile(JAsset output, JFileExtension formatType, BigDecimal i, BigDecimal incr) { | ||||
return new File(output.destDirectory(), output.getName() + "_" + i + "_" + i.add(incr) + formatType.ext()); | |||||
return new File(output.destDirectory(), output.getName() + "_" + i + "_" + incr + formatType.ext()); | |||||
} | } | ||||
@NoArgsConstructor | @NoArgsConstructor | ||||
@@ -8,6 +8,7 @@ import jvcl.service.Toolbox; | |||||
public class TrimOperation implements JOperator { | public class TrimOperation implements JOperator { | ||||
@Override public void operate(JOperation op, Toolbox toolbox, AssetManager assetManager) { | @Override public void operate(JOperation op, Toolbox toolbox, AssetManager assetManager) { | ||||
} | } | ||||
} | } |
@@ -62,7 +62,9 @@ public class Toolbox { | |||||
private final Map<String, JMediaInfo> infoCache = new ConcurrentHashMap<>(); | private final Map<String, JMediaInfo> infoCache = new ConcurrentHashMap<>(); | ||||
public JMediaInfo getInfo(JAsset asset) { | public JMediaInfo getInfo(JAsset asset) { | ||||
final File infoFile = new File(replaceExt(asset.getPath(), ".json")); | |||||
if (!asset.hasPath()) return die("getInfo: no path for asset: "+asset); | |||||
final String infoName = replaceExt(asset.getPath(), ".json"); | |||||
final File infoFile = new File(infoName); | |||||
final String infoPath = abs(infoFile); | final String infoPath = abs(infoFile); | ||||
if (!infoFile.exists() || infoFile.length() == 0) { | if (!infoFile.exists() || infoFile.length() == 0) { | ||||
execScript(getMediainfo() + " --Output=JSON " + abs(asset.getPath())+" > "+infoPath); | execScript(getMediainfo() + " --Output=JSON " + abs(asset.getPath())+" > "+infoPath); | ||||