#!/usr/bin/env bash #=============================================================================== # # FILE: speedup # # USAGE: ./speedup [-s ...] [-t ...] [-m] [-c] [-d] [-D] [-h] filename # # DESCRIPTION: A script to perform a speedup and silence removal on a given # audio file # # OPTIONS: --- # REQUIREMENTS: --- # BUGS: --- # NOTES: --- # AUTHOR: Dave Morriss (djm), Dave.Morriss@gmail.com # VERSION: 0.0.4 # CREATED: 2015-05-01 21:51:32 # REVISION: 2016-04-22 11:35:08 # #=============================================================================== set -o nounset # Treat unset variables as an error SCRIPT=${0##*/} VERSION="0.0.4" #=== FUNCTION ================================================================ # NAME: _usage # DESCRIPTION: Report usage # PARAMETERS: 1 - the exit value (so it can be used to return an error # value) # RETURNS: Nothing #=============================================================================== _usage () { local res="${1:-0}" cat <<-endusage Usage: ${SCRIPT} [-s ...] [-t ...] [-m] [-c] [-d] [-D] [-h] filename Speeds up and truncates silence in an audio file Options: -s This option if present causes the audio to be sped up. The option can be repeated and the speed up is increased for every -s given -t This option if present causes the audio to have silences truncated. The option can be repeated to increase the sensitivity of the truncation -m Mix-down multiple (stereo) tracks to mono -c Delete the original file leaving the modified file behind with the same name as the original -d Engage dry-run mode where the planned actions are reported but nothing is actually done -D Run in DEBUG mode where more information is reported about what is going on -h Print this help Arguments: filename The full path of the audio file containing the podcast episode. Note: Unless deleted with the -c option the script will rename the original file and create the modified file with the same name as the original. The original file will have the name 'NAME_.EXT' with an underscore added after the original name. Version: $VERSION endusage exit "$res" } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # # Default settings # CLEANUP=0 DEBUG=0 DRYRUN=0 SPEEDUP=0 TRUNCATE=0 MIXDOWN=0 # # Process options # while getopts :cDdhmst opt do case "${opt}" in c) CLEANUP=1;; D) DEBUG=1;; d) DRYRUN=1;; s) ((SPEEDUP++));; t) ((TRUNCATE++));; m) MIXDOWN=1;; h) _usage 1;; *) _usage 1;; esac done shift $((OPTIND - 1)) # # Check there is one argument # if [[ $# -ne 1 ]]; then echo "Error: filename missing" _usage 1 fi # # Does the file given as an argument exist? # if [[ ! -e "$1" ]]; then echo "File not found: $1" exit 1 fi if [[ $DRYRUN -eq 1 ]]; then echo "Dry run: no changes will be made" fi # # Work out the speed-up we want (if any) and generate the argument to sox # SPEEDS=( 1.05 1.1 1.2 1.3 1.4 1.5 1.6 1.7 ) if [[ $SPEEDUP -eq 0 ]]; then TEMPO= else if [[ $SPEEDUP -gt ${#SPEEDS[@]} ]]; then SPEEDUP=${#SPEEDS[@]} fi ((SPEEDUP--)) speed=${SPEEDS[$SPEEDUP]} TEMPO="tempo ${speed}" fi # # Work out the silence truncation parameters (if any). The first set trims # silence but ignores silences of 0.5 seconds in the middle (like pauses for # breaths). The second set removes everything but can make a rather rushed # result. See http://digitalcardboard.com/blog/2009/08/25/the-sox-of-silence/ # for some advice. # TRUNCS=( "1 0.1 1% -1 0.5 1%" "1 0.1 1% -1 0.1 1%" ) if [[ $TRUNCATE -eq 0 ]]; then SILENCE= else if [[ $TRUNCATE -gt ${#TRUNCS[@]} ]]; then TRUNCATE=${#TRUNCS[@]} fi ((TRUNCATE--)) silence=${TRUNCS[$TRUNCATE]} SILENCE="silence ${silence}" fi if [[ $MIXDOWN == 0 ]]; then REMIX= else REMIX="remix -" fi # # Report some internals in debug mode # if [[ $DEBUG -eq 1 ]]; then echo "SPEEDUP = $SPEEDUP" echo "TRUNCATE = $TRUNCATE" echo "MIXDOWN = $MIXDOWN" echo "speed = ${speed:-0}" echo "silence = ${silence:-}" echo "TEMPO = $TEMPO" echo "SILENCE = $SILENCE" echo "REMIX = $REMIX" fi # # Is there anything to do? # if [[ -z $TEMPO && -z $SILENCE ]]; then echo "Nothing to do; exiting" exit 1 fi # # Divide up the path to the file # orig="$(realpath "$1")" odir="${orig%/*}" oname="${orig##*/}" oext="${oname##*.}" # # The name of the original file will be changed to this # new="${odir}/${oname%.$oext}_.${oext}" # # Report the name of the input file # echo "Processing $orig" # # If the new name exists we already processed it # if [[ -e $new ]]; then echo "Oops! Looks like this file has already been sped up" exit 1 fi # # Rename the original file # if [[ $DRYRUN -eq 1 ]]; then printf "Dry run: rename %s to %s\n" "$orig" "$new" else mv "$orig" "$new" fi # # Speed up and remove long silences as requested # -S requests a progress display # -v2 adjusts the volume of the file that follows it on the command line by # a factor of 2 # -V9 requests a very high (debug) level of verbosity (default -V2) # remix - mixes all stereo to mono # #sox -S -v2 "${new}" "${orig}" -V9 ${TEMPO} remix - ${SILENCE} if [[ $DRYRUN -eq 1 ]]; then printf "Dry run: %s\n" \ "sox -S -v2 \"${new}\" \"${orig}\" ${TEMPO} ${REMIX} ${SILENCE}" else # [We want TEMP, REMIX and SILENCE to be word-split etc] # shellcheck disable=SC2086 sox -S -v2 "${new}" "${orig}" ${TEMPO} ${REMIX} ${SILENCE} fi # # Delete the original file if asked. Note that the script can't detect that # the audio has been sped up if this file is missing. # if [[ $CLEANUP -eq 1 ]]; then if [[ $DRYRUN -eq 1 ]]; then printf "Dry run: delete %s\n" "$new" else rm -f "$new" fi fi exit # vim: syntax=sh:ts=8:sw=4:ai:et:tw=78:fo=tcrqn21