Marc's Public Blog - Linux Hacking


vvv Click on the categories below to see other topic specific pages vvv



>>> Back to post index <<<

π 2024-11-17 01:01 in Linux
This is a script I've had for over 20 years to recompress videos to multiple formats, including resizing resolution, rotating files, changing framerate, capturing from PAL analog cards, back in the day capturing videos from an analog tivo (circa 20 years ago), and much more.
While some amount is kind of obsolete and left for posterity, it's full of options that took me a long time to find for mencoder, and now ffmpeg, the better solution.

The script: https://marc.merlins.org/linux/scripts/vidcomp

There isn't a lot of documentation, except the script itself. Please get the version from the link above, but for indexing purposes, I'll include a potentially slightly out of date version here:

#!/bin/bash # don't use h265 due to lack of decoders in some devices due to license? # # https://trac.ffmpeg.org/wiki/Encode/AV1 # # vp9 vs av1 comparison and flags: # https://jonathanmh.com/p/encoding-webm-videos-with-ffmpeg-vp9-av1
# # Gemini says: Compression Efficiency # * AV1: Offers the best compression efficiency, resulting in smaller file sizes for a given quality level # * H.265: Provides significant improvements over H.264, offering better compression than VP9 in many cases # * VP9: While not as efficient as H.265 or AV1, it still offers decent compression and is widely supported. # # Encoding and Decoding Speed: # * AV1: Requires more computational power for encoding and decoding, which can impact performance on older hardware # * H.265: Offers a good balance between compression efficiency and encoding/decoding speed. # * VP9: Generally faster to encode and decode compared to AV1. # # x264 (H.264) Fastest # libvpx-vp9 ~5–10× slower than x264 # libaom-av1 ~20–50× slower than x264 (depending on settings) # # VP9 (libvpx-vp9): VP9 is a more modern and complex codec. It performs a much # more exhaustive analysis of the video to find better ways to compress it. This # allows it to achieve the same visual quality at a 20-50% smaller file size than # H.264, but this complex analysis requires significantly more CPU time.

# h4 9mn 91MB => join worked # h4ff 15mn 93MB => non matching but can read android h265 that mencoder cannot # vp9 45mn 102MB => join worked # av1 65mn 93MB => join worked # # 13390439 PXL_20250611_065327037.mp4 # 6336358 PXL_20250611_065327037.mp4.new << h4ff (required over h4 to read android h265) # 5871070 PXL_20250611_065327037.vp9.webm << vp9, 2x slower # 6514320 PXL_20250611_065327037.av1.webm << av1, 10x slower and BIGGER!

# vidcomp -h -time "-dvd-device . -alang English" dvd://1 /var/local/space/vid/10com8.avi

# http://gentoo-wiki.com/HOWTO_Mencoder_Introduction_Guide # http://electron.mit.edu/~gsteele/ffmpeg
# http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-enc-libavcodec.html # http://web.njit.edu/all_topics/Prog_Lang_Docs/html/mplayer/encoding.html # http://www.linux.com/article.pl?sid=06/08/22/2121258

# transcode -f 15 -w 800,250,100 -y divx5,lame -N 0x55 -o test.avi -i $1 # enable PAL on PVR350 mpeg2 encoder #v4l2-ctl --set-input 2 #v4l2-ctl -s 2 #v4l2-ctl --set-ctrl=video_peak_bitrate=8000000 #v4l2-ctl --set-ctrl=video_bitrate=6000000

# dumpstream stream# file.tivo dumpstream () { mplayer tivo://tivo/$1 -demuxer 33 -dumpstream -dumpfile "$2" }

die () { echo "${1:-}" exit 1 }

# vidcomp -br 10000 -time "-edl cuts" rec_0012.mov

#mplayer -vf cropdetect enquete.vob #vidcomp -h -vf crop=336:320:12:126 enquete.vob # Aspect ratio has to be forced with codecs other than xvid #vf='-vf scale=480:370' # vidcomp -vf "-filter:v fps=29" $i vf="" af="" # surprisingly h4ff causes output files with slightly non matching framerate # which then prevents merging them. but can read android h265 that # mencoder cannot codec=h264 #codec=h265 #br=3000

