diff --git a/flake.lock b/flake.lock index 42ea3b1..6769406 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1771369470, - "narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=", + "lastModified": 1781074563, + "narHash": "sha256-md8WlXOlfnIeHeOScMTTHFyf2d6iaTwPl2apR5EQ3P4=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "0182a361324364ae3f436a63005877674cf45efb", + "rev": "9ae611a455b90cf061d8f332b977e387bda8e1ca", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b28100a..d9eff05 100644 --- a/flake.nix +++ b/flake.nix @@ -31,6 +31,7 @@ scr = final.callPackage ./nix/scr.nix { }; thm = final.callPackage ./nix/thm.nix { }; vid2gif = final.callPackage ./nix/vid2gif.nix { }; + vidcompress = final.callPackage ./nix/vidcompress.nix { }; yemou-scripts = final.symlinkJoin { name = "yemou-scripts"; paths = [ @@ -39,6 +40,7 @@ scr thm vid2gif + vidcompress ]; }; }; @@ -50,6 +52,7 @@ scr = pkgs.scr; thm = pkgs.thm; vid2gif = pkgs.vid2gif; + vidcompress = pkgs.vidcompress; yemou-scripts = pkgs.yemou-scripts; }); }; diff --git a/nix/vidcompress.nix b/nix/vidcompress.nix new file mode 100644 index 0000000..7247609 --- /dev/null +++ b/nix/vidcompress.nix @@ -0,0 +1,26 @@ +{ + writeScriptBin, + bash, + coreutils, + ffmpeg, + ... +}: + +writeScriptBin "vidcompress" ( + builtins.replaceStrings + [ + "#!/bin/sh" + "ffmpeg " + "ffprobe " + "printf " + "rm " + ] + [ + "#!${bash}/bin/sh" + "${ffmpeg}/bin/ffmpeg " + "${ffmpeg}/bin/ffprobe " + "${coreutils}/bin/printf " + "${coreutils}/bin/rm " + ] + (builtins.readFile ../scritps/vidcompress) +) diff --git a/scritps/vidcompress b/scritps/vidcompress new file mode 100755 index 0000000..a67a6a7 --- /dev/null +++ b/scritps/vidcompress @@ -0,0 +1,64 @@ +#!/bin/sh +usage() { + printf '%b\n' "${0##*/} -i [OPTIONS]" \ + "\noptions:" \ + "\t-c CODEC - video codec to use (default: libx264)" \ + "\t-h - display this message" \ + "\t-o FILE - output file (default: out.ext)" \ + "\t-p PRESET - ffmpeg encoding preset to use (default: veryslow)" \ + "\t-t FILE_SIZE - file size to target in MiB (default: 50)" +} + +while [ "$*" ] +do + case $1 in + - ) shift; continue ;; + -- ) shift; break ;; + -* ) flag=${1#-}; shift ;; + * ) shift; continue ;; + esac + + while [ "$flag" ] + do + arg=${flag%"${flag#?}"} + + case $arg in + c ) VIDCOMP_CODEC=$1; shift ;; + h ) usage; exit 0 ;; + i ) VIDCOMP_INPUT_FILE=$1; shift ;; + o ) VIDCOMP_OUTPUT_FILE=$1; shift ;; + t ) VIDCOMP_TARGET_SIZE=$1; shift ;; + * ) printf '%s\n' "${0##*/}: -$arg: invalid argument" 1>&2 + usage 1>&2; exit 1 ;; + esac + + flag=${flag#?} + done +done + +[ -z "$VIDCOMP_INPUT_FILE" ] && { + printf '%s\n' "${0##*/}: missing input video" 1>&2 + usage 1>&2; exit 1 +} + +ext="${VIDCOMP_INPUT_FILE##.*}" +: "${VIDCOMP_OUTPUT_FILE:=out.${ext}}" + +: "${VIDCOMP_CODEC:=libx264}" +: "${VIDCOMP_TARGET_SIZE:=50}" +: "${VIDCOMP_PRESET:=veryslow}" + +a_bitrate="$(ffprobe -v error -select_streams a:0 -show_entries stream=bit_rate -of default=noprint_wrappers=1:nokey=1 \ + "${VIDCOMP_INPUT_FILE}")" +secs="$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${VIDCOMP_INPUT_FILE}")" +bitrate="$(fend floor \("${VIDCOMP_TARGET_SIZE} * 8388.608 / ${secs}" - \("${a_bitrate}" / 1000\)\))" + +ffmpeg -hide_banner -loglevel warning \ + -i "${VIDCOMP_INPUT_FILE}" -c:v "${VIDCOMP_CODEC}" -b:v "${bitrate}k" -preset "${VIDCOMP_PRESET}" -pass 1 \ + -an -f null -y /dev/null && \ +ffmpeg -hide_banner -loglevel warning \ + -i "${VIDCOMP_INPUT_FILE}" -c:v "${VIDCOMP_CODEC}" -b:v "${bitrate}k" -preset "${VIDCOMP_PRESET}" -pass 2 \ + -c:a copy "${VIDCOMP_OUTPUT_FILE}" + +rm ffmpeg2pass*.log +rm ffmpeg2pass*.log.mbtree