Example Script using mythtranscode in fifodir mode

From MythTV Official Wiki
Jump to: navigation, search

The script pipes the output of mythtranscode into ffmpeg, using libx264 to compress the video. The intended use is to set it up as a myth user job. the --passthrough option can currently be used only on 0.25.

#!/bin/bash

exec >/var/log/mythtv/mythar`date +%F-%T`.log 2>&1

usage()
{
echo "Usage: $0 --chanid <channel id> --starttime <start time> --title <title> [--subtitle <sub title>] --outdir <directory> [options]";
echo "       $0 --chanid <channel id> --starttime <start time> -outfile <path> [options]";
echo "";
echo "       --chanid <channel id>                   The channel id for the recording. REQUIRED.";
echo "       --starttime <start time>                The start time for the recording. REQUIRED.";
echo "       --title <title>                         The title of the recording.";
echo "       --subtitle <subtitle>                   The subtitle of the recording.";
echo "       --outdir <path>                         The path of the directory for the output file. If one of";
echo "                                               --title --subtitle and --outdir are specified, then both --title and --outdir must";
echo "                                               be, and an output file will be chosen on their basis, avoiding";
echo "                                               conflict with existing files.";
echo "       --outfile <path>                        The exact path of the output file. ALTERNATIVE to";
echo "                                               --title --subtitle and --outdir.";
echo "       --vsize <width>x<height>                Scale video to specified resolution (the aspect ratio will";
echo "                                               be maintained using non-square pixels). If not specified,";
echo "                                               the source resolution will be maintained.";
echo "       --interlaced                            Assume the source is interlaced and maintain the interlace,";
echo "                                               provided --vsize not specified. If --vsize is specified then";
echo "                                               recode at double the frame rate.";
echo "       --passthrough                           Pass through the audio unaltered if possible.";
echo "       --quality <quality>                     Quality for compression (default 20.0)";
}

# Read arguments
unset CHANID
unset STARTTIME
unset TITLE
unset SUBTITLE
unset OUTDIR
unset OUTFILE
unset VSIZE
unset INTERLACED
unset PASSTHROUGH
unset QUALITY

ARGS=("$@")
I=0
while (( $I < $# )); do
{
    case ${ARGS[I]} in
        --chanid)      CHANID=${ARGS[I+1]};      I=$((I+2));;
        --starttime)   STARTTIME=${ARGS[I+1]};   I=$((I+2));;
        --title)       TITLE=${ARGS[I+1]};       I=$((I+2));;
        --subtitle)    SUBTITLE=${ARGS[I+1]};    I=$((I+2));;
        --outdir)      OUTDIR=${ARGS[I+1]};      I=$((I+2));;
        --outfile)     OUTFILE=${ARGS[I+1]};     I=$((I+2));;
        --vsize)       VSIZE=${ARGS[I+1]};       I=$((I+2));;
        --interlaced)  INTERLACED=1;             I=$((I+1));;
        --passthrough) PASSTHROUGH=1;            I=$((I+1));;
        --quality)     QUALITY=${ARGS[I+1]};     I=$((I+2));;
        *)             echo "Illegal option ${ARGS[I]}"; usage; exit 1;;
    esac
} done

# Check arguments make sense
if [[ ! -n $CHANID || ! -n $STARTTIME ]]; then
{
    echo "--chanid and --starttime required"
    usage
    exit 1
} fi

if [[ ! -n $OUTFILE && ! -n $OUTDIR ]]; then
{
    echo "Use either --outfile, or both --title --outdir, with optionally --subtitle"
    usage
    exit 1
} fi

if [[ -n $OUTFILE && ( -n $TITLE || -n $SUBTITLE || -n $OUTDIR) ]]; then
{
    echo "Use either --outfile, or both --title --outdir, with optionally --subtitle"
    usage
    exit 1
} fi

if [[ ( -n $TITLE || -n $OUTDIR || -n $SUBTITLE) && ( ! -n $OUTDIR || ! -n $TITLE ) ]]; then
{
    echo "Both --title and --outdir required for this mode of oparation"
    usage
    exit 1
} fi

if [[ -n $PASSTHROUGH ]]; then
{
    MYTHPASSTHROUGH="--passthrough"
}
else
{
    MYTHPASSTHROUGH=""
} fi

#Detect source formats
INFO=`mythtranscode -v general --chanid $CHANID --starttime $STARTTIME --fifoinfo $MYTHPASSTHROUGH`
echo $INFO
OLDIFS=$IFS
IFS=$'\n'
LINES=( $INFO )
IFS=$OLDIFS

unset SVWIDTH
unset SVHEIGHT
unset SVASPECT
unset SVRATE
unset SAFMT
unset SACHANS
unset SARATE

for LINE in "${LINES[@]}" ; do
{
    case $LINE in
        *FifoVideoWidth*)         SVWIDTH=${LINE#*FifoVideoWidth };;
        *FifoVideoHeight*)        SVHEIGHT=${LINE#*FifoVideoHeight };;
        *FifoVideoAspectRatio*)   SVASPECT=${LINE#*FifoVideoAspectRatio };;
        *FifoVideoFrameRate*)     SVRATE=${LINE#*FifoVideoFrameRate };;
        *FifoAudioFormat*)        SAFMT=${LINE#*FifoAudioFormat };;
        *FifoAudioChannels*)      SACHANS=${LINE#*FifoAudioChannels };;
        *FifoAudioHz*)            SARATE=${LINE#*FifoAudioHz };;
        *FifoAudioSampleRate*)    SARATE=${LINE#*FifoAudioSampleRate };;
    esac
} done