# AV1 is supposed to be better than VP9, but on my short tests, # VP9 was faster and gave smaller files. #codec=vp9 br=2000 abr=128 rot="" ffrot="" aud_channels="" aud_srate="" time="" # -ss 10 -endpos 1:54:00 (mencoder) # -time "-ss 0:3:40 -t 3:20" (ffmpeg) # or -time "-ss 0:3:40 -t 3:20" -vf "mp=eq2=0.9:1:-0.1" (ffmpeg) # vidcomp -br 8000 -time "-ss 04:00 -t 0:29:20" -vf "mp=eq2=0.9:1:-0.1" full.avi

# Crop the right side crop=1540:1080:0:0

if [ $0 = *tivo* ]]; then echo "Tivo Mode" # tivo files are sometimes mis-detected: force the right demuxer demux="-demuxer 33" # Aspect ratio has to be forced with codecs other than xvid aspect='-force-avi-aspect 1.333' # and remove crap we don't want (tivo inserts a line of crap at the top) vf="-vf crop=352:476,kerndeint" elif [ $0 = *pal* ]]; then # Couldn't quite get this to work yet, crop overrides it :( #vf='-vf scale=540:405,crop=512:384,kerndeint' vf='-vf scale=768:576,kerndeint' # problem with divx is that pass2 can fail with br too low errors codec=h264 br=800 # elif [ $0 = *camvidrecomp ]]; then # codec=ffmpeg # br=8000 # abr=128 # old cameras # abr=48 # br=2400 # aud_channels="-channels 1" # aud_srate="-srate 22050" fi # Hack for MTS demux="-mc 100" #demux="-demuxer lavf"

#aspect='-force-avi-aspect 1.777'

while [ ! -z "$1" ] && [ "$1" =~ ^-.* ]] do if [ "$1" = "-w" ]; then shift codec=win vf="-forceidx -vf kerndeint" fi

if [ "$1" = "-d" ]; then shift codec=divx #vf="-forceidx -vf kerndeint" fi

if [ "$1" = "-D" ]; then shift codec=divx1 vf="-forceidx -vf kerndeint" fi

if [ "$1" = "-F" ]; then shift codec=flv br=400 abr=56 aud_srate="-srate 22050" vf='-vf scale=512:384' fi

if [ "$1" = "-h" -o "$1" = "-h4" ]; then shift codec=h264 vf="-forceidx -vf kerndeint" fi

if [ "$1" = "-h4ff" ]; then shift codec=ffmpeg4 fi

if [ "$1" = "-h5" ]; then shift codec=h265 fi

if [ "$1" = "-vp9" ]; then shift codec=vp9 fi

if [ "$1" = "-av1" ]; then shift codec=av1 fi

if [ "$1" = "-x" ]; then shift codec=xvid vf="-forceidx -vf kerndeint" fi

if [ "$1" = "-ff" ]; then shift codec=ffmpeg fi

# https://trac.ffmpeg.org/wiki/Encode/H.264 # says not compatible with most players if [ "$1" = "-ffll" ]; then shift codec=ffmpegll fi

if [ "$1" = "-vol" ]; then shift vol=":vol=$1" shift fi

# try instead of rotate if [ "$1" = "-f" ]; then shift rot="-vf flip,mirror" #ffrot="-vf hflip,vflip" # https://www.baeldung.com/linux/ffmpeg-rotate-video#:~:text=transpose%20is%20an%20FFmpeg%20filter,the%20values%20from%200%2D3. ffrot="-vf hflip,vflip" ffrot="-vf transpose=1,transpose=3" fi

if [ "$1" = "-r" ]; then #rot="-vf mirror,rotate=$2" # works with -r 3 rot="-vf rotate=$2" ffrot="-vf transpose=$2" shift 2 fi

if [ "$1" = "-br" ]; then br="$2" shift 2 fi

# -ss 10 -endpos 1:54:00 # -ss 00:01:00 -to 00:02:00 if [ "$1" = -time ]; then time="$2" shift 2 fi

# for instance -vf scale=540:405,crop=512:384 if [ "$1" = -vf ]; then vf="$2" shift 2 fi done

