Browse Source

add more command line utilities

master
Jonathan Cobb 3 years ago
parent
commit
f2ab6a385e
9 changed files with 264 additions and 11 deletions
  1. +66
    -0
      bin/jconcat
  2. +46
    -0
      bin/jletterbox
  3. +67
    -0
      bin/jscale
  4. +49
    -0
      bin/jsplit
  5. +3
    -2
      bin/jtrim
  6. +20
    -0
      bin/jvcl_common
  7. +2
    -3
      src/main/java/jvcl/main/JvclOptions.java
  8. +2
    -2
      src/main/java/jvcl/service/AssetManager.java
  9. +9
    -4
      src/test/resources/tests/test_concat.jvcl

+ 66
- 0
bin/jconcat View File

@@ -0,0 +1,66 @@
#!/bin/bash
#
# Concatenate media files
#
# Usage:
#
# jconcat out-file in-file-1 [in-file-2 ...]
#
# out-file : output file
# in-file-N : input files
#
# BEWARE SHELL WILDCARDS!
# Shell wildcards will match files in non-deterministic order, meaning that
# your combined file will be assembled out of order.
#
# If you are combining files that were split with `jvcl` (or `jsplit`), then
# sorting them by time (oldest first) is sufficient.
#
# For example, do this:
#
# jconcat combined-file.mp4 $(ls -1tr path/to/parts*.mp4)
#
# NOT THIS:
#
# jconcat combined-file.mp4 path/to/parts*.mp4 # args not ordered!
#
SCRIPT="${0}"
SCRIPT_DIR="$(cd "$(dirname "${SCRIPT}")" && pwd)"
. "${SCRIPT_DIR}"/jvcl_common

OUT_FILE="${1?no out-file provided}"
shift

IN_FILE="${1?no in-file(s) provided}"
echo "
{
\"assets\": [
$(
F_INDEX=0
for path in "$@" ; do
if [[ ${F_INDEX} -gt 0 ]] ; then
echo ","
fi
F_INDEX=$((F_INDEX + 1))
echo -n " { \"name\": \"input_${F_INDEX}\", \"path\": \"${path}\" }"
shift
done)
],
\"operations\": [
{
\"operation\": \"concat\",
\"creates\": {
\"name\": \"combined\",
\"dest\": \"${OUT_FILE}\"
},
\"sources\": [$(END=$#
for ((i=1;i<=END;i++)); do
if [[ ${i} -gt 1 ]] ; then echo -n "," ; fi
echo -n "
\"input_${i}\""
done)
]
}
]
}
" | "${SCRIPT_DIR}"/jvcl -z ${JVCL_OPTIONS}

+ 46
- 0
bin/jletterbox View File

@@ -0,0 +1,46 @@
#!/bin/bash
#!/bin/bash
#
# Letterbox a video file
#
# Usage:
#
# jletterbox in-file out-file width height [color]
#
# in-file : file to trim
# out-file : write scaled file here
# width : output width
# height : output height
# color : padding color, can be a hex value (0xff0000 is red), or a color
# name from https://ffmpeg.org/ffmpeg-utils.html#color-syntax
#
SCRIPT="${0}"
SCRIPT_DIR="$(cd "$(dirname "${SCRIPT}")" && pwd)"
. "${SCRIPT_DIR}"/jvcl_common

IN_FILE="${1?no in-file provided}"
OUT_FILE="${2?no out-file provided}"
WIDTH="${3}"
HEIGHT="${4}"
COLOR="${5:-black}"

echo "
{
\"assets\": [
{ \"name\": \"input\", \"path\": \"${IN_FILE}\" }
],
\"operations\": [
{
\"operation\": \"letterbox\",
\"creates\": {
\"name\": \"boxed\",
\"dest\": \"${OUT_FILE}\"
},
\"source\": \"input\",
\"width\": \"${WIDTH}\",
\"height\": \"${HEIGHT}\",
\"color\": \"${COLOR}\"
}
]
}
" | "${SCRIPT_DIR}"/jvcl ${JVCL_OPTIONS}

+ 67
- 0
bin/jscale View File