if [[ ! -n $SVWIDTH || ! -n $SVHEIGHT || ! -n $SVASPECT || ! -n $SVRATE || ! -n $SAFMT || ! -n $SACHANS || ! -n $SARATE ]]; then
{
    echo "Failed to derive fifo formats"
    exit 1
} fi

SVSIZE=${SVWIDTH}x${SVHEIGHT}
if [[ $SVASPECT == 1.77778 ]]; then
{
    SVASPECT=16:9
}
elif [[ $SVASPECT == 1.33333 ]]; then
{
    SVASPECT=4:3
} fi
	
# Set up default values to unset variables
QUALITY=${QUALITY:-"20.0"}


if [[ $SAFMT == aac_latm ]]; then
{
    SAFMT=latm;
} fi


EXT=".mp4"
FFMT="mp4"

if [[ $SAFMT == latm ]]; then
{
    EXT=".mkv"
    FFMT="matroska"
} fi

# If --outfile not specified, use --outdir --title and --subtitle
if [[ ! -n $OUTFILE ]]; then
{
    OBNAME="$OUTDIR/$TITLE"
    if [[ "$SUBTITLE" != "" ]]; then OBNAME+=" - $SUBTITLE"; fi

    I=1
    OUTFILE="$OBNAME$EXT"
    while [[ -a "$OUTFILE" ]]; do
    {
        I=$((I+1))
        OUTFILE="$OBNAME($I)$EXT"
    } done
} fi

# Can do pass through only with formats that ffmpeg will take as input
if [[ $SAFMT != ac3 && $SAFMT != dts && $SAFMT != mp3 && $SAFMT != latm ]]; then
{
    unset PASSTHROUGH
} fi

# Tell ffmpeg what audio to expect and what to do with it
if [[ -n $PASSTHROUGH ]]; then
{
    MYTHPASSTHROUGH="--passthrough"
    AUDINDESC="-f $SAFMT"
    AUDCODEC="copy"
}
else
{
    MYTHPASSTHROUGH=""
    AUDINDESC="-f s16le -ac 2 -ar $SARATE"
    AUDCODEC="ac3 -ab 160k"
} fi

unset VSCALER
# If scaling use lanczos
if [[ -n $VSIZE ]]; then
{
    VSIZE=`echo $VSIZE | sed 's/x/:/'`
    # Lanczos seems to make the files bigger yet less sharp
    #VSCALER="-sws_flags lanczos"
} fi

unset VFILTER
unset VFLAGS
unset VRATE
if [[ -n $INTERLACED ]]; then
{
    if [[ -n $VSIZE ]]; then
    {
        # If scaling interlaced video, we must deinterlace first
        VFILTER="yadif=3,scale=$VSIZE"
        VRATE="-r `echo 2*$SVRATE | bc`"
    }
    else
    {
        # Otherwise maintain the interlace
        VFILTER=
        VFLAGS="-flags +ilme+ildct"
    } fi
}
else
{
    if [[ -n $VSIZE ]]; then
    {
        VFILTER="scale=$VSIZE"
    } fi
} fi

if [[ $SVHEIGHT == 1088 ]]; then
{
    if [[ -n $VFILTER ]]; then
    {
        VFILTER="crop=$SVWIDTH:1080:0:0,$VFILTER"
    }
    else
    {
        VFILTER="crop=$SVWIDTH:1080:0:0"
    } fi

} fi

if [[ -n $VFILTER ]]; then
{
    VFILTER="-vf $VFILTER"
} fi

# Create fifo dir
FIFODIR=/tmp/mythar$$
/bin/mkdir $FIFODIR
trap "rm -r $FIFODIR" EXIT

# Start mythtranscode outputting into the pipes
echo /usr/bin/mythtranscode --chanid $CHANID --starttime $STARTTIME --honorcutlist $MYTHPASSTHROUGH --fifodir $FIFODIR --cleancut &
/usr/bin/mythtranscode --chanid $CHANID --starttime $STARTTIME --honorcutlist $MYTHPASSTHROUGH --fifodir $FIFODIR --cleancut &

# Ensure we kill the background task at the end of the run
BACKGROUND=$!
trap "kill -9 $BACKGROUND" EXIT

# Wait for the background task to create the pipes
while [[ ! -e "$FIFODIR/audout" || ! -e "$FIFODIR/vidout" ]]; do /bin/sleep 1; done

echo /usr/bin/ffmpeg $AUDINDESC -i $FIFODIR/audout -f rawvideo -top 1 -pix_fmt yuv420p -s $SVSIZE -r $SVRATE -i $FIFODIR/vidout -threads 2 $VFILTER $VSCALER -vcodec libx264 -preset medium -profile high $VFLAGS -crf $QUALITY $VRATE -aspect $SVASPECT -acodec $AUDCODEC -ar $SARATE -f $FFMT "$OUTFILE"
/usr/bin/ffmpeg $AUDINDESC -i $FIFODIR/audout -f rawvideo -top 1 -pix_fmt yuv420p -s $SVSIZE -r $SVRATE -i $FIFODIR/vidout -threads 2 $VFILTER $VSCALER -vcodec libx264 -preset medium -profile high $VFLAGS -crf $QUALITY $VRATE -aspect $SVASPECT -acodec $AUDCODEC -ar $SARATE -f $FFMT "$OUTFILE"