Browse Source

allow split into directory

master
Jonathan Cobb 3 years ago
parent
commit
b4f7b74087
9 changed files with 150 additions and 4 deletions
  1. +3
    -0
      README.md
  2. +5
    -0
      src/main/java/jvcl/model/JAsset.java
  3. +24
    -1
      src/main/java/jvcl/op/SplitOperation.java
  4. +2
    -2
      src/test/java/javicle/test/BasicTest.java
  5. +98
    -0
      src/test/resources/outputs/..json
  6. BIN
     
  7. +0
    -0
     
  8. +14
    -0
      src/test/resources/tests/test_concat.json
  9. +4
    -1
      src/test/resources/tests/test_split.json

+ 3
- 0
README.md View File

@@ -152,3 +152,6 @@ Here is a complex example using multiple assets and operations:
]
}
```

## What's up with the name?
I dunno, a cross between a javelin and an icicle? does that have any positive connotations? ok then...

+ 5
- 0
src/main/java/jvcl/model/JAsset.java View File

@@ -20,6 +20,7 @@ import java.math.BigDecimal;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
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.StreamUtil.loadResourceAsStream;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.reflect.ReflectionUtil.copy;
@@ -42,6 +43,10 @@ public class JAsset {
@Getter @Setter private String dest;
public boolean hasDest() { return !empty(dest); }
public boolean destExists() { return new File(dest).exists(); }
public boolean destIsDirectory() { return new File(dest).isDirectory(); }
public File destDirectory() {
return mkdirOrDie(new File(dest.endsWith("/") ? dest.substring(0, dest.length()-1) : dest));
}

// if path was not a file, it got resolved to a file
// the original value of 'path' is stored here


+ 24
- 1
src/main/java/jvcl/op/SplitOperation.java View File

@@ -19,8 +19,10 @@ import java.util.Map;

import static jvcl.model.JAsset.json2asset;
import static jvcl.service.Toolbox.getDuration;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.empty;
import static org.cobbzilla.util.io.FileUtil.abs;
import static org.cobbzilla.util.io.FileUtil.mkdirOrDie;
import static org.cobbzilla.util.json.JsonUtil.json;
import static org.cobbzilla.util.system.CommandShell.execScript;

@@ -54,10 +56,27 @@ public class SplitOperation implements JOperator {
i.compareTo(endTime) < 0;
i = i.add(incr)) {

final File outfile = assetManager.assetPath(op, source, formatType, new Object[]{i, incr});
final File outfile;
if (output.hasDest()) {
if (!output.destExists()) {
outfile = sliceFile(output, formatType, i, incr);
} else {
if (output.destIsDirectory()) {
outfile = sliceFile(output, formatType, i, incr);
} else {
die("dest exists and is not a directory: "+output.getDest());
return;
}
}
} else {
outfile = assetManager.assetPath(op, source, formatType, new Object[]{i, incr});
}

if (outfile.exists()) {
log.info("operate: outfile exists, not re-creating: "+abs(outfile));
return;
} else {
mkdirOrDie(outfile.getParentFile());
}
final JAsset slice = new JAsset(output);
slice.setPath(abs(outfile));
@@ -75,6 +94,10 @@ public class SplitOperation implements JOperator {
log.info("operate: completed");
}

private File sliceFile(JAsset output, JFileExtension formatType, BigDecimal i, BigDecimal incr) {
return new File(output.destDirectory(), output.getName() + "_" + i + "_" + i.add(incr) + formatType.ext());
}

@NoArgsConstructor
private static class SplitConfig {



src/test/java/javicle/test/SplitTest.java → src/test/java/javicle/test/BasicTest.java View File

@@ -11,9 +11,9 @@ import static org.cobbzilla.util.io.FileUtil.abs;
import static org.cobbzilla.util.io.StreamUtil.loadResourceAsStream;
import static org.cobbzilla.util.io.StreamUtil.stream2file;

public class SplitTest {
public class BasicTest {

@Test public void testSplit () throws Exception {
@Test public void testSplitAndConcat () throws Exception {
@Cleanup("delete") final File specFile = stream2file(loadResourceAsStream("tests/test_split.json"));
Jvcl.main(new String[]{JvclOptions.LONGOPT_SPEC, abs(specFile)});
}

+ 98
- 0
src/test/resources/outputs/..json View File

@@ -0,0 +1,98 @@
{
"media": {
"@ref": "/Users/jonathan/git/javicle/src/test/resources/outputs/vid1_splits_65_75.mp4",
"track": [
{
"@type": "General",
"VideoCount": "1",
"AudioCount": "1",
"FileExtension": "mp4",
"Format": "MPEG-4",
"Format_Profile": "Base Media",
"CodecID": "isom",
"CodecID_Compatible": "isom/iso2/avc1/mp41",
"FileSize": "4887637",
"Duration": "75.022",
"OverallBitRate_Mode": "VBR",
"OverallBitRate": "521195",
"FrameRate": "29.970",
"FrameCount": "2248",
"StreamSize": "82479",
"HeaderSize": "40",
"DataSize": "4805166",
"FooterSize": "82431",
"IsStreamable": "No",
"Title": "Moonwalk One, ca. 1970 - http://www.archive.org/details/gov.archives.arc.1257628",
"Movie": "Moonwalk One, ca. 1970 - http://www.archive.org/details/gov.archives.arc.1257628",
"File_Modified_Date": "UTC 2020-12-12 00:09:41",
"File_Modified_Date_Local": "2020-12-11 19:09:41",
"Encoded_Application": "Lavf58.45.100",
"Comment": "license:http://creativecommons.org/licenses/publicdomain/"
},
{
"@type": "Video",
"StreamOrder": "0",
"ID": "1",
"Format": "AVC",
"Format_Profile": "High",
"Format_Level": "1.3",
"Format_Settings_CABAC": "Yes",
"Format_Settings_RefFrames": "4",
"CodecID": "avc1",
"Duration": "75.009",
"BitRate": "386043",
"Width": "320",
"Height": "240",
"Sampled_Width": "320",
"Sampled_Height": "240",
"PixelAspectRatio": "1.000",
"DisplayAspectRatio": "1.333",
"Rotation": "0.000",
"FrameRate_Mode": "CFR",
"FrameRate_Mode_Original": "VFR",
"FrameRate": "29.970",
"FrameCount": "2248",
"ColorSpace": "YUV",
"ChromaSubsampling": "4:2:0",
"BitDepth": "8",
"ScanType": "Progressive",
"StreamSize": "3619556",
"Encoded_Library": "x264 - core 161 r3027 4121277",
"Encoded_Library_Name": "x264",
"Encoded_Library_Version": "core 161 r3027 4121277",
"Encoded_Library_Settings": "cabac=1 / ref=3 / deblock=1:0:0 / analyse=0x3:0x113 / me=hex / subme=7 / psy=1 / psy_rd=1.00:0.00 / mixed_ref=1 / me_range=16 / chroma_me=1 / trellis=1 / 8x8dct=1 / cqm=0 / deadzone=21,11 / fast_pskip=1 / chroma_qp_offset=-2 / threads=7 / lookahead_threads=1 / sliced_threads=0 / nr=0 / decimate=1 / interlaced=0 / bluray_compat=0 / constrained_intra=0 / bframes=3 / b_pyramid=2 / b_adapt=1 / b_bias=0 / direct=1 / weightb=1 / open_gop=0 / weightp=2 / keyint=250 / keyint_min=25 / scenecut=40 / intra_refresh=0 / rc_lookahead=40 / rc=crf / mbtree=1 / crf=23.0 / qcomp=0.60 / qpmin=0 / qpmax=69 / qpstep=4 / ip_ratio=1.40 / aq=1:1.00",
"extra": {
"CodecConfigurationBox": "avcC"
}
},
{
"@type": "Audio",
"StreamOrder": "1",
"ID": "2",
"Format": "AAC",
"Format_Settings_SBR": "No (Explicit)",
"Format_AdditionalFeatures": "LC",
"CodecID": "mp4a-40-2",
"Duration": "75.022",
"Duration_LastFrame": "-0.008",
"BitRate_Mode": "VBR",
"BitRate": "126428",
"BitRate_Maximum": "128000",
"Channels": "2",
"ChannelPositions": "Front: L R",
"ChannelLayout": "L R",
"SamplesPerFrame": "1024",
"SamplingRate": "48000",
"SamplingCount": "3601056",
"FrameRate": "46.875",
"FrameCount": "3517",
"Compression_Mode": "Lossy",
"StreamSize": "1185602",
"StreamSize_Proportion": "0.24257",
"Default": "Yes",
"AlternateGroup": "1"
}
]
}
}


BIN
View File


+ 0
- 0
View File


+ 14
- 0
src/test/resources/tests/test_concat.json View File

@@ -0,0 +1,14 @@
{
"assets": [
{ "name": "vid1_splits" }
],
"operations": [
{
"operation": "concat",
"creates": "combined_vid",
"perform": {
"concat": ["vid1_splits[1..{{vid1_splits.length}}"]
}
}
]
}

+ 4
- 1
src/test/resources/tests/test_split.json View File

@@ -14,7 +14,10 @@
"operations": [
{
"operation": "split", // name of the operation
"creates": "vid1_splits", // assets it creates, will be an array asset
"creates": {
"name": "vid1_splits",
"dest": "src/test/resources/outputs/"
},
"perform": {
"split": "vid1", // split this source asset
"interval": "10s", // split every ten seconds


Loading…
Cancel
Save