test $# -eq 1 || test $# -eq 2 || die "$0 file_src file_dest (please read script for options)" test $# -eq 2 && test -f "$2" && die "file_dest should not exist"

src="$1" dest="${2:-$src.new}"

set -vx if [ "$codec" = win ]; then ionice -c3 nice -19 mencoder $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc lavc -lavcopts vcodec=msmpeg4v2:vhq:vbitrate=$br $rot -o "$dest" "$src" elif [ "$codec" = divx1 ]; then ionice -c3 nice -19 mencoder $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc lavc -lavcopts vcodec=mpeg4:vhq:trell=yes:v4mv=yes:vbitrate=$br -ffourcc DX50 $rot -o "$dest" "$src" elif [ "$codec" = flv ]; then # http://www.jeremychapman.info/cms/mencoder-avi-to-flv-conversion ionice -c3 nice -19 mencoder $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc lavc -lavcopts vcodec=flv:vbitrate=$br:mbd=2:mv0:trell:v4mv:cbp:last_pred=3 -of lavf $rot -o "$dest" "$src" elif [ "$codec" = xvid ]; then ionice -c3 nice -19 mencoder $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc xvid -xvidencopts bitrate=$br $rot -o "$dest" "$src" elif [ "$codec" = ffmpeg4 ]; then # aspect/-force-avi-aspect not supported by ffmpeg #ionice -c3 nice -19 ffmpeg $time -analyzeduration 9999999 -probesize 9999999 -y -i "$src" $vf -c:v libx264 -preset medium -b:v ${br}k -pass 1 -c:a libfdk_aac -b:a 128k -f mp4 /dev/null #ionice -c3 nice -19 ffmpeg $time -analyzeduration 9999999 -probesize 9999999 -i "$src" $vf -c:v libx264 -preset medium -b:v ${br}k -pass 2 -c:a libfdk_aac -b:a 128k -f mp4 "$dest" ionice -c3 nice -19 ffmpeg $time -analyzeduration 9999999 -probesize 9999999 -y -i "$src" -filter:v fps=30 $vf -c:v libx264 -preset medium -b:v ${br}k -pass 1 -an -f mp4 /dev/null ionice -c3 nice -19 ffmpeg $time -analyzeduration 9999999 -probesize 9999999 -i "$src" -filter:v fps=30 $vf -c:v libx264 -preset medium -b:v ${br}k -pass 2 -c:a aac -b:a 128k -f mp4 "$dest"

# slow and royalties so not implemented everywhere elif [ "$codec" = h265 ]; then # https://trac.ffmpeg.org/wiki/Encode/H.265 ionice -c3 nice -19 ffmpeg $time -y -i "$src" $vf $ffrot -filter:v fps=30 -c:v libx265 -b:v ${br}k -x265-params pass=1 -an -f mp4 /dev/null ionice -c3 nice -19 ffmpeg $time -i "$src" $vf $ffrot -filter:v fps=30 -c:v libx265 -b:v ${br}k -x265-params pass=2 -c:a aac -b:a 128k -f mp4 "$dest"

elif [ "$codec" = vp9 ]; then # cpu used lower values are slower but better quality -row-mt 1 added HT. Speed is faster than AV1 but compression seems still good # 2453715 file1.mp4 # 1555963 file1_av1_4.webm # 1611192 file1_av1_6.webm # 1611192 file1_av1_8.webm # 1668740 file1_vp9_4.webm # 1598794 file1_vp9_6.webm # 1595698 file1_vp9_8.webm # two pass seems broken on recent ffmpeg and hangs on first pass, not sure why. # actually it may work but just hang a long time on pass1 making it look like it's hung # ionice -c3 nice -19 ffmpeg $time -y -i "$src" -filter:v fps=30 -c:v libvpx-vp9 -b:v ${br}k $vf $ffrot -cpu-used 6 -row-mt 1 -pass 1 -an -f null /dev/null # ionice -c3 nice -19 ffmpeg $time -i "$src" -filter:v fps=30 -c:v libvpx-vp9 -b:v ${br}k $vf $ffrot -cpu-used 6 -row-mt 1 -pass 2 -c:a libopus -b:a 128k "$src.webm" #ionice -c3 nice -19 ffmpeg $time -y -i "$src" -filter:v fps=30 -c:v libvpx-vp9 -crf 31 -b:v ${br}k $vf $ffrot -cpu-used 6 -row-mt 1 -c:a libopus -b:a 128k "$src.webm"

