Project

General

Profile

Recovering from disk failure

Added by Hiro Protagonist over 5 years ago

I recently had a disk failure that wiped out my tvheadend directory. I have some backups, but they're older than I'd like.

I've reinstalled & re-configured TVH without any drama, but I have ~1TB of recordings that I'd like to import into my new setup.

Two questions:

1) If I restore my tvheadend/dvr directory from backup, how can I purge it of entries that have been deleted since the backup was made?

2) How can I import the recordings made since the backup?


Replies (7)

RE: Recovering from disk failure - Added by Joe User over 5 years ago

1) after restoring log files (while tvheadend is NOT running), when you start tvheadend, it will check for the existence of each file. If the file is not found, the recrding will be moved to the "Removed Recordings" tab. From there you can delete the entries. (If you are sure they are really missing...)
2) AFAIK, there is STILL no way to import recordings. If there are not too many, you can attempt to create your own dvr/log files using an existing one as an example and filling in the right data. Or use the API to create the dvr log entries. (in this thread there is an example of using the api: [[https://tvheadend.org/boards/5/topics/34366]])

To find which existing files are missing from the dvr/log files, you can use something like this script (modifying paths as necessary...)

cat /record/find_missing_tvh_logs.sh

#!/bin/bash

# Get list of filenames from existing log files
grep filename /home/hts/.hts/tvheadend/dvr/log/* |cut -d: -f3 > /tmp/log_filenames.txt

# Get list of recordings in recording directory
find /record/tvh -name "*.ts" > /tmp/files.txt

# Search for files in list of existing log files
while  read -r file ; do

    if grep -q "$file" /tmp/log_filenames.txt
    then
    :
    # echo "found" $file
    else
        echo "not found" $file
    fi

done < /tmp/files.txt

RE: Recovering from disk failure - Added by Hiro Protagonist over 5 years ago

Joe User wrote:

2) AFAIK, there is STILL no way to import recordings.

8-( 8-(

Or use the API to create the dvr log entries.

I think I can script up something to do this.

RE: Recovering from disk failure - Added by Hiro Protagonist over 5 years ago

I was lucky & managed to recover my up-to-date dvr/log directory.

I went some way down the path of writing a script to import existing recordings.

This is a simple script that imports a single recording into TVH. It assumes the recordings are
stored in subdirectories per title. More work could be done to sanitise the file path of
unsafe characters

If I hadn't been able to recover my log directory, I would probably have used 'find' to
create a text file containing all the files in my recording directory, gone through the file
manually to clean it up [delete recordings made in the interim etc], then modified this
script to read the file & import the recordings.

Possibly one could create a .json file per recording and manually add extra metadata before
importing, but in my case at least that would have been a lot of work.

tvhimport.sh:

#!/bin/bash
#
# Import recordings into TVHeadend
# Assumes "Make subdirectories per title" is enabled, - if this is not the
# case, the title will have to be extracted from the filename.
#

INFILE=$1

if [ $# -ne 1 ] || [ ! -e "$INFILE" ]; then
 echo "Usage: $0 /full/path/to/file" 
 exit 1
fi

FILE=$(basename $INFILE)
RECPATH=$(dirname $INFILE)
START=$(stat --format=%X $INFILE)
END=$(stat --format=%Y $INFILE)
# Extract title from last level of RECPATH
TITLE=$(basename $RECPATH | sed -e 's/-/ /g'  -e 's/_/ /g')

cat << EOF > /tmp/import.json
conf={
    "enabled": true,
    "start": $START,
    "stop":  $END,
    "channelname": "local file",
    "title": {
        "eng": "$TITLE" 
    },
    "subtitle": {
        "eng": "filename: $FILE" 
    },
    "description": {
        "eng": "" 
    },
    "comment": "added by $0",
    "files": [
        {
            "filename": "$INFILE" 
        }
    ]
}
EOF

echo "Sending create command for \"$TITLE\"" 
curl -q --data @/tmp/import.json 'http://admin:admin@localhost:9981/api/dvr/entry/create'
exit 0

RE: Recovering from disk failure - Added by Hiro Protagonist over 5 years ago

One more lesson I've learned from this - recovering from disk failure is a lot easier if you have access to your log files.
It makes sense to back your dvr/log directory up to the same media where your recordings are stored [if you lose that, you're
completely hosed].

rsync -avih --delete /path/to/.hts/tvheadend/dvr/log /path/to/pvr

RE: Recovering from disk failure - Added by Hiro Protagonist over 5 years ago

I've done a bit more work on importing:

Extracting the start and end times from the filesystem won't give correct results if you're post-processing.
This version of tvhimport.sh calculates a duration from the file times, and if that's too short
it uses ffprobe to get the duration of the recording and calculates approximately correct start
and end times from that. The duration is now included in the import data.

Obviously you'll need to ensure you have ffprobe installed for this to be useful.

cat tvhimport.sh

#!/bin/bash
#
# Import recordings into TVHeadend
# Assumes "Make subdirectories per title" is enabled, - if this is not the
# case, the title will have to be extracted from the filename.
#

INFILE=$1

if [ $# -ne 1 ] || [ ! -e "$INFILE" ]; then
 echo "Usage: $0 /full/path/to/file" 
 exit 1
fi

duration ()
{
        echo $(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $1 2> /dev/null | cut -d '.' -f 1)
}

FILE=$(basename $INFILE)
RECPATH=$(dirname $INFILE)
START=$(stat --format=%X $INFILE)
END=$(stat --format=%Y $INFILE)
let DUR=END-START
# If duration is too short, probe the file
if [ $DUR -lt 1800 ]; then
        DUR=$(duration $INFILE)
        END=$START
        let START=END-DUR
fi
# Extract title from last level of RECPATH
TITLE=$(basename $RECPATH | sed -e 's/-/ /g'  -e 's/_/ /g')
cat << EOF > /tmp/import.json
conf={
    "enabled": true,
    "start": $START,
    "stop":  $END,
    "channelname": "local file",
    "duration" : $DUR,
    "title": {
        "eng": "$TITLE" 
    },
    "subtitle": {
        "eng": "filename: $FILE" 
    },
    "description": {
        "eng": "" 
    },
    "comment": "added by $(basename $0)",
    "files": [
        {
            "filename": "$INFILE" 
        }
    ]
}
EOF

echo "Sending create command for \"$TITLE\"" 
curl -q --data @/tmp/import.json 'http://admin:secret@localhost:9981/api/dvr/entry/create'
echo
exit 0

This script finds any .ts or .mkv files in your recording dir, and imports them into
tvheadend if they're not found in the tvh logs. If you run it with any arguments at all it
will just print out the files it finds.

cat tvh_import_missing.sh

#!/bin/bash
#
# Usage - call with any argument to display files not found in TVH logs
# tvh_import_missing test
#
# Call with no args to import the files into TVH
#
# Modify to suit
HOME=/home/pi/.hts
BIN=/usr/local/bin
RECORDINGS=/var/spool/pvr/

if [ $# -eq 0 ]; then
        COMMAND=$BIN/tvhimport.sh
else
        COMMAND=echo
        echo "Running in test mode" 
fi

echo "Scanning logs and recordings" 
# Get list of filenames from existing log files
grep filename $HOME/tvheadend/dvr/log/* | cut -d: -f3 > /tmp/log_filenames.txt

# Get list of recordings in recording directory
find /var/spool/pvr/ -name "*.ts" -o -name "*.mkv" > /tmp/files.txt

echo "Checking for recordings missing from logs" 
# Search for files in list of existing log files
while  read -r file ; do

    if ! grep -q "$file" /tmp/log_filenames.txt
    then
        $COMMAND "$file" 
    fi

done < /tmp/files.txt

RE: Recovering from disk failure - Added by Hiro Protagonist over 5 years ago

Sometimes ffprobe is unable to return a duration and you get a non-numeric value as a result.
This can be handled by using a default value if the result isn't numeric:

duration ()
{
        VALUE=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $1 2> /dev/null | cut -d '.' -f 1)
        if ! let $VALUE 2>/dev/null
        then
                # Duration from ffprobe wasn't valid
                VALUE=3600
        fi
        echo $VALUE
}

RE: Recovering from disk failure - Added by Joe User over 5 years ago

Although old, the python scripts in this thread may be helpful.
[[https://tvheadend.org/boards/5/topics/9863?r=10862]]

    (1-7/7)