RecoveringVideosFromLostAndFound

From MythTV Official Wiki
Jump to: navigation, search

Introduction

I recently had a problem with a hard drive that was playing up. As a result my JFS partition that was striped across 4 drives decided to drop all my mythtv recordings into "lost+found". These files were placed into the lost+found folder with filenames in the form of "I303105.RCN". This made restoring the files very difficult. By comparing the modified time on the files, with the end time of the recording it was possible (mostly) to determine which file was which recording. Thus i wrote the following script, which scans the "recorded" table (for recordings mythtv thinks it should have), and the modified times on the file, and restores the files accordingly.

How To:

I wrote this script for use on my machine, it will most definitely need changing if you wish to re-use it. DO NOT SIMPLY EXECUTE THIS SCRIPT, READ THROUGH IT AND MAKE NECESSARY CHANGES.

Save this script as lostfiles.sh, and make it executable (chmod u+x lostfiles.sh).

#!/usr/bin/php
<?php

$con = mysql_connect('mysql_server', 'mysql_user', 'mysql_password');

mysql_select_db('mythconverg');

$query = 'SELECT * from recorded order by title';
$result = mysql_query($query);

while ($line = mysql_fetch_array($result, MYSQL_ASSOC)) {
        $chanid = $line["chanid"];
        $dateid = $line["endtime"];
        $startdate = $line["starttime"];
        $startdate = ereg_replace("[^A-Za-z0-9]", "", $startdate );
        $dateid = ereg_replace("[^A-Za-z0-9]", "", $dateid );
        $filename = $chanid."_".$startdate.".mpg";
        echo "\nProgram: ".$line["title"]."-".$line["subtitle"].": \n";
        //echo $filename;
        $year = substr($dateid, 0,4);
        $month = substr($dateid, 4,2);
        $day = substr($dateid, 6,2);
        $hour = substr($dateid, 8,2);
        $minute = substr($dateid, 10,2);
        $second = substr($dateid, 12,2);
        //echo $year."-".$month."-".$day." ".$hour.":".$minute.":".$second."\n";
        $dbtime = mktime($hour, $minute, $second, $month, $day, $year);

        $lostdir = '/myth/lost+found/';
        $mythdir = '/myth/';
        $nummatch = 0;
        if ($handle = opendir($lostdir)) {
                while (false !== ($file = readdir($handle))) {
                        if ($file != "." && $file != "..") {
                                $modtime = stat($lostdir.$file);
                                $modtime = $modtime['mtime'];

                                //echo "DB: ".$dbtime."\tMT: ".$modtime."\n";

                                if (substr($dbtime, 0, 8) == substr($modtime, 0, 8)) {
                                        $nummatch++;
                                        $matchsource = $lostdir.$file;
                                        $matchdest = $mythdir.$filename;
                                        echo "MATCH - Source: $matchsource Dest: $matchdest\n";
                                }

                        }
                }
        }
        if ($nummatch == 1) {
                //only one match, lets fix the file!
                echo "Moving ".$matchsource." to ".$matchdest."\n";
                rename ($matchsource, $matchdest);
        }
        closedir($handle);

}

mysql_free_result($result);

mysql_close($con);

?>

Unfortunately I've not got chance to write this up any further, this script could by much better, feel free to make changes/improvements and post them here.

How To: File Size method

I too have suffered the temporary loss of recordings when a JFS storage volume has broken down.

I've done the work of associating the lost recordings with database entries manually with gedit and oocalc (OpenOffice Spreadsheet).

The basic steps:

cd /path/to/volume/lost+found
ls -l > found.files.txt

Import found.files.txt in to oocalc as plain text, fixed width fields, keeping only the filename and filesize.

Some of the records may be thumbnails so anything smaller than about 10K can likely be disregarded. Sort the table then select and delete the rows of any very small files.

Copy the file size column to your favorite text editor. gedit has all of the features needed to make this next part easy.

You need an SQL select statement that will return all of the records in mythconverg.recorded that match any of the files in lost+found by size, for possibly hundreds of files.

USE mythconverg;
SELECT `basename`,`filesize` FROM `recorded`
WHERE `filesize` = "345678900"
   OR `filesize` = "456789001"
   OR `filesize` = "456789002"
   OR `filesize` = "456789003"
   OR `filesize` = "456789004";

First do a replace statement that replaces all newline marks with

   "\n\tOR `filesize` = "

This will setup the double quotes, a nice indent, and the OR syntax.

Then add the SELECT and WHERE parts at the top of the list, and make sure the semicolon is on the end. Save the resulting SQL query where you can find it easily. i.e. ~/find-by-size.sql

Execute the query:

mysql -A -h dbhost -u mythtv -p mythconverg < ~/find-by-size.sql > ~/found-by-size.txt

Import foundbysize.txty into another sheet, sort it, then copy and paste it into columns to the right of the records imported from found.files.txt. I flip these columns so the file sizes are side by side with the *.mpg or *.nuv file name in the fourth column.

Now you go through the two columns of numbers, cut and paste, aligning all matches.

When you have made your matches move the file size columns out of the way so you can select the filename columns and copy them to a text file.

Do a replace in the text file to add a 'mv' statement to each line. You should also be able to replace the tab character separating the old and new filename with the destination path:

mv I303105.RCN ../1049_20060415095900.mpg

Save the script as ~/found-files.txt and run it:

cd /path/to/volume/lost+found
bash ~/found-files.txt

Caveats:

If you have ever used the mythtranscode --mpeg2 feature to fix dysfunctional PVR-x50 recordings, the database file size may not match the real files size unless you ran the transcode function from mythfrontend afterward.