@@ -0,0 +1,67 @@
#!/bin/bash
#
# Scale a media file
#
# Usage:
#
# jscale in-file out-file factor
# or
# jscale in-file out-file width height
#
# in-file : file to trim
# out-file : write scaled file here
# factor : scale factor
# width : output width
# height : output height
#
SCRIPT="${0}"
SCRIPT_DIR="$(cd "$(dirname "${SCRIPT}")" && pwd)"
. "${SCRIPT_DIR}"/jvcl_common

IN_FILE="${1?no in-file provided}"
OUT_FILE="${2?no out-file provided}"
WIDTH="${3}"
HEIGHT="${4}"
FACTOR=""

if [[ -z "${HEIGHT}" ]] ; then
FACTOR=${WIDTH}
echo "
{
\"assets\": [
{ \"name\": \"input\", \"path\": \"${IN_FILE}\" }
],
\"operations\": [
{
\"operation\": \"scale\",
\"creates\": {
\"name\": \"scaled\",
\"dest\": \"${OUT_FILE}\"
},
\"source\": \"input\",
\"factor\": \"${FACTOR}\"
}
]
}
" | "${SCRIPT_DIR}"/jvcl ${JVCL_OPTIONS}
else
echo "
{
\"assets\": [
{ \"name\": \"input\", \"path\": \"${IN_FILE}\" }
],
\"operations\": [
{
\"operation\": \"scale\",
\"creates\": {
\"name\": \"scaled\",
\"dest\": \"${OUT_FILE}\"
},
\"source\": \"input\",
\"width\": \"${WIDTH}\",
\"height\": \"${HEIGHT}\"
}
]
}
" | "${SCRIPT_DIR}"/jvcl ${JVCL_OPTIONS}
fi

+ 49
- 0
bin/jsplit View File

@@ -0,0 +1,49 @@
#!/bin/bash
#
# Split a media file into multiple files of equal time length
#
# Usage:
#
# jsplit in-file out-dir interval [start] [end]
#
# in-file : file to trim
# out-dir : write split files to this directory (will be created if it does not exist)
# interval : time duration of output files, in seconds
# start : when to start splitting the in-file. default is 0 (start)
# end : when to stop splitting the in-file. default is to continue until end of file is reached
#
SCRIPT="${0}"
SCRIPT_DIR="$(cd "$(dirname "${SCRIPT}")" && pwd)"
. "${SCRIPT_DIR}"/jvcl_common

IN_FILE="${1?no in-file provided}"
OUT_DIR="${2?no out-dir provided}"
if [[ -e "${OUT_DIR}" && ! -d "${OUT_DIR}" ]] ; then
die "Not a directory: ${OUT_DIR}"
fi
mkdir -p "${OUT_DIR}" || die "Error creating ${OUT_DIR}"

INTERVAL="${3?no interval provided}"
T_START="${4}"
T_END="${5}"

echo "
{
\"assets\": [
{ \"name\": \"input\", \"path\": \"${IN_FILE}\" }
],
\"operations\": [
{
\"operation\": \"split\",
\"creates\": {
\"name\": \"splits\",
\"dest\": \"${OUT_DIR}/\"
},
\"source\": \"input\",
\"interval\": \"${INTERVAL}\"$(if [[ -n "${T_START}" ]] ; then echo ",
\"start\": \"${T_START}\"" ; fi)$(if [[ -n "${T_END}" ]] ; then echo ",
\"end\": \"${T_END}\"," ; fi)
}
]
}
" | "${SCRIPT_DIR}"/jvcl ${JVCL_OPTIONS}

+ 3
- 2
bin/jtrim View File

@@ -19,6 +19,7 @@ IN_FILE="${1?no in-file provided}"
OUT_FILE="${2?no out-file provided}"
T_START="${3}"
T_END="${4}"

echo "
{
\"assets\": [
@@ -31,10 +32,10 @@ echo "
\"name\": \"trimmed\",
\"dest\": \"${OUT_FILE}\"
},
\"trim\": \"input\",
\"source\": \"input\",
\"start\": \"${T_START}\",
\"end\": \"${T_END}\"
}
]
}
" | "${SCRIPT_DIR}"/jvcl
" | "${SCRIPT_DIR}"/jvcl ${JVCL_OPTIONS}

