Snippets

Peter Finlayson twitch mp4 download and reencode

Created by Peter Finlayson last modified
#!/bin/bash
# twitch_dl_reencode.sh
# 
# requires ffmpeg and fdkaac

VERSION="2.1.0"

# audio variable bitrate setting (1-5)
audio_vbr=3

# default h264 rate factor (22-28 recommended range)
video_crf=27

# h264 profile and preset
# https://trac.ffmpeg.org/wiki/Encode/H.264
video_profile="-profile:v high -level 4.2 -pix_fmt yuv420p"

video_preset="veryslow"
video_preset_short="vs"

# options and parameters
keep_orig=""

function usage {
    echo "$(basename "$0") v${VERSION} - Download and transcode a twitch video file to make much smaller."
    echo "If no output filename is provided, one will be generated automatically."
    echo "Examples:"
    echo "    $(basename "$0") <twitch URL> [output.mp4]" 
    echo "Options:"
    echo "    -h, --help         Print this help message and exit"
    echo "    -v, --version      Print this help message and exit"
    echo "    -k, --keep         Keep the original Twitch video file"
    echo "    --video-crf        h264 rate factor (quality, 22-28, default $video_crf)"
}

function parse_args {
    local arg
    
    while (( $# != 0)); do
	arg="$1"
	shift
	
	case "$arg" in
	-h|--help)
	    usage
	    exit 0
	    ;;
	-v|--version)
	    usage
	    exit 0
	    ;;
	-k|--keep)
	    keep_orig="true"
	    ;;
	--video-crf)
	    [[ -z "$1" ]] && echo "ERROR: --video-crf must specify a rate factor" && exit 1
	    video_crf="$1"
	    echo "Video h264 rate factor set to $video_crf"
	    shift
	    ;;
	*)
	    if [[ -z "$input" ]]; then
		input="$arg"
	    else
		output="$arg"
	    fi
	    ;;
	esac
    done
    
    [[ -z "$input" ]] && usage && exit 1
    
    if [[ -z "$output" ]]; then
	echo "Fetching video filename"
	input_filename=$(ydl -q --get-filename "$input")
	output="${input_filename%.*}-${video_preset_short}-crf${video_crf}-faacm${audio_vbr}.reenc.mp4"
    fi
}

# main
parse_args "$@"

temp_dir=$(mktemp --tmpdir -d twitch-XXXXXX)
temp_fifo="$temp_dir"/twitch.mp4

# do we keep the original file or send it to /dev/null?
if [[ -n "$keep_orig" ]]; then
    keep_message=" and keeping original file"
    if [[ -n "$input_filename" ]]; then
	keep_filename="$input_filename"
    else
	keep_filename="orig-$output"
    fi
else
    # bin the intermediate file
    keep_filename="/dev/null"
fi

# do the deed
echo "downloading '$input' via FIFO '$temp_fifo' and reencoding to '$output'$keep_message"

mkfifo "$temp_fifo"

ydl -q --console-title --no-part -o - "$input" | tee "$temp_fifo" | tee "$keep_filename" | ffmpeg -loglevel 24 -i - -vn -f caf - | fdkaac -S -m "$audio_vbr" - -f 2 -o - | nice -n 20 ffmpeg -i "$temp_fifo" -i - -c:v h264 ${video_profile} -movflags +faststart -crf "$video_crf" -preset "$video_preset" -c:a copy -map 0:v:0 -map 1:a:0 -y "$output"

rm "$temp_fifo"
rmdir "$temp_dir"

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.