Browse Source

Snapshot 0a563dd372

master
commit
5f963736c1
3 changed files with 334 additions and 0 deletions
  1. +1
    -0
      Licence note
  2. +92
    -0
      README.md
  3. +241
    -0
      ffmpeg_ein.sh

+ 1
- 0
Licence note View File

@ -0,0 +1 @@
If you find software that doesn’t have a license, that means you have no permission from the creators of the software to use, modify, or share the software. Although a code host such as GitHub may allow you to view and fork the code, this does not imply that you are permitted to use, modify, or share the software for any purpose.

+ 92
- 0
README.md View File

@ -0,0 +1,92 @@
# FFmpeg Encode If Needed
FFmpeg wrapper to encode upon some conditions.
## Installation
The script can be use "as is" with a command like `./ffmpeg_ein.sh` but
you could also "install" it with something like:
```bash
mv ffmpeg_ein.sh /usr/bin/ffmpeg_ein
```
## Usage
```bash
ffmpeg_ein [OPTION] [INPUT]
````
Refer to the `-h` argument to get the full list of options.
## Description
By default, FFmpeg encode a file regardless of the fact that the
original and selected codec are the same. Although it may be be a
desired outcome, it can lead to unnecessary operations losing time
and quality.
This script allow the user to specified a desired codec for audio
and video, only if either of those are not present an encoding will be
triggered.
For example if the desired codecs are aac/h264 and the source file is
wmav2/h264 then the file will be encoded with aac and the h264 stream
copied.
| Desired ( `-a aac` ) | Source | FFmpeg option |
|:--------------------:|:------:|:----------------:|
| aac | aac | `-c:a copy` |
| aac | X | content of `-b` |
**Warning**, by default no output is set, use the `-d` option or specify
the output file with `-o`.
### Batch friendly
This script is designed to be batch friendly allowing the sorting of
processed and sources files within multiple directories. The following
points also help in this endeavor:
+ INPUT can be multiple files and/or directories.
+ The output files will be automatically named with the `-d` option.
+ Errors generated by FFmepg are stored in a *[FILE].error.txt* file
alongside the outputted file.
+ Friendly statistics available if the verbose option is set to default
value.
## Example
```bash
ffmpeg_ein \
-a aac -b "-c:a aac -b:a 48k" \
-v h264 -u "-c:v libx264 -crf 23" \
-d /tmp/ \
[FILE]
```
Will result in the encoding of the file(s) [FILE] if either their audio
codec is not "aac" or their video codec is not "h264". The result
encoded file(s) (if created) will have the same name as the original(s)
and be placed in the "/tmp" folder.
| Desired | Source | FFmpeg option |
|:---------:|:---------:|:--------------------------------------:|
| aac/h264 | aac/h264 | -c:a copy -c:v copy |
| aac/h264 | X/h264 | -c:a aac -b:a 48k -c:v copy |
| aac/h264 | aac/X | -c:a copy -c:v libx264 -crf 23 |
| aac/h264 | X/X | -c:a aac -b:a 48k -c:v libx264 -crf 23 |
## Limitations / Future roadmap
+ Only the first audio and video streams are accounted for during codec
comparaison.
+ Only the codecs are checked so it's not possible to trigger encoding
on other parameters like bitrate or length.
+ The comparaison doesn't allow for multiple value (example compare
source against h264 and mpeg4)
+ No "-n, --dry-run" option exist to perform a trial run with no
changes made.
+ Some assumptions are made regarding the fact that the user will
provide valid input (valid FFmpeg arguments; read/write access to
specified files and folders; ...)

+ 241
- 0
ffmpeg_ein.sh View File

@ -0,0 +1,241 @@
#!/bin/bash
function displayHelp {
echo -e "Encode If Needed is a warper for FFmpeg to encode upon some conditions."
echo -e "USAGE: ein [OPTION] [INPUT]"
echo -e "DESCRIPTION:"
echo -e "By default, FFmpeg encode a file regardless of the fact that the"
echo -e "original and selected codec are the same. Although it may be be a"
echo -e "desired outcome, it can lead to unnecessary operations losing time"
echo -e "and quality."
echo -e "This script allow the user to specified a desired codec for audio"
echo -e "and video, only if either of those are not present an encoding will be"
echo -e "triggered."
echo -e "Example if the desired codecs are aac/h264 and the source file is wmav2"
echo -e "/h264 then the file will be encoded with aac and the h264 stream copied."
echo -e "Warning, by default no output is set, use the \"-d\" option or specify"
echo -e "the output file with \"-o\"."
echo -e "Errors generated by FFmpeg will be put in [INPUT].error.txt"
echo -e "[INPUT] can be one or multiple file(s) or directory(ies)."
echo -e "OPTION:"
echo -e "-a\tDesited audio codec like aac."
echo -e "-v\tDesited video codec like aac."
echo -e "-b\tArgument pass to FFmpeg if the audio codec specified by \"-a\""
echo -e "\tdon't match."
echo -e "-b\tArgument pass to FFmpeg if the video codec specified by \"-a\""
echo -e "\tdon't match."
echo -e "-d\tOptional output directory for the encoded file(s)."
echo -e "\tThe original filename will be used."
echo -e "\tMake sure the directory exist and that you have write access."
echo -e "-e\tUsed with \"-d\" to specified the container output file."
echo -e "\tBy default mkv will be used."
echo -e "-k\tOptional directory for original files kept \"as is\"."
echo -e "-f\tOptional directory for original files processed."
echo -e "-q\tReduce the verbosity."
echo -e "-h\tDisplay this help."
echo -e "EXAMPLE:"
echo -e "\t-a aac -b \"-c:a aac -b:a 48k\" \\"
echo -e "\t-v h264 -u \"-c:v libx264 -crf 23\" \\"
echo -e "\t-d /tmp/ \\"
echo -e "\t[FILE]"
echo -e "Will result in the encoding of the file(s) [FILE] if either their audio"
echo -e "codec is not \"aac\" or their video codec is not \"h264\". The result"
echo -e "encoded file(s) (if created) will have the same name as the original(s)"
echo -e "and be placed in the \"/tmp\" folder."
}
#"codec" will always matching thus allowing to specified only audio or video codec
audioCodecDesired="codec"
videoCodecDesired="codec"
audioParameter=""
videoParameter=""
outputDirectory=""
outputExtension="mkv"
goodAsIsDirectory=""
processedDirectory=""
optionalParameter=""
verbose=1
fileCount=0
errorCount=0
directoryCount=0
unencodedCount=0
no_args=1
while getopts a:v:b:u:d:e:o:k:f:qh option
do
case $option in
(a)
audioCodecDesired=$OPTARG;;
(v)
videoCodecDesired=$OPTARG;;
(b)
audioParameter=$OPTARG;;
(u)
videoParameter=$OPTARG;;
(d)
outputDirectory=$OPTARG;;
(e)
outputExtension=$OPTARG;;
(k)
goodAsIsDirectory=$OPTARG;;
(f)
processedDirectory=$OPTARG;;
(o)
optionalParameter=$OPTARG;;
(q)
verbose=0;;
(h)
(*)
displayHelp
exit;;
esac
no_args=0
done
shift $((OPTIND -1))
function processFile {
basename=$(basename "$@")
verbose $basename
errorFile="$basename.error.txt"
#Retrieve audio and video codec for the first stream of each
aCodec=$(ffprobe -select_streams a:0 -show_entries stream=codec_name -i "$@" -v error|head -n 2|tail -n 1)
vCodec=$(ffprobe -select_streams v:0 -show_entries stream=codec_name -i "$@" -v error|head -n 2|tail -n 1)
prefix="codec_name="
verboseAudio=$(echo -e "\t"$aCodec | sed -e "s/$prefix/Audio /")
verboseVideo=$(echo -e "\t"$vCodec | sed -e "s/$prefix/Video /")
encode=0
ffmpegCmd=""
if echo $aCodec|grep --quiet $audioCodecDesired; then
ffmpegCmd=$ffmpegCmd" -c:a copy"
verboseAudio=$verboseAudio" -> copy"
else
ffmpegCmd=$ffmpegCmd" "$audioParameter
encode=1
verboseAudio=$verboseAudio" -> "$audioCodecDesired
fi
if echo $vCodec|grep --quiet $videoCodecDesired; then
ffmpegCmd=$ffmpegCmd" -c:v copy"
verboseVideo=$verboseVideo" -> copy"
else
ffmpegCmd=$ffmpegCmd" "$videoParameter
encode=1
verboseVideo=$verboseVideo" -> "$videoCodecDesired
fi
verbose "$verboseAudio"
verbose "$verboseVideo"
if [[ $encode == 1 ]]; then
#Add optional arguments passed by user
if [ ! -z "$optionalParameter" ]; then
ffmpegCmd="$ffmpegCmd $optionalParameter"
fi
#Add directory "-d" if selected
if [ ! -z "$outputDirectory" ]; then
ffmpegCmd="$ffmpegCmd $outputDirectory/${basename%.*}.$outputExtension"
fi
verbose "\tffmpeg arguments:"$ffmpegCmd
FFREPORT=file="$errorFile":level=24
ffmpeg -hide_banner -i "$@" $(echo "$ffmpegCmd")
if [ -f "$errorFile" ]; then
errorCount=$((errorCount+1))
fi
# 2> "$basename".error.txt
if [ ! -z "$processedDirectory" ]; then
mv "$@" "$processedDirectory/" -v
if [ -f "$errorFile" ]; then
mv "$errorFile" "$processedDirectory/" -v
fi
fi
else
verbose "\tKeep original source."
unencodedCount=$((unencodedCount+1))
if [ ! -z "$goodAsIsDirectory" ]; then
mv "$@" "$goodAsIsDirectory/" -v
fi
fi
}
#Process user input that could be a file, a directory or anything really.
function processInput {
verbose "Input \"$@\""
if [ -d "$@" ]; then
directoryCount=$((directoryCount+1))
for inputInDir in "$@"/*; do
processInput "$inputInDir"
done
fi
if [ -f "$@" ]; then
fileCount=$((fileCount+1))
processFile "$@"
fi
}
function verbose {
if [[ $verbose == 1 ]]; then
echo -e "$@"
fi
}
if [[ $no_args == 1 ]]; then
displayHelp
else
verbose "Configuration:"
verbose "\tAudio codec desired="$audioCodecDesired
verbose "\tVideo codec desired="$videoCodecDesired
verbose "\tAudio parameter="$audioParameter
verbose "\tVideo parameter="$videoParameter
verbose "\tOptional parameter="$optionalParameter
verbose "\tDirectory encoded file="$outputDirectory
verbose "\tEncoded file extension="$outputExtension
verbose "\tDirectory processed file="$processedDirectory
verbose "\tDirectory unmodified file="$goodAsIsDirectory
verbose "Number of inputs "$#
if
([ $audioCodecDesired = "codec" ] && [ $videoCodecDesired = "codec" ]) ||
([ -z "$audioParameter" ] && [ -z "$videoParameter" ])
then
echo "At least one codec must be choosed."
exit
fi
for input in "$@"; do
processInput "$input"
done
#Display statistics
message="Processed "$fileCount" file"
if [ $fileCount -gt 1 ]; then
message=$message"s"
fi
if [ $directoryCount -gt 0 ]; then
message=$message" in $directoryCount director"
if [ $directoryCount -gt 1 ]; then
message=$message"ies."
else
message=$message"y."
fi
fi
encodedCount=$((fileCount-unencodedCount))
if [ $encodedCount -gt 0 ]; then
message=$message"\n"$encodedCount" encoded."
fi
if [ $unencodedCount -gt 0 ]; then
message=$message"\n"$unencodedCount" kept \"as is\"."
fi
if [ $errorCount -gt 0 ]; then
message=$message"\n"$errorCount" error"
if [ $fileCount -gt 1 ]; then
message=$message"s"
fi
message=$message" reported by FFmpeg."
fi
verbose $message
fi

Loading…
Cancel
Save