+ 20
- 0
bin/jvcl_common View File

@@ -19,6 +19,15 @@ function handle_help_request() {
break
fi
done <"${1}"
echo "# Environment Variables
#
# JVCL_SCRATCH_DIR : Use this as the scratch directory
# Default is to create a new temp directory
#
# JVCL_NO_EXEC : If set to anything, print the commands that would
# have run but do not execute anything
#
"
exit 1
fi
}
@@ -33,4 +42,15 @@ if [[ -z "${JVCL_JAR}" ]] ; then
fi
fi

SCRATCH_DIR=""
if [[ -n "${JVCL_SCRATCH_DIR}" ]] ; then
SCRATCH_DIR="--temp-dir ${JVCL_SCRATCH_DIR}"
fi

NO_EXEC=""
if [[ -n "${JVCL_NO_EXEC}" ]] ; then
NO_EXEC="--no-exec"
fi
JVCL_OPTIONS="${SCRATCH_DIR} ${NO_EXEC}"

handle_help_request "${0}" "${1}"

+ 2
- 3
src/main/java/jvcl/main/JvclOptions.java View File

@@ -12,8 +12,7 @@ import org.kohsuke.args4j.Option;
import java.io.File;

import static jvcl.service.Toolbox.JSON_MAPPER;
import static org.cobbzilla.util.daemon.ZillaRuntime.die;
import static org.cobbzilla.util.daemon.ZillaRuntime.readStdin;
import static org.cobbzilla.util.daemon.ZillaRuntime.*;
import static org.cobbzilla.util.io.FileUtil.abs;
import static org.cobbzilla.util.io.FileUtil.toStringOrDie;
import static org.cobbzilla.util.json.JsonUtil.json;
@@ -37,7 +36,7 @@ public class JvclOptions extends BaseMainOptions {
try {
return json(json, JSpec.class, JSON_MAPPER);
} catch (Exception e) {
return die("getSpec: invalid spec: "+specFile);
return die("getSpec: invalid spec: "+specFile+": "+shortError(e));
}
}



+ 2
- 2
src/main/java/jvcl/service/AssetManager.java View File

@@ -120,7 +120,7 @@ public class AssetManager {
final int fromIndex = parseIndexExpression(from, list, JIndexType.from);
final int toIndex = parseIndexExpression(to, list, JIndexType.to);
if (toIndex < fromIndex) return die("parseIndexExpression("+indexExpr+"): 'to' index ("+toIndex+") < 'from' index ("+fromIndex+")");
final int len = toIndex - fromIndex;
final int len = 1 + (toIndex - fromIndex);
final JAsset[] subList = new JAsset[len];
System.arraycopy(list, fromIndex, subList, 0, len);
return new JAsset(asset).setList(subList);
@@ -142,7 +142,7 @@ public class AssetManager {
if (empty(indexExpr)) {
switch (type) {
case from: return 0;
case to: return list.length;
case to: return list.length-1;
case single: return die("parseIndexExpression(): no expression provided!");
default: return die("parseIndexExpression(): invalid type: "+type);
}


+ 9
- 4
src/test/resources/tests/test_concat.jvcl View File

@@ -6,11 +6,16 @@
"operations": [
{
"operation": "concat", // name of the operation
"sources": ["vid1_splits[1..]"], // concatentate these sources (everything but the first video in vid1_splits)
"sources": ["vid1_splits"], // concatentate these sources -- all split files
"creates": {
"name": "combined_vid", // name of the output asset
"dest": "src/test/resources/outputs/combined.mp4" // asset will be written to this file
},
"name": "combined_vid1", // name of the output asset
"dest": "src/test/resources/outputs/combined1.mp4" // asset will be written to this file
}
},
{
"operation": "concat", // name of the operation
"sources": ["vid1_splits[1..2]"], // concatentate these sources -- the 2nd and 3rd files only
"creates": "combined_vid2", // name of the output asset, will be written to scratch directory
}
]
}

Loading…
Cancel
Save