# # cpu-used is quality set to lowest/fastest speed ionice -c3 nice -19 ffmpeg $time -y -i "$src" -filter:v fps=30 -c:v libvpx-vp9 -crf 31 -b:v ${br}k $vf $ffrot -cpu-used 6 -row-mt 1 -c:a libopus -b:a 128k -tile-columns 4 "$src.webm"

### AV1 a better version of VP9 but it's slower even than VP9 # https://caniuse.com/?search=av1 # https://trac.ffmpeg.org/wiki/Encode/AV1 # cpu used lower values are slower but better quality -row-mt 1 added HT elif [ "$codec" = av1 ]; then # two pass seems broken on recent ffmpeg and hangs on first pass, not sure why. # actually it may work but just hang a long time on pass1 making it look like it's hung ionice -c3 nice -19 ffmpeg $time -y -i "$src" $vf $ffrot -filter:v fps=30 -c:v libaom-av1 -b:v ${br}k -cpu-used 8 -row-mt 1 -pass 1 -an -f null /dev/null ionice -c3 nice -19 ffmpeg $time -i "$src" $vf $ffrot -filter:v fps=30 -c:v libaom-av1 -b:v ${br}k -cpu-used 8 -row-mt 1 -pass 2 -c:a libopus -b:a 128k "$src.webm"

# old legacy mencoder stuff (mencoder h264 or divx) else pass="$dest".pass for i in 1 2 do echo "DOING $codec PASS $i" echo "------------------" if [ "$codec" = h264 ]; then #vf=$vf,dsize=4/3,scale #vf=$vf,scale=720:480 vf=$vf,scale # why is scale there by itself? # Trellis searched quantization

# do not allow space in source, to allow a multi file source ionice -c3 nice -19 mencoder -passlogfile "$pass" $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc x264 -x264encopts bitrate=$br:turbo=1:pass=1:threads=0 $rot -o "$dest" $src || die "multipass failed on pass $i" elif [ "$codec" = divx ]; then # Trellis searched quantization ionice -c3 nice -19 mencoder -passlogfile "$pass" $demux $aud_channels $aud_srate -oac mp3lame -lameopts mode=3:abr:br=$abr$vol $time $aspect $vf -ovc lavc -lavcopts vcodec=mpeg4:vhq:trell=yes:v4mv=yes:vbitrate=$br:vpass=$i -ffourcc DX50 $rot -o "$dest" "$src" || die "multipass failed on pass $i" fi done /bin/rm "$pass" *.pass.mbtree &>/dev/null #else # echo "Unknown $codec" >&2 fi

#vidrename --noinfo "$dest"

/bin/rm ffmpeg2pass-0.log ffmpeg2pass-0.log.mbtree x265_2pass.log* &>/dev/null

Again, to up to date version is here: https://marc.merlins.org/linux/scripts/vidcomp


More pages: July 2002 February 2004 March 2004 November 2004 April 2005 August 2005 January 2006 July 2006 August 2007 November 2007 December 2007 January 2008 October 2008 November 2008 December 2008 January 2009 May 2009 July 2009 August 2009 September 2009 November 2009 December 2009 January 2010 March 2010 April 2010 June 2010 August 2010 October 2010 January 2011 July 2011 August 2011 December 2011 January 2012 March 2012 May 2012 August 2012 December 2012 January 2013 March 2013 May 2013 September 2013 November 2013 January 2014 March 2014 April 2014 May 2014 October 2014 January 2015 March 2015 May 2015 January 2016 February 2016 June 2016 July 2016 August 2016 October 2016 January 2017 September 2017 January 2018 March 2018 December 2018 January 2019 August 2019 January 2020 May 2020 January 2021 September 2021 March 2023 April 2023 December 2023 June 2024 September 2024 November 2024 July 2025 August 2025 October 2025 November 2025

>>> Back to post index <<<

Contact Email