Difference between revisions of "Length Script"

From MythTV Official Wiki
Jump to: navigation, search
Line 1: Line 1:
 
This script will generate accurate lengths for all movies in your MythVideo directory.  Even with IMDB, many movies come back with lengths of zero minutes.  Personally, I also have many television episodes archived in MythVideo.  In an attempt to make my metadata more accurate, I wrote this script.
 
This script will generate accurate lengths for all movies in your MythVideo directory.  Even with IMDB, many movies come back with lengths of zero minutes.  Personally, I also have many television episodes archived in MythVideo.  In an attempt to make my metadata more accurate, I wrote this script.
  
''Thanks to siXy in #mythtv-users for helping me simplify this script.''
+
''Thanks to siXy and Marcus Brown (mzb) in #mythtv-users for helping me simplify this script.''
  
 
<pre>
 
<pre>
 +
 
#!/bin/bash
 
#!/bin/bash
 
#
 
#
Line 19: Line 20:
 
#  all relatively standard, this should be unnecessary.
 
#  all relatively standard, this should be unnecessary.
 
#
 
#
Define the next four items.
+
Originally written by Robert McNamara (robert.mcnamara ATSIGN gmail.com)
 +
#  Contributions and code improvment by Marcus Brown
 +
#
 +
 
  
# MythTV MySQL Database NameDefault is "mythconverg."
+
###  Define the next five items###
DBNAME=mythconverg
 
  
# Hostname or IP Address of MySQL Server.
+
# Myth Database Name
DBHOST=localhost
+
DBNAME=$1
  
# MySQL user name
+
# Myth DB User
DBUSER=root
+
DBUSER=$2
  
# MySQL Password
+
# Myth DB Password
DBPASSWORD=soulfire
+
DBPASSWORD=$3
  
 
# Where do your movies live? (Root MythVideo Directory)
 
# Where do your movies live? (Root MythVideo Directory)
MOVIEHOME=/movies
+
MOVIEHOME=$4
 +
 
 +
# Most people have their mysql server on their localhost
 +
SQLSERVER=$5
 +
 
 +
 
 +
### Change nothing below this point.  ###
 +
 
 +
DEBUG=9
  
 +
## Define our SQL Commands
 +
SQL_DETAILS="-u$DBUSER -h$SQLSERVER -p$DBPASSWORD $DBNAME"
 +
ZERO_LENGTH="SELECT filename FROM videometadata WHERE length = 0 AND filename LIKE \"$MOVIEHOME%\""
 +
UPDATE_LENGTH='UPDATE videometadata SET length = \"$LENGTH\" WHERE filename = \"$videofile\" LIMIT 1'
  
 
##  End of definitions
 
##  End of definitions
  
until [ "$count" = "0" ]
+
trap 'forcequit' INT KILL TERM
do
+
 
 +
dprint () {
 +
  level=$1
 +
  if [ $level -le $DEBUG ]
 +
    then
 +
      shift
 +
      while [ $level -gt 0 ]
 +
        do
 +
          echo -n " " >&2
 +
          let "level--"
 +
        done
 +
      echo -e "$*" >&2
 +
  fi
 +
}
 +
 
 +
cleanup () {
 +
  [ -x "$filefifo" ] && exec 6<&-
 +
  [ -f "$filefifo" ] && rm -f "$filefifo"
 +
  exit 1
 +
}
 +
 
 +
forcequit () {
 +
  dprint -1 "Forced quit ... cleaning up."
 +
  cleanup
 +
  exit 1
 +
}
 +
 
 +
#########################
 +
#
 +
#  Main
 +
#
 +
 
 +
 
 +
# Generate file list
 +
 
 +
filefifo="$(mktemp)"
 +
rm -f "$filefifo"
 +
mkfifo "$filefifo"
 +
exec 6<> "$filefifo"
 +
mysql $SQL_DETAILS -e "$ZERO_LENGTH;" | grep -v ^filename$ >&6
 +
echo "EOF" >&6
  
##find out how many movies to process
+
# Loop through videos
echo "USE $DBNAME; SELECT filename FROM \`videometadata\` WHERE \`length\` = 0;"  > lengthlist.sql
 
  
mysql -h $DBHOST -u$DBUSER -p$DBPASSWORD < lengthlist.sql > sqllist.out
+
while read -u6 videofile && [ "$videofile" != "EOF" ]
ed -s sqllist.out <<< $'1d\nw'
+
  do
count=`wc -l sqllist.out | awk '{print $1}'`
+
    if [ -n "$videofile" ]
 +
      then
 +
        dprint 2 "Processing: \"$videofile\""
  
 +
        # Calculate length of video
  
##get a  movie to process
+
        TOTAL_SECONDS="$(
echo "USE mythconverg
+
            mplayer -vo null -ao null -frames 0 -identify "$videofile" 2>/dev/null |
SELECT filename FROM \`videometadata\` WHERE \`length\` = 0 LIMIT 1;
+
              grep "^ID_LENGTH" | sed -e 's%ID_LENGTH=%%'
SELECT title FROM \`videometadata\` WHERE \`length\` = 0 LIMIT 1;" > lengthfind.sql
+
          )"
 +
        TOTAL_SECONDS="${TOTAL_SECONDS:-0}"
 +
        dprint 5 "Length: $TOTAL_SECONDS secs"
  
mysql -h $DBHOST -u$DBUSER -p$DBPASSWORD < lengthfind.sql > sql.out
+
        # convert to minutes (round off to nearest minute)
MOVIE="`cat sql.out | grep -v title | grep -v filename | grep $MOVIEHOME`"
 
MOVIEID="`cat sql.out | grep -v filename | grep -v title | grep -v $MOVIEHOME`"
 
  
##Calculate the length
+
        #LENGTH="$(perl -e "print eval(join(' ',@ARGV)).qq{};" "$TOTAL_SECONDS/60" | awk '{print int($1+0.5)}')"
TOTALSECONDS=`mplayer -vo null -ao null -frames 0 -identify "$MOVIE" 2>/dev/null | grep "ID_LENGTH" | sed -e 's/ID_LENGTH=//' | awk '{print int($1+0.5)}'`
+
        LENGTH="$[ ( (${TOTAL_SECONDS%.*} * 100) + 3000 ) / 6000 ]"
LENGTHCALC=`expr $TOTALSECONDS "/" 60`
+
        dprint 4 "Length: $LENGTH mins"
LENGTH=`echo $LENGTHCALC | awk '{print int($1+0.5)}'`
 
echo "USE $DBNAME
 
  
SELECT @var_MOVIEID:=\`title\` FROM \`videometadata\` WHERE \`length\` = 0 LIMIT 1;
+
        # Update database
SELECT @var_MOVIEID;
 
  
UPDATE \`videometadata\` SET \`length\` = $LENGTH WHERE \`title\` = @var_MOVIEID LIMIT 1 ;" > lengthupdate.sql
+
        if [ $LENGTH -gt 0 ]
 +
          then
 +
            dprint 7 "$(eval echo "mysql $SQL_DETAILS -e \'$UPDATE_LENGTH\;\'")"
 +
            if eval "mysql $SQL_DETAILS -e \"$UPDATE_LENGTH;\""
 +
              then
 +
                dprint 3 "Database updated"
 +
              else
 +
                dprint -1 "Error updating database! Exiting"
 +
                cleanup
 +
                exit 1
 +
              fi
 +
          else
 +
            dprint 6 "Unable to calculate length of video."
 +
          fi
 +
      fi
 +
  done
  
  ##update the database
+
cleanup
mysql -h $DBHOST -u$DBUSER -p$DBPASSWORD < lengthupdate.sql
 
  
done
+
exit 0
 
</pre>
 
</pre>

Revision as of 23:49, 2 January 2008

This script will generate accurate lengths for all movies in your MythVideo directory. Even with IMDB, many movies come back with lengths of zero minutes. Personally, I also have many television episodes archived in MythVideo. In an attempt to make my metadata more accurate, I wrote this script.

Thanks to siXy and Marcus Brown (mzb) in #mythtv-users for helping me simplify this script.


#!/bin/bash
#
#  Script to automate setting of video lengths in mythtv.
#
#  Searches for all MythVideo files with length of "0."
#  Generates a list, and pipes each file through an
#  mplayer -identify "filename."  Inserts each length
#  back into the database.  This script needs slight
#  babysitting as, if mplayer cannot play the file
#  properly, it will go into a loop.  In my MythVideo
#  of ~500 files, I had to set lengths four times to
#  get the script to complete.  These files were all
#  .m2ts files from Blu-Ray discs.  If your files are
#  all relatively standard, this should be unnecessary.
#
#  Originally written by Robert McNamara (robert.mcnamara ATSIGN gmail.com)
#  Contributions and code improvment by Marcus Brown
#


###  Define the next five items.  ###

# Myth Database Name
DBNAME=$1

# Myth DB User
DBUSER=$2

# Myth DB Password
DBPASSWORD=$3

# Where do your movies live? (Root MythVideo Directory)
MOVIEHOME=$4

# Most people have their mysql server on their localhost
SQLSERVER=$5


### Change nothing below this point.  ###

DEBUG=9

## Define our SQL Commands
SQL_DETAILS="-u$DBUSER -h$SQLSERVER -p$DBPASSWORD $DBNAME"
ZERO_LENGTH="SELECT filename FROM videometadata WHERE length = 0 AND filename LIKE \"$MOVIEHOME%\""
UPDATE_LENGTH='UPDATE videometadata SET length = \"$LENGTH\" WHERE filename = \"$videofile\" LIMIT 1'

##  End of definitions

trap 'forcequit' INT KILL TERM

dprint () {
  level=$1
  if [ $level -le $DEBUG ]
    then
      shift
      while [ $level -gt 0 ]
        do
          echo -n " " >&2
          let "level--"
        done
      echo -e "$*" >&2
  fi
}

cleanup () {
  [ -x "$filefifo" ] && exec 6<&-
  [ -f "$filefifo" ] && rm -f "$filefifo"
  exit 1
}

forcequit () {
  dprint -1 "Forced quit ... cleaning up."
  cleanup
  exit 1
}

#########################
#
#  Main
#


# Generate file list

filefifo="$(mktemp)"
rm -f "$filefifo"
mkfifo "$filefifo"
exec 6<> "$filefifo"
mysql $SQL_DETAILS -e "$ZERO_LENGTH;" | grep -v ^filename$ >&6
echo "EOF" >&6

# Loop through videos

while read -u6 videofile && [ "$videofile" != "EOF" ]
  do
    if [ -n "$videofile" ]
      then
        dprint 2 "Processing: \"$videofile\""

        # Calculate length of video

        TOTAL_SECONDS="$(
            mplayer -vo null -ao null -frames 0 -identify "$videofile" 2>/dev/null |
              grep "^ID_LENGTH" | sed -e 's%ID_LENGTH=%%'
          )"
        TOTAL_SECONDS="${TOTAL_SECONDS:-0}"
        dprint 5 "Length: $TOTAL_SECONDS secs"

        # convert to minutes (round off to nearest minute)

        #LENGTH="$(perl -e "print eval(join(' ',@ARGV)).qq{};" "$TOTAL_SECONDS/60" | awk '{print int($1+0.5)}')"
        LENGTH="$[ ( (${TOTAL_SECONDS%.*} * 100) + 3000 ) / 6000 ]"
        dprint 4 "Length: $LENGTH mins"

        # Update database

        if [ $LENGTH -gt 0 ]
          then
            dprint 7 "$(eval echo "mysql $SQL_DETAILS -e \'$UPDATE_LENGTH\;\'")"
            if eval "mysql $SQL_DETAILS -e \"$UPDATE_LENGTH;\""
              then
                dprint 3 "Database updated"
              else
                dprint -1 "Error updating database! Exiting"
                cleanup
                exit 1
              fi
          else
            dprint 6 "Unable to calculate length of video."
          fi
      fi
  done

cleanup

exit 0