UNIX/LINUX, FOSS, FFMPEG, SOX, MEDIA FFmpeg and SOX 15 Mar، 2022 محمد زینلی محمد زینلی common usage common usage ffmpeg -i input.mp4 -hide_banner # getting input file information ffmpeg -i input.webm -qscale 0 output.mp4 # convert video preserving the quality of source video file ffmpeg -formats # list all supported formats ffmpeg -i input.mp4 -vn -ar 44100 -ac 2 -ab 320k -f mp3 output.mp3 # split audio vn: disable video. -ar audio frequency (common values 22050, 44100, 48000 Hz). -ac: number of audio channels. -ab: audio bitrate. -f: format. ffmpeg -i input.mp3 -af 'volume=0.5' output.mp3 # decrease volume by half (use numbers greater than 1 to increase volume) ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4 # increase/decrease(0.5 double, 2 half) the video playback speed ffmpeg -i input.mp4 -filter:a "atempo=2.0" -vn output.mp4 # Increase/decrease Audio playback speed (available value 0.5-2.0) ffmpeg -i input.mp4 -filter:v scale=1280:720 -c:a copy output.mp4 ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4 # set a particular resolution ffmpeg -i input.mp4 -vf scale=1280:-1 -c:v libx264 -preset veryslow -crf 24 -ac 2 -c:a aac -strict -2 -b:a 128k output.mp4 # reduce size and quality of output file ffmpeg -i input.mp3 -ab 128 output.mp3 # reduce audio bitrate (available bitrates: 96, 112, 128, 160, 192, 256, 320kbps) ffmpeg -i input.mp4 -an output.mp4 # remove audio ffmpeg -i input.mp4 -vn output.mp3 # remove video ffmpeg -i input.mp4 -r 1 -f image2 image-%2d.png # extract images -r: frame rate (image per second). -f: format. %2d name outputs image-01.png - image-99.png ffmpeg -i input.mp4 -filter:v "crop=w:h:x:y" output.mp4 # crop video ffmpeg -i input.mp4 -aspect 16:9 output.mp4 # set the aspect ratio (common ratios: 16:9, 4:3, 16:10, 5:4, 2:21:1, 2:35:1, 2:39:1) ffmpeg -loop 1 -i inputimage.jpg -i inputaudio.mp3 -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest output.mp4 # add poster image to audio ffmpeg -i input.mp4 -codec:v h264 -codec:a copy -ss 00:00:10.70 -t 01:10:52.26 output.mp4 # split a video from starting from 00:00:10.70 and end in 01:10:52.26 ffmeg -i vinput.mp4 -codec:v h264 -an -sn -dn -ss 00:05:00 -t 00:10:00 -i ainput.mp4 -codec:a mp3 -vn -ss 00:12:00 -t 00:17:00 output.mp4 # create output.mp4 using vinput.mp4 from 00:05:00 to 00:10:00 as video source and ainput.mp4 from 00:12:00 -t 00:17:00 as audio source ffmpeg -f concat -safe 0 -i <PATH-TO-LIST> -c copy ouput ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4 # concatinating the files in list fmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4 ffmpeg -i infile.mp4 -i infile.srt -c copy -c:s mov_text outfile.mp4 # add subtitle ffmpeg -i input.mp4 -vf "transpose=1" output.mp4 ffmpeg -i input.mp4 -vf "transpose=clock" output.mp4 # rotate the given video by 90 degrees clockwise. # 0. Rotate by 90 degrees counter-clockwise and flip vertically. This is the default. # 1. Rotate by 90 degrees clockwise. # 2. Rotate by 90 degrees counter-clockwise. # 3. Rotate by 90 degrees clockwise and flip vertically. metadata ffmpeg -i in.mp4 -f ffmetadata in.txt # Save the global metadata to a text file ffmpeg -i in.mp4 -c copy -map_metadata 0 -map_metadata:s:v 0:s:v -map_metadata:s:a 0:s:a -f ffmetadata in.txt # Save metadata from the video and audio streams ffprobe -show_streams -show_format input.mkv # Use ffprob for information ffprobe -show_frames input.mkv # Use ffprobe or information about each single frame in a video file ffmpeg -i source.mp4 -metadata album_artist='VAR' -c copy output.mp4 # Set metadata find /home/user/videos-to-process/ -type f -iname '*.mp4' -exec ffmpeg -i "{}" -codec copy -metadata artist="John Smith" -metadata album="Foo Bar" "{}.new.mp4" \; -exec mv "{}.new.mp4" "{}" \; # set metadata lbry preferred format ffmpeg -i input.avi -c:v libx264 -crf 21 -preset faster -pix_fmt yuv420p -maxrate 5000K -bufsize 5000K -vf 'scale=if(gte(iw\,ih)\,min(1920\,iw)\,-2):if(lt(iw\,ih)\,min(1920\,ih)\,-2)' -movflags +faststart -c:a aac -b:a 160k output.mp4 convert a PDF to video convert -density 400 input.pdf picture.png # convert PDF to picture-1.png, ... ffmpeg -r 1/10 -i picture-%01d.png -c:v libx264 -r 30 -pix_fmt yuv420p video.mp4 # -r 1/10: Display each image for 10 seconds. noise reduction using sox #!/usr/bin/env bash usage () { echo 'Usage : noiseclean.sh <input video file> <output video file>' exit } # Tests for requirements ffmpeg -version >/dev/null || { echo >&2 "We require 'ffmpeg' but it's not installed. Install it by 'sudo apt-get install ffmpeg' Aborting."; exit 1; } sox --version >/dev/null || { echo >&2 "We require 'sox' but it's not installed. Install it by 'sudo apt-get install sox' Aborting."; exit 1; } if [ "$#" -ne 2 ] then usage fi if [ ! -e "$1" ] then echo "File not found: '$1'" exit fi if [ -e "$2" ] then read -p "File '$2' already exists, overwrite? [y/N]: " yn case $yn in [Yy]* ) break;; * ) exit;; esac fi inBasename=$(basename "$1") inExt="${inBasename##*.}" isVideoStr=`ffprobe -v warning -show_streams "$1" | grep codec_type=video` if [[ ! -z $isVideoStr ]] then isVideo=1 echo "Detected '$inBasename' as a video file" else isVideo=0 echo "Detected '$inBasename' as an audio file" fi read -p "Sample noise start time [00:00:00]: " sampleStart if [[ -z $sampleStart ]] ; then sampleStart="00:00:00"; fi read -p "Sample noise end time [00:00:00.500]: " sampleEnd if [[ -z $sampleEnd ]] ; then sampleEnd="00:00:00.500"; fi read -p "Noise reduction amount [0.21]: " sensitivity if [[ -z $sensitivity ]] ; then sensitivity="0.21"; fi tmpVidFile="/tmp/noiseclean_tmpvid.$inExt" tmpAudFile="/tmp/noiseclean_tmpaud.wav" noiseAudFile="/tmp/noiseclean_noiseaud.wav" noiseProfFile="/tmp/noiseclean_noise.prof" tmpAudCleanFile="/tmp/noiseclean_tmpaud-clean.wav" echo "Cleaning noise on '$1'..." if [ $isVideo -eq "1" ]; then ffmpeg -v warning -y -i "$1" -qscale:v 0 -vcodec copy -an "$tmpVidFile" ffmpeg -v warning -y -i "$1" -qscale:a 0 "$tmpAudFile" else cp "$1" "$tmpAudFile" fi ffmpeg -v warning -y -i "$1" -vn -ss "$sampleStart" -t "$sampleEnd" "$noiseAudFile" sox "$noiseAudFile" -n noiseprof "$noiseProfFile" sox "$tmpAudFile" "$tmpAudCleanFile" noisered "$noiseProfFile" "$sensitivity" if [ $isVideo -eq "1" ]; then ffmpeg -v warning -y -i "$tmpAudCleanFile" -i "$tmpVidFile" -vcodec copy -qscale:v 0 -qscale:a 0 "$2" else cp "$tmpAudCleanFile" "$2" fi echo "Done" booksplit #!/bin/sh # Requires ffmpeg (audio splitting) and my `tag` wrapper script. [ ! -f "$2" ] && printf "The first file should be the audio, the second should be the timecodes.\ " && exit echo "Enter the album/book title:"; read -r booktitle echo "Enter the artist/author:"; read -r author echo "Enter the publication year:"; read -r year inputaudio="$1" # Get a safe file name from the book. escbook="$(echo "$booktitle" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")" ! mkdir -p "$escbook" && echo "Do you have write access in this directory?" && exit 1 # As long as the extension is in the tag script, it'll work. ext="opus" #ext="${1#*.}" # Get the total number of tracks from the number of lines. total="$(wc -l < "$2")" while read -r x; do end="$(echo "$x" | cut -d' ' -f1)" [ -n "$start" ] && echo "From $start to $end; $track $title" file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext" [ -n "$start" ] && echo "Splitting \"$title\"..." && ffmpeg -nostdin -y -loglevel -8 -i "$inputaudio" -ss "$start" -to "$end" -vn -c copy "$file" && echo "Tagging \"$title\"..." && tag -a "$author" -A "$booktitle" -t "$title" -n "$track" -N "$total" -d "$year" "$file" title="$(echo "$x" | cut -d' ' -f 2-)" esctitle="$(echo "$title" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")" track="$((track+1))" start="$end" done < "$2" # The last track must be done outside the loop. echo "From $start to the end: $title" file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext" echo "Splitting \"$title\"..." && ffmpeg -nostdin -y -loglevel -8 -i "$inputaudio" -ss "$start" -vn -c copy "$file" && echo "Tagging \"$title\"..." && tag -a "$author" -A "$booktitle" -t "$title" -n "$track" -N "$total" -d "$year" "$file" tag script #!/bin/sh err() { echo "Usage: tag [OPTIONS] file Options: -a: artist/author -t: song/chapter title -A: album/book title -n: track/chapter number -N: total number of tracks/chapters -d: year of publication -g: genre -c: comment You will be prompted for title, artist, album and track if not given." && exit 1 ;} while getopts "a:t:A:n:N:d:g:c:f:" o; do case "${o}" in a) artist="${OPTARG}" ;; t) title="${OPTARG}" ;; A) album="${OPTARG}" ;; n) track="${OPTARG}" ;; N) total="${OPTARG}" ;; d) date="${OPTARG}" ;; g) genre="${OPTARG}" ;; c) comment="${OPTARG}" ;; f) file="${OPTARG}" ;; *) printf "Invalid option: -%s\ " "$OPTARG" && err ;; esac done shift $((OPTIND - 1)) file="$1" [ ! -f "$file" ] && echo "Provide file to tag." && err [ -z "$title" ] && echo "Enter a title." && read -r title [ -z "$artist" ] && echo "Enter an artist." && read -r artist [ -z "$album" ] && echo "Enter an album." && read -r album [ -z "$track" ] && echo "Enter a track number." && read -r track case "$file" in *.ogg) echo "Title=$title Artist=$artist Album=$album Track=$track Total=$total Date=$date Genre=$genre Comment=$comment" | vorbiscomment -w "$file" ;; *.opus) echo "Title=$title Artist=$artist Album=$album Track=$track Total=$total Date=$date Genre=$genre Comment=$comment" | opustags -i -S "$file" ;; *.mp3) eyeD3 -Q --remove-all -a "$artist" -A "$album" -t "$title" -n "$track" -N "$total" -Y "$date" "$file" ;; *) echo "File type not implemented yet." ;; esac use booksplit path/to/audio path/to/timecodefile timecodefile: 00:00:00 first part name hh:mm:ss second part name ... filters frozen frames with mpdecimate ffmpeg -i input.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB -an output.mkv # remove frozen frames ffmpeg -hide_banner -nostats -an -i $IN -vf "freezedetect=n=${NOISE}dB:d=${DURATION}" -f null - 2>&1 | grep -e "freeze_start" -e "freeze_end" # detect frozen frames video stabliser vidstabs ffmpeg -i input.mp4 -vf vidstabdetect -f null - # Use default values ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10:accuracy=15:result="mytransforms.trf" -f null - # Analyzing strongly shaky video and putting the results in file mytransforms.trf ffmpeg -i input.mp4 -vf vidstabdetect=show=1 dummy_output.mp4 # Visualizing the result of internal transformations in the resulting video ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=5:show=1 dummy_output.mp4 # Analyzing a video with medium shakiness ffmpeg -i input.mp4 -vf vidstabtransform,unsharp=5:5:0.8:3:3:0.4 out_stabilized.mp4 # Using default values ffmpeg -i input.mp4 -vf vidstabtransform=zoom=5:input="mytransforms.trf" out_stabilized.mp4 # Zooming-in a bit more and load transform data from a given file ffmpeg -i input.mp4 -vf vidstabtransform=smoothing=30:input="mytransforms.trf" out_stabilized.mp4 # Smoothening